不写一行代码如何对整个系统产生影响

376 阅读9分钟

PPT架构师

大多程序员心中都有一个梦,成为一名优秀的架构师,带领团队攻克一个又一个技术难关。可现实中也会有一些架构师被吐槽,不写一行代码,就会画画图,写PPT,这真能给项目带来帮助吗。以下我们就来讨论,如何不写一行代码,让你的设计对整个系统产生影响而不是沦为一纸无用的PPT。

什么是架构

拆个服务就叫架构吗?

在笔者参加校招时,在简历上祭出自己的电商系统,里面分了好多模块,用户模块,商品模块,订单模块等等等。然后我各种吹嘘自己的架构设计思想,结果面试官一句吐槽让我懵了,拆个服务就叫架构吗。当然这次面试我失败了,从那以后,我也有长达两年的时间不敢说自己懂架构。

什么时候不需要架构

关于什么是架构,网上不同平台有不同的解释,至今也没人能够说清楚,软件架构到底是什么,什么时候需要用到软件架构。笔者参加过公司一名架构师的分享,他以逆向思维的角度,提出了一个问题,什么时候不需要架构。答案是,一个人的时候。

架构是一群人写代码

当你一个人写代码的时候,设计的是你,开发的是你,可以随心所欲想怎么写怎么写。这时候如果给你个帮手,那你们可以分工合作,比如你写SQL,他写接口。假如现在给你10个人去做一个系统呢,你会发现组织起来不是那么容易的。他们的理解能力可能各不相同,你叫他往东,他可能理解为往西。而且你还要考虑上级会不会对你有制约(时间,金钱,权力),下级会不会听你话。现在还不是麻烦的时候,我们把人员增加到100倍,1000人,这时你会发现,如果你搞不好,这群人非但不是你的帮手,反而是一群累赘。

现实转换虚拟

面临问题

现实很残酷,你面临的问题是,带领无组织的1000个人进行开发,就算你的个人能力很强很突出。但是,你的设计别人不一定看得懂,看得懂他也不一定会照着做,照着做也不一定能保证质量。而你,碰到某个人具体的问题,又不能简单粗暴地责怪他,因为这可能不是个案,并不能从根本上解决问题。

问题拆分

按照正常逻辑,碰到一个大问题都会将他拆解为若干个小问题。1000个人的团队,也可以进行拆分,拆分的方式大致有两种,垂直拆分,水平拆分。

垂直拆分

1000人的团队可以按照职能进行拆分。比如,前端,后台,安卓,测试,运维。这种结构的好处是,可以让同样技术栈的同学充分地进行沟通交流。弊端是,当要组织一个项目的时候,需要跨部门协调的成本比较大。部门内部各人员由于分配到不同项目组,互相之间其实也不需要沟通交流,反而和其他部门的人沟通的时间会比较多。

水平拆分

1000人的团队可以按照项目来进行划分,做哪个项目就在哪个部门,然后由项目经理统一去带领一个团队。这样的好处是,资源可以充分为项目进行服务,成员目标一致。缺点是项目的好坏会影响到部门的每一个人,比如有些部门的人很闲,有些部门的人很忙,造成资源浪费。

虚拟转换现实

上述的划分方式都没有好坏之分,可以根据团队的现状和想要达到的目标去进行抉择。假设说我们选择了第二种水平拆分的方式。这时,就要将虚拟的设计转换为现实。比如说,我可以:

  • 让同个项目部门的成员都坐在独立的办公室
  • 让同个项目部门的成员都在同一层楼办公
  • 让同个项目部门的成员都在独立的公司园区(独立结算)

这样从物理的角度就可以体现出组织结构的设计。但实际上我又并不关心它是放同一个办公室或者同一个层,因为物理结构并不会改变逻辑的关系。但是如果说不根据逻辑的设计划分出物理的结构,那你的设计就真的成为了一张普通的PPT。可以想像一下,你们部门的人全都分散到各个办公室去坐,还会觉得这是一个部门吗?

小结

通过现实转换虚拟,我们可以根据团队目前的现状和面临的问题,提出针对性的设计解决方案。通过虚拟转换现实,又可以将这些方案真实地落地。

实际案例

假设现在你和你的团队两个人做学校账号管理系统,负责维护各个学校学生的基础用户信息。一个学生属于一个班级,一个班级属于一个学院。

功能如下:

  • 查看班级里的所有学生
  • 查看学生所在的班级
  • 查看班级所在的学院

虽然只有三个需求,但是你有两个人嘛,所以还是要考虑一下如何分工的。比如说,你们可以一个人负责写接口和逻辑controller和service,一个人负责写sql(数据库设计,sql)。然后采用MVC的三层垂直架构风格进行开发。三层架构规定,只能controller调用service,service调用dao。

写着写着你会发现,即使是一个很小的需求,都要和另外一个同学商量,等他的接口,好麻烦哦。能不能我们每个人负责一个模块呢。比如我将系统分为用户模块,组织模块。依赖关系是用户模块依赖组织模块。于是你们就继续采用MVC三层开干了。

直到有一天发现,写用户模块的同学直接调用组织模块的dao接口,这时你就说他了,不要调用其他模块的细节,用户模块应该依赖组织模块的service接口而不能直接调用dao。他一脸无奈地望着你,可是我遵循了MVC模式啊,service调用dao,有什么问题吗。

诚然,你设计的架构是分成两个模块,但是,实际代码中,你的partner看到的还是MVC,也就是说,你的设计并没有在真实的代码中得到相应的体现。所以别人没办法理解是很正常的事情。在逻辑上,你们采用水平划分的方式进行分工,可是在实际上,你们采用的物理结构还是垂直结构。

方案一

改成这样可以吗?在service层分两个包,用户模块,组织模块。还是会有问题,因为,不清楚到底什么dao是可以让unit调用,什么dao可以让user调用。上下两层并没有分包。

方案二

每个模块一个包,包下面写controller,service,dao。好像确实可以从代码结构看出来逻辑的设计,系统分成两个模块,模块的物理表现是分包。它的好处就是当我要从分包拓展到分服务的适合,只需要把模块的包都挪走就好了。但是它其实还是有个弊端,不同模块之间的沟通方式没有确定。

方案三

方案三,每个模块一个包,同时定义了外部的接口,模块之间的调用只能通过接口,不能去引用实现。这样一来,你的partner就可以从暴露的服务里选择他想要的服务去使用,而不会去看你实现的细节了。

康威定律

  1. 划分成MVC三层垂直架构,意味着,沟通方式是负责写service层的同学去和写dao层的同学沟通,两个人都要去了解所有的需求。优点是,可能其中某个同学擅长优化sql会对系统性能有很大的帮助。
  2. 按模块分包,沟通方式是包内部需求自治,对于上下文交互部分,根据模块的依赖关系暴露服务。比如做组织模块的小伙子不需要了解用户模块的领域知识,甚至不用关心这个模块存不存在。而用户模块,只有需要用到组织相关信息的时候,才会寻求组织模块的服务进行请求。

为什么我们要花费那么多的时间去调整结构呢。因为康威定律第一条告诉我们,组织沟通方式会通过系统设计表达出来。 假如一个10人的团队不进行结构划分,他们在同一片区域工作可能会相互影响。沟通成本 = 10 * (10 - 1) / 2 = 45。假如现在你将10人划分为5人一组。一组沟通成本 = 5 * (5 - 1) / 2 = 10,两个组2 * 10 = 20。他可以大量的节省沟通的成本,还能够从结构上约束团队的沟通方式,从而让混乱的系统变得有序。

什么是架构

任何的设计都有好处和坏处,比如单体和SOA,很多人只知道SOA好,而架构师知道什么时候用单体什么时候用SOA。很多人知道MVC,而架构师知道什么时候用MVC。 架构是为了解决真实的问题,在引入新技术的时候,可以多考虑,为什么我要用这个,不用行不行,有没其他可选方案。而不是“手里拿着锤子,满眼都是钉子”。

如上例子,你会选择将用户模块和组织模块分成两个独立的服务吗?为什么?