从架构可视化入门到抽象坏味道

抽象的坏味道

上文说过,C4说穿了就是几个东西:关系-线、元素-方块和角色(角色不过是图形不同的方块)、关系表述-线上的文字、元素的描述-方块里的文字,虚线框(如前文所说,在C4里面虚线框的表达力被极大的限制了)。

这些东西一点都不新,我们自己随便找个白板,无非也是用这几个东西来表达架构,它的优点在于引进了一些分层,帮助我们理清思路、也有利于可视化给别人看。

换言之,C4不能帮你做好架构设计,但是它能暴露出你设计中的问题,以便于被自己或其他人纠正。

可视化的威力就在这里,但根据我的经验,即便你用上了C4也不见得就能表达清楚,不过好消息是,我们终于可以聊一些高级的表达问题了。

可视化之后,我们能看到自己的表达问题,大概的问题有两个:抽象层次和抽象粒度。这个是表达方面永恒的问题,也就是软件设计永恒的问题,没有万灵丹,但是用上了可视化手段之后还是有机会让生活更美好一点的。

这两个问题可能太抽象了,不容易意识到,那我们可以看图,从图上的具体表现来发现坏味道。一般会有几个迹象表明我们有可视化的坏味道:

  1. 一张图上过分密密麻麻的线
  2. 一张图上太过多元素(也就是方块)
  3. 一张图上太少的元素,比如角色特别少
  4. 每个图上文字表达不契合,有的太泛泛,有的太细节
  5. 无限制的画更多张图,基本上也就失去了使用图形化表达的意义

那么对应的手段就有:

合成更大的元素

当我们意识到有密密麻麻的线、太多的元素,闻到这个味道的时候,可以考虑是不是该把里面的一些元素合成更大的元素了。Component可以合成Container,Container可以合成System,这样就会分成更多的图,每张图就变得没那么多线和元素了。

紧接着会面临下一个问题:怎么合成一个更大的系统,Container是明确的,所以Component合成Container不是问题,问题是Container怎么合成一个系统,为什么是这些Container合成这个系统,而不是另外几个?或者多加几个、减几个?

这个问题没有标准答案,但是有一些其他的框架可以提供一些思考的维度。

比如可以结合akf扩展立方来思考。

(akf扩展立方)

X轴就比较容易,一方面从容器本身的描述来看设计上是不是支持横向复制的,另一方面则是看部署图。

Z轴相对难一些,只是比较偏技术。比如当技术上有性能瓶颈,则需要注意这一个维度,有时不得不搞出一些特殊的容器出来,有时已经存在这些容器了,他们可能单独属于一个系统(类似于大数据分析的系统),或者一个系统的某一个局部(这就是前面提到的虚线框表达力被限制的地方)。

Y轴给人的感觉是最容易操作的,但实际上却是最难做好的,Y轴的背后是业务,往往我们觉得就按业务切成多张图就好了。这种想法就表现出我们往往意识不到业务的真正难度,于是总在这里出问题。如果你能跨过这个心理障碍,决定去认真做一下,那么也有一些工具可以帮助我们做好。

(领域模型与架构设计)

最经典的工具组合就是求助于DDD,结合康威定律和步速,考虑维护的团队、使用的角色、变化的节奏,这块展开就复杂了,有机会再聊。

这里说一个最简单的做法:按照用户角色分。同一种角色,由于其在公司里的职能、职责都是已经被定好的,天然在系统上就有一种隔离性。比如招聘专员、会计、出纳,他们使用的系统肯定是不一样。

但说简单,其实也不简单。我见过一些图,上面的角色只有两个,内部用户和外部用户。而另一些图,细化到了个人的级别,或者把职级都放上去了。所以无论再简单的原则,最后都会掉进抽象的坑。

画一些共识图来忽略掉一些通用的元素

有时候合成了更大的元素,元素依然很多,线条依然很密。画多张图也不够切分的。这个时候我们可以求助于共识。

人与人交流,如果已经有一些共识存在就可以少废很多话,共识多到一定程度只需要确认一个眼神就完成交流了。所以毫无疑问,做好共识管理,可以大幅简化我们的架构图。

所以在我们做架构可视化的时候,经常会先画一个技术共识图,比如以一个能力建设的数字平台为例,我们就画了一个下面这样的技术共识图:

(技术共识图)

在后面画具体的图时,就可以省略掉一些共识的元素,像nginx和数据库就没有了,可以更关注在业务上,而不是技术上。

通过制定主题,限制文字的抽象层次

其实上面的技术共识图就是类似的做法,只是用于技术方面,如果用于业务方面,我们可以用一些抽象的名词或动词来代替一类业务,比如下图:

(数字平台系统景观图)

上图是一个系统景观图。当前这个主题是希望人们能一眼看清楚这个系统里面的相关角色都在使用什么系统,他们关注什么,职责是什么。至于具体学什么,怎么学的,都不是那么重要。所以我们就用学习一词代表了一系列的业务。

当主题确定的时候,很多纷杂的信息就没有了。一定要克制住自己试图在一张图上表达足够多信息的冲动。

只画重要的图,剩下的交流的时候再画

除了像上面说的,不要试图在一张图上给他足够的信息。同时也不要试图把所有的信息都表达出来。

绝大多数的图可能只在交流具体业务的时候才画,推荐使用动态图。

总结

即便有了C4这么,好用的可视化工具。我们依然会看到,自己会掉进抽象的坑。所以在使用的时候一定要注意坏味道,经常自查是不是犯了抽象层次和抽象力度的错,才能做好可视化。这件事上,没有谁能幸免,所以要时常自省,与诸君共勉。


更多精彩洞见,请关注微信公众号:ThoughtWorks洞见

Share

可视化架构设计——C4介绍

好多年前,同事徐昊说过的一句话给了我很大启发,他说“纸上的不是架构,每个人脑子里的才是”。这句话告诉我们,即便是天天工作在一个团队里的人,对架构的认识也可能是不一样的。每个人嘴上说的是类似的话,但心里想象的画面仍然是不一样的。在多年的工作中,我越来越认可这句话所揭示出的道理。软件开发是一个团队协作的工作,混乱的理解会造成架构的无意义腐化、技术债的无意识积累、维护成本的无价值上升。

最近听到一句话,“那些精妙的方案之所以落不了地,是因为没有在设计上兼容人类的愚蠢”。话糙理不糙,虽然最终人们选择的方案的思想都是在十年前甚至几十年前就已经存在的,然而在技术升级到足以“兼容”人类的愚蠢之前,这些思想只能在学术的故纸堆里睡大觉。当然话糙确实也会有一个问题,将一个思想性问题转化成了情绪性问题。人们容易把一些糟心的事情归因到人类的愚蠢,在宣泄完不满情绪后就停止思考了。作为知识工作者,我们的思维不能停步,我们需要思考到底人类有哪些愚蠢,分别用什么方法去避免或者“兼容”。

可以肯定彼此明明对自己开发的软件有不一样的认识却天天在一起讨论问题并试图把软件做好是一件愚蠢的事情,为了兼容这种愚蠢我们需要采用可视化的方法。

为什么需要可视化呢,主要还是语言不靠谱。人类语言真的是太随意了,只要你想,你可以说你见过一个方形的圆,并为此与别人辩论。但是无论如何你也画不出来一个方形的圆,这就是我们需要可视化的原因。

今天我们介绍一个工具,叫做C4 model,这是我近几年见到的一个比较难得跟我的认知有大量共鸣的工具。

该工具的作者在多年的咨询中经常发现,很多个人画出来的架构图都是不一样的,但也不是说谁画错了,而是每个人的抽象层次不一样。抽象层次这种东西,说起来好像存在,但真要说清楚还挺难,于是作者类比地图,提出了缩放的概念。(两年前我在教学生的时候提过同样的概念)如下图:

上面的四张地图就是想说明,当我们看待真实世界的“架构图”时候,也是要不停的缩放,在每一个层次刻意忽略一些细节才能表达好当前抽象层次的信息。所以他类比着把架构也提出了四个抽象层次:

从上到下依次是系统System、容器Container、组件Component和代码Code。(咦,那为什么叫C4呢,因为系统的图叫System Context,系统上下文图。为了凑四个C也是够拼的。)

基于这四个层次的抽象,C4模型由4张核心图和3张附属图组成,分别用于描述不同的场景,下面我们一一介绍一下。

四张核心图

系统上下文图

如上图所示,这个图表达的是你所开发的系统和它的用户以及它所依赖的系统之间的关系。从这个图上我们已经看出来C4图形的几个关键图形:

C4说穿了就是几个要素:关系——带箭头的线、元素——方块和角色、关系描述——线上的文字、元素的描述——方块和角色里的文字、元素的标记——方块和角色的颜色、虚线框(在C4里面虚线框的表达力被极大的限制了,我觉得可以给虚线框更大的扩展空间)。

通过在不同的抽象层次上,重新定义方块和虚线框的含义来将我们的表达限制在一个抽象层次上,从而避免在表达的时候产生抽象层次混乱的问题。

那么在系统上下文图里,方块指代的是软件系统,蓝色表示我们聚焦的系统,也就是我开发的系统(也可能是我分析的系统,取决于我是谁),灰色表示我们直接依赖的系统,虚线框表示的是企业的边界。通过这些图形化的元素表达我们可以看出来各个系统彼此之间的关系。

容器图

当我们放大一个系统,就会看到容器,如上图所示,C4模型认为系统是由容器组成的。我个人认为,容器是C4模型最大的创举,尤其是在这个单体架构快速崩塌的时代。所谓容器,既不是Docker的容器,也不是JavaEE里的容器,而是借用了进程模型,代指有自己独立进程空间的一种存在。不管是在服务器上的单独进程空间,还是在浏览器里的单独进程空间,只要是单独的进程空间就可以看作一个容器。当然如果你容器化做得好,Docker的Container和这个Container可以一一对应。有了这个概念的存在我们就可以更清晰的去表达我们的架构,而不是总是用一些模糊的东西。

组件图

当我们放大一个容器,我们就会看到组件,如上图所示。组件在这里面很好的把接口和它的实现类打包成一个概念来表达关系。我个人觉得有时候一些存在于代码中,但又不是接口的某些东西,比如Service、Controller、Repository之类也可以用组件图来表达,如果你学了一些没有明确抽象层次的架构知识或者一些单体时代的遗留经验的时候,你可以画出来一些组件图,来印证自己的理解,如下图,是我画的自己对DDD战术设计里面的一些概念的理解:

比起模糊的堆砌在一起的文字,这种表达要清晰的很多,哪怕我的理解是不对的,也容易指出和讨论。

代码图

代码图没什么可说的,就是UML里的类图之类很细节的图。一般是不画的,都是代码生成出来。除非非常重要的且还没有写出代码的组件才画代码图。

以上就是C4的核心图,我们可以看到四种不同的抽象层次的定义会让我们更容易固定住我们讨论的层次,这点上我觉得C4是非常有价值的。

三张扩展图

架构设计设计要考虑的维度很多,仅四张核心图是不够的,所以作者又提供了三张扩展图,可以让我们关注更多的维度。

系统景观图

看得出来,系统景观图是比上下文图更丰富的系统级别的表达。不像上下文图只关注聚焦系统和它的直接关系,连一些间接相关的系统都会标示出来,那些系统的用户以及用户之间的关系也会标示出来,只是内部的用户会用灰色标记。

这个图有什么用呢?在我们分析一个企业的时候,我们需要一个工具帮助我们把一家公司给挖个底掉,做到完全穷尽,才能看到企业的全景图,从而理解局部的正确定位以做好局部设计为全局优化服务。之前我试过以四色建模的红卡、事件风暴的事件两种工具来教人掌握这种能力,一般来说,程序员学员都无法快速掌握这种顺藤摸瓜的分析技巧,毕竟跟程序员的思维还是有些差异的。但是用了系统景观图之后,学员就毫不费力的掌握了这种分析能力,所以我后来都是用这个图来教程序员探索企业的数字化全景图,效果极好,推荐给大家。

动态图

动态图不同于其他表达静态关系的图,它是用来表达动态关系的,也就是不同的元素之间是如何调用来完成一个业务的。所以动态图不仅仅适用于一个层面上,它在系统级、容器级和组件级都可以画,表达的目标是不一样的。

我之前曾经写过名为《像机器一样思考》的一系列文章,在文中也发明了类似的图,不同于本文中关系线上标注的是调用的方法、函数,我更关注的是数据,使用效果也很好。

什么时候用动态图呢?举个小例子,我之前做一个内部的小系统,团队中只有一个有经验的工程师带着十多个毕业生,我便要求他们在开始工作之前都画出动态图来,交由有经验的工程师去评估他们的思路是否正确,如果有问题,就在开始之前就扼杀掉烂设计。不管是毕业生还是初级工程师,改代码的能力都比写代码的能力要差很多,所以将烂设计扼杀在实现之前还是有帮助的。

部署图

前面的几张图都是站在开发的角度思考,但是一个没有充分思考过部署的架构很容易变成一个运维的灾难。所以作者提供了一个部署图。考虑到DevOps运动如火如荼,这个图可以变成很好的Dev和Ops之间沟通的桥梁。我们在实操中发现,Dev和Ops关注点的不同、语言的不一致,在这张图上表现得非常清楚。

图上最大的的实线框不同于虚线框,它表达的是数据中心,当你开始考虑异地载备的时候它就有了意义。数据的同步、实例的数量都会影响部署图的内容。部署图基本都是容器级的,它能很好的表达出来容器到底部署了几个实例,部署在什么样的操作系统上,一个节点部署了几个容器之类,我们在实际使用中,发现需要考虑的信息太多,自己就抽象出了类似于亚马逊上实例规格的Small、Large之类的术语来表达机器配置,增进了开发和运维之间的交流准确性。

为什么C4值得推荐

够直观,对于程序员来说容易理解,容易使用。

我们在开头的时候说过,只有每个人脑子里的才是架构图,如果我们使用一个本身就很难达成一致理解的工具,那成员就会陷入理解的死循环。经过尝试教授不同工具,发现C4模型是最容易理解、最容易使用的工具。可能它的概念是复用了程序员已有的一些认知模型,程序员在学习后都可以迅速的使用起来,并问出一些高质量的问题。

总结

在思维的世界里,我们都是盲人,很多东西我们以为自己知道,实际上画出来之后,才发现很多东西没想到,或者想的是乱的,同时别人也才可以给我们反馈。

有了上面的这个工具,我们就可以开始可视化的架构设计之路了,但路上还有一个心魔需要战胜。在我们的文化里,出错是一件很丢人的事情,所以我们喜欢用一些模糊的描述避免被别人挑战,而可视化是让我们精确的描述出自己的理解,来欢迎别人的挑战。这一个坎不太容易跨过去,但是一旦跨过去、大家形成正向的互动之后,我们的进步速度会变得很快,从而把封闭的人远远的甩在后面,获得组织级的成长推力。我自己就在跟别人的交流之后获得了更深入的洞见,本文已经分享了一些,还有一些内容后续再跟大家分享。


注:文中图片均来自:https://c4model.com/

更多精彩洞见,请关注微信公众号:ThoughtWorks洞见

Share

以用户为中心的软件开发

问题

今天这个时代迭代开发已经成为常识,甚至政治正确。随便谁就能给你扯两句mvp。敏捷也从一个开发的,名词变成了管理名词。迭代,测试,反馈,名词满天飞。

人人都在说这些术语,仿佛他们真的就懂怎么做软件了。起码,觉得自己真的懂怎么创新了。然而经不起细聊,一旦深入下去聊一个mvp,聊聊他的迭代计划。就会发现露馅了张嘴闭嘴,谈的都是功能。这个迭代要交付几个功能,这个mvp多了什么功能?他的竞争对手都有哪些功能?却很少听到用户人人都在喊,以用户为中心。口号喊得震天响,但你看他们的行为模式,他们的语言,并没有用户的身影。

我时常觉得这个事情不太对劲。但是也没有想到更好的方法。敏捷中使用的故事卡比功能的视角要好一点。因为在故事卡里,你要写下用户的价值。但是,我一直也不知道这个价值是从哪儿来的。是先开枪后画靶子我们想做某个功能了,所以硬按一些价值的。还是真的存在的,价值的单位应该是什么呢?没有单位的东西就无法管理。无法管理,也就无法优化。我们交付的价值是越来越多吗?还是交付的不如以前了?用什么来判断?

回答不了这些问题,不管输赢都是有点不明不白的。这些问题的核心问题就是价值的单位应该是什么?怎么算一个价值?直到我看了,我们公司设计团队的一个框架MERLIN。又在《创新的窘境》,作者的新书《与运气竞争》里,看到了理论依据。这个问题在我这里才算是告一段落。我明白了,以用户为中心的软件开发大概应该怎么做。

方法核心

如果我们想以用户为中心进行软件开发,那么知行要合一,我们的分析方法应该是围绕着用户展开的。

这个方向倒是不新鲜,我们在inception的时候做用需求分析时我们的方法就是围绕着用户展开的。一个典型的分析过程,如下图所示:

​ 我们会在上面画一条轴,标示出用户旅途。这是用户在使用软件的时候的,他的一个全过程。然后在对应的时间点上,标记出,我们的功能。这样我们的功能就不是平白出来的。每一个都联系了用户价值。在ThoughtWorks,我们可能标记的是用户故事,相对于功能,用户故事,首先就是要写出价值。

但是这个图还是不够给力。首先,从用户旅途上的点,到功能的映射简直是个magic move。并不能很好的传递为什么是这样的一个功能,而不是别的功能?毕竟实现一个用户的价值方法有很多。后续在执行的过程当中,难免会僵化行事。 其次,上面的旅途,还可以再抽象和封装。简言之,旅途本身也应该是有抽象层次的。一个旅途上的一个点,可能也是一段新的旅途。

一个更系统的做法是这样的,首先做服务设计:

​ 系统化的分析用户的行为,过程中与企业有哪些触点,在这些触点上用户“雇佣”企业的产品到底是来做什么的,也就是动机。

然后将这些点再进一步细化,采用故事的模式:

​ 图上的一行会讲一个故事,就像电影分镜或者漫画一样,来表达用户使用的故事,真正的故事,而不是用户故事那种东西,我们叫这个东西故事板。 在故事板上,我们描绘了一个故事,这个故事里,用户获得了一种体验。一个故事对应一个体验。在基本需求都已经得到满足的今天,体验是新的最有价值的事情,以体验为中心才是以用户为中心。故事板恰好给了我们一个非常符合人类认知习惯的方式来描述什么是一个体验。也就回答了开头的问题,什么是价值的单位。

​ ​当我们定义出了价值的单位,就可以从这一单位的价值里面映射出故事卡,来进行开发过程的管理。

​ ​这里就是我们的重点,我们将来交付的软件、交付的服务、我们交付的一个MVP本质上是交付给了用户一组体验。MVP的迭代则应该是更多的体验或某些旧体验的升级(也就是同一个动机,换了一个故事来满足)。

这就是以用户为中心的软件开发的核心。最终我们把用户的价值很好的表达了出来,并且找到了用户体验的基本单位——故事板,由于故事板也可以转化为用户故事,结合早已经存在的敏捷开发方法,也就可以对体验的交付进行度量和管理。达到真正的以用户为中心进行软件开发。


更多精彩洞见,请关注微信公众号:思特沃克

Share

复用的着相

着相是佛家用语,指的是执着于外相偏离了本质。

仙剑奇侠传中有一个故事。讲的是一个成精了的佛珠。想要让更多的人向佛,于是施法,让这些人失去了记忆,只想一心礼佛。使人向佛,本来是好事,但强人所难,脱离了本质,便是着了相,也可以说反而是入了魔。

这个小故事告诉我们,在认知的世界里,我们很容易被表象所欺骗,忽略了本质。为此,佛家发明了这么一个名词来专门指出这种现象。

复用也是一样。复用本来是通过消除重复的方式。得到一系列可以复用的组件。从而在未来的开发工作中,更快速的响应需求变化,也就是所谓的提升响应力。

然而很多复用的结果,会造成代码是变少了,改起来却更难了。复用是增加了,可读性却下降了。考虑到软件开发是一个团队协作的工作,而我们这个行业的离职率又能到百分之二十之多。难以学习的代码确实是难以维护的,尽管你可以抱怨接手的人无能,但总之是降低了响应力,也就违背了复用的本质。

什么情况下会出现这样的场景呢?主要是因为视角的单一,只从自己单一的视角看到了重复而不是在做全局优化。这个说法可能稍微有些抽象,那我说几个相对具体的情况。

当我们只关注功能视角的时候

需求有很多的描述视角,可以只在功能角度描述,比如“网站要有任务卡,任务卡上有文字版学习内容,视频讲解、也有作业题。”也可以加入业务视角,比如“学生要报名特训营,才能参加特训营。学生进入特训营后,就看到了任务卡列表。学生在任务卡上阅读学习资料,阅读完学习资料后做题来验证他是否学到,做完后提交交由助教审阅。”当我们只看功能视角的时候,可能会忽视业务上的不同,变的在功能角度过分抽象,最后当业务变化的时候,反而响应速度比较弱。

一个简单的后台,我们看起来所有东西长得都一样,不过是列表页面,添加页面修改页面,再加点儿删除什么的功能。说穿了都是crud,干脆我把这事弄成一一个组件好了,每个页面只需要简单配置一下,就可以出来自己的一套增删改查页面。

这种视角完全没有考虑到,不同的实体,它们其实所在的业务是不一样的,关心它们的人也是不一样的。最后,彼此的演化方向也总会出现一些不同,你把它定义成一种东西,对于我每做一个修改,都要背负着其他所有实体的特异性。于是就逐渐拖慢了我改变的速度,降低了响应能力。

无谓的自动化

有追求的程序员一定会考虑提升工作效率,通过一些自动化的手段来缩短流程,提高效率。不过有时候,这种追求也会有害。

在我们的系统里有一个面包屑功能,就是典型的“页面A / 页面B / 页面C”那种面包屑。团队成员提出,一个个页面写面包屑好烦啊,干脆做一个根据URL生成面包屑的功能吧。乍一看好像提高了效率,但实际上URL上的名词和你想显示在面包屑上的名字是可能出现不同的。

比如在我们的场景里,我们提供一个任务卡的预览功能,你的面包屑可能是“xx后台 / xx 训练营管理界面 / xx卡预览”,而学生正式使用任务卡的时候,他可能是 “ 学习中心 / xx 训练营 / xx卡 ”。而他们的url里可能都会出现’/programs/$pid/tasks/$tid’。同样的program、task翻译出来的文字完全不同。你为了支持这点不同,又要扩展一些额外功能来做这种区分,做来做去,可能还不如直接写来的方便,至多抽几个常量来简单的消除一下重复。

当我们只从代码上看重复性的时候

这个我就不举例子了,其实很多犯这个错误的人都是重构的支持者,不过学艺不太精。因为如果你仔细看的话,重构里好多怀味道都有一个跟他对立的怀味道,比如发散式变化和霰弹式修改。如果我们只看代码就会违背复用的本质——更好的响应变化。

这个跟我说的第一个场景,只关注功能视角是类似的问题,这个可能更具象一点,只关注代码。

无视上下文的时候

这个可以看作是只有功能视角的一种情况,很多功能我们觉得有重复性,提升成一个概念,然而其实根本是两个东西,他们只是刚好叫一个名字。

比如过去很多软件里,是有一个统一的用户组概念,不管你在哪个业务上下文里,你都需要扩展这个用户组的概念来管理用户的权限。这个带来的结果就是用户组变得越来越臃肿,每次修改都要改一下别的组的功能。在我们的网校数字平台里,学生学习有学习小组,老师出题有出题小组,这两个小组业务完全不一样,这个时候如果都用统一的用户组来管理的话,那就势必会造成无谓的耦合,损害响应力。

这些故事告诉我们,我们不是在真空里去做复用。我们做的软件都是有它的商业目的。我们的工程实践也都是为商业目的服务的。当我们说tech@core的时候,让我们说技术就是业务的时候。诚然,他给技术人员带来了更多的权利,然而权利越大,责任也越大。技术人员也需要跳出技术,具备更多的业务视角和体验视角。而不仅仅是沉浸在技术得自high当中。才能真正的发挥出各种实践的价值。


更多精彩洞见,请关注微信公众号:思特沃克

Share

软件开发工作的第一现场

我的同事王健最近写了一篇文章——《从汽车贴膜看专业团队》。看了之后感触良多,特别是文中提到的现场管理和全功能团队两点。

我有一个观点,说到专业性,传统行业比我们IT行业要强得多。从这篇文章可以看出,不管是管理人员的现场管理能力,还是全功能团队中一线人员的全栈能力,传统行业都比我们要强一些。相信有人会有些不服,不管什么现场管理,全功能团队我们也在做呀。

说的没有错,但是,在IT行业里还真不容易找到这么专业的一个团队。而在传统行业里,这种水平的一个团队已经越来越常见了。这是为什么呢?按说大家都是人,通常来讲,IT行业的人能力素质不是还高一点吗?在我们这个行业中,专业团队不是应该更常见吗?虽然我们不一定要比你强,但是也不会比你弱得这么明显啊。

当然,一方面是由于我们这个行业的工作比较复杂,不容易做到全栈,但我觉得更重要的是,IT行业属于知识工作,知识工作者的现场非常不明显,极难做到现场管理。

我们IT行业的管理者,不管是项目经理,产品经理,还是技术领导者,大家也基本都和团队坐在一起。但是坐在一起,并不意味着就能够真的在现场。

我们看到在那个贴膜团队里,团队领导只需要看一眼,发现有气泡,就知道质量有问题。也就是说,在传统行业进行现场管理的时候,问题都是非常直观的,非常容易发现。在软件行业想做到一点就难的多,记得几年前我的同事熊节也曾经写过一篇文章,文章的核心洞见就是软件开发的现场在代码里。

这个想法在ThoughtWorks有很多拥护者,公司里有很多人提出过类似的观点,于是我们的很多方法就是构建于这些类似的观点之上。

然而,如果我们想要追求IT工作者开发效率的极限,这个洞见还不够极致。经过几年的工作,我发现,代码只是软件开发工作的第二现场,软件开发工作的第一现场,在语言里。

这里说的语言,不是编程语言,也不是广义的人类语言,比如汉语、英语。指的是我们在从事软件开发工作中所使用的一系列术语和相关的一系列呈现方式和沟通工具。借用一个技术术语,我们所说的语言是一套仅供软件开发所有相关人员使用的、组合的DSL,DSL全称:Domain specific language,中文名叫做:领域特定语言。

DSL就DSL,还组合的DSL,为什么要说的这么拗口呢?什么叫组合的DSL?我们知道在软件开发的过程当中,需要各种不同的角色参与。每个角色有自己特定的领域,泛泛的讲可以分为三类:我们把产品经理和设计人员所使用的领域特定语言叫做设计语言;把开发和测试使用的语言叫做技术语言;把业务人员、组织管理者使用的语言,叫做业务语言。

所以我们使用的这套领域特定语言是把这三类语言组合在一起而形成的一套语言。这就意味着我们这套语言非常容易充满歧义,造成每个角色自说自话却难以被发现。

软件工程里的核心观点是:一个问题被发现的越晚,修正的成本就越高。比代码更早的是沟通,比沟通更早的就是语言。我们用语言去描述沟通的错误,去描述代码中的错误,我们用什么来描述语言的错误呢?还是语言,这就使得整个工作困难重重,难以达成共识。所以我们更需要非常严肃的对待软件开发工作的第一现场。

之前一些方法试图建立纯粹的统一语言,所有人都说一套语言,事实上这个方法已经被行业放弃了,我们要承认,各自不同的语言有些部分可以简单统一成一种表达以消除歧义,有些部分只能结合。也就是说相关人员要懂多门语言。这个现实是我们必须接受的,软件正在吞噬世界,语言只会越来越复杂。就像我们再努力消除污染,也不能幻想世界回到工业文明以前了。无论我们多么努力的去建立统一语言,也不可能形成一门简单的语言,只能是多门DSL的一个杂合体。

不过由于历史的原因,在行业放弃的过程中,由于“反对预先设计”走的过了头,“不谈建模,不谈标准化”成了一种奇怪的政治正确,导致很多优秀的工具和方法被边缘化了。其实我们憎恨的只是预先设计造成的反馈速度变慢,只是在这个过程中连带上了憎恨预先设计时代的一些工具,这就有点上纲上线了。

幸而最近几年,各种领域建模的设计方法又重新回归。最近大行其道的领域驱动设计,就是在很严肃的对待业务语言的设计和使用。而在前端领域,Design System试图解决前端开发和设计师之间的语言分歧问题。我个人在从事软件开发工程师的培养方面发现,很多传统的可视化工具,比如说UML。如果不以繁重的预先设计为目的,来使用这些工具,仅把它们用作提高沟通效率的工具,他们的威力是十分惊人的。

以我本人的团队为例,我们使用ant design为基础,设计了design system。使得我们可以在三天之内得到一个可以点击的软件原型,并在此基础上,进行各利益相关方之间的需求交流和反馈。在交流的过程当中,我们也刻意的统一了语言,使得我们尽管是一个远程团队,但是在交流的时候,能够很清楚的知道我们在对信息架构在哪一层进行反馈。这不但使得业务方可以反馈技术方,其实技术方也在引导业务方。语言的影响是双向的。

在技术领域里,我们也选择了隔离性更好的技术架构,使得MVP的代码不会变成我们演进道路上必须长期背负的负累。而之所以在一篇聊“语言”的文章里提技术架构,是因为我们认为真正的架构不是纸上的,也不是代码里的,而是每个团队成员心里的架构。实施一个架构必然也是要进行大量沟通,也需要统一语言。

而在交流业务的时候,我们刻意的划分了各种不同的子领域,又在每个领域当中统一了名词。统一名词还是比较简单的,最难的是划分领域,我们为此投入了大量的工作,也犯了一些错误,但这些付出是值得的,这之后,我们的沟通变得非常流畅。

具体的实践有机会再跟大家分享。在这里仅仅聊一下沟通顺畅带来的价值,沟通顺畅的威力并不仅仅表现在沟通的时候可以很顺畅的传递信息,最重要的是当有团队成员对信息理解出现错误的时候,可以很容易的发现和给予反馈。

这个优势在IT行业至关重要。IT行业的人员流动率接近25%,这意味着每年我们团队中至少有1/4的新人加入。即便我们想尽方法让我们的团队保持稳定,随着敏捷和精益创业的相关思想慢慢成为我们的工作常识,每个项目存在的时间都不会太长,这使得IT团队经常性的重组,有时是团队被打散,有时是同一个系统从一个团队交给了另一个团队。如果缺乏一种有效的反馈机制,那么无论是人员流动还是组织重组,所造成的切换成本都是一个很大的。尽管这个切换成本无法消除,但是尽量减少切换成本是我们每个专业人员应该追求的,尤其是团队中的技术领导者。

技术领导者重音在“领导”,而不在“技术”。尤其在Tech@Core的今天,技术就是业务。优秀的技术领导者更不能把自己变成一个救火队员,只是被动的响应,尽管救火队员常常因为很容易被人看到而获得一些关注和赞扬,但在中国的文化里,我们都知道还有更高一层的境界,这个境界存在于很多典故中,比如上医治未病,善战者无赫赫之功。同理,软件开发领域的技术领导者们也应该努力使大多数问题发生的基础消灭于无形,这就需要我们走出舒适区,深入到软件开发的第一现场,进行现场管理。


更多精彩文章,请关注微信公众号:软件乌托邦

Share