软件开发团队的脓包

潘加宇

在严谨建模思维的扫视之下,软件开发团队中很多有意无意遮掩的脓包会被强制露出。

接下来我会总结一些常见的脓包,供大家参考。

脓包(1)皇帝的新装

emperorclothes.png

图片来自Wikipedia

阿Q家徒四壁,连衣服都没得穿,觉得很丢脸。这时,有人和阿Q说,其实这是一种时髦,你穿的是“皇帝的新装”。像溺水的人抓住救命稻草一样,阿Q立刻被这个说法洗脑,以后都和别人说自己穿的是“皇帝的新装”,遮掩没有衣服穿的事实。

在我刚开始为软件组织提供服务时,常听到软件组织的负责人和我介绍他们的团队“我们现在用的不是面向对象和UML,用的是结构化方法”。我一开始信以为真,认为如果能做到用数据流等建模元素从组织级、系统级到模块级层层分解也不错啊,后来发现,绝大多数情况下负责人所说的“结构化方法”其实就是随意的分解,也就是没有方法。

后来,这个场景升级了。软件组织的负责人和我介绍他们的团队“我们现在采用的是敏捷开发方法”,我听到这里有时会忍不住咧开嘴笑看着对方,对方也意识到我表情的意思,连忙解释“我们自己以为是敏捷开发方法”。

你瞧,如果说团队“没有方法”,那很没面子,但抓住“敏捷”这根救命稻草,宣称我用的是“敏捷”,脸上就有了光彩。

*******

这还不是最关键的。

我们经常会自嘲。比如没有车走路来的,会自嘲说“我坐的是11路车”,没上过大学,会自嘲说“我上的是社会大学”。说这些话的时候,说话人很可能知道是在自嘲。

而有的软件开发团队说类似话语的时候,并不是在自嘲,是信以为真哪!


脓包(2)口号党

hell.png

如果评价三种做事情的方式:有口号有方法、有口号无方法、无口号无方法,哪一种最坏?

可能有的人会认为无口号无方法最坏,其实不然,无口号无方法地呆在原地,可能会慢慢衰落,但不是最坏的。历史上各种最坏的大悲剧往往和“有口号无方法”有关——最坏的事是“有口号无方法”的“好人”做的。

“坏人”知道自己做的是坏事,会暗自收敛,事后会内疚,甚至做一些善事来弥补以求心安。比如,强盗打家劫舍抢了一千万,可能会拿出五十万来“济贫”,剩下九百五十万自己爽。这样,他心里就觉得自己是“侠盗”。

而“好人”认为自己是做好事,既然做好事,那出手就不要有顾虑了,做得越绝越好,所以可能会做得很极端。如果有口号无方法,大悲剧就发生了。希特勒把那么多人送去做肥皂,他也没觉得有啥不好意思,因为这是为了建设更美好的社会嘛。

hitler.png

我们切换到软件开发领域。

互联网公司的研发人员喊口号:我们只做最重要的需求,尽快把产品投放市场。

问题来了:怎么才能知道哪个需求最重要?拍脑袋?抓阄?"投放市场"就有人要?莫非你爸是李刚?怎样才能"尽快"呢?

没有掌握相应的技能,多半是一次又一次的惨烈碰壁(可以自我安慰为“试错”),所谓的"快"也只是手忙脚乱的表面的"快",给自己一个心理安慰"我努力了"而已。在训练有素的对手面前,根本就是一个莽夫在胡乱出招,到处都是漏洞,只要对手乐意,分分钟取你性命。

那么,就算没方法,喊喊口号总比不喊要好吧?很多情况下确实如此。口号先行,慢慢再改善方法。

但是,我们必须注意到“有口号无方法”状况的危险:

危险一:无意识的自我陶醉

有的人喊完“最重要的需求”、“砍掉80%功能只留20%”之后,就满足了,陶醉了,觉得自己太牛×了,这么厉害的道理都懂,足矣,其他都是小意思了,然后并不认真思考如何才能真正能够做到,连自己以前采用的一些虽然不是很好但还过得去的做法也懒得做了。

危险二、有意识的胡作非为

有心人会挑一些褒义词作为口号,例如“敏捷”,再辅以煽动性很强的词语,例如“无敌”、“硝烟”、“颠覆”。褒义词作为口号声明了一个美好的、不容否定的目标,而手段也声明为无需思考只需要冲冲冲,更是正中某些不喜欢思考或者没有能力思考的开发人员的下怀。

然后,在口号的遮掩下胡作非为。

这是最坏的情况。因为口号是正确的,这些胡作非为就很难阻挡,而且后果也不好追责,毕竟“初衷是好的嘛”。

我印象最深的是,一位女生天真无邪地问我,“老师,希望敏捷一些难道不好吗?”——我还能怎么说,我能说不好吗。这和“爱国难道不好吗”、“环保难道不好吗”一样的。(在此处提到“女生”,没有歧视的意思,只是说到这里,让我想个例子,我最容易想起来的就是这个。)


脓包(3)鸵鸟

鸵鸟遇到危险的时候,就把头埋到沙子里,以为这样别人就看不见自己了。

tuoniao.png

假设有这么一道数学题:

妈妈买了苹果和梨共320千克,其中苹果的重量比梨的4倍多20千克,求妈妈买了苹果和梨各多少千克?

没学过未知数、方程等知识的小学生,可能会画线段图:

学习了二元一次方程组的初中生,可能用以下方法:

但是,初中生马上就杯具了。因为他学会了更高级的方法,所以他作业和考试要面对的题目比小学生要复杂得多!

当方程组越来越复杂,初中学习的代入法、消元法已经很难应对。

大学生学了线性代数,了解了,其实就是矩阵的运算Ax=b,x=b/A,而且还可以用计算机来帮忙算(例如MATLAB)。

但是,大学生马上就杯具了。因为他学会了更高级的方法,所以他作业和考试要面对的题目比中学生要复杂得多!

于是,有人就想:我要是不学习更高级的方法,我要面对的问题不就不复杂了吗?或者说,我面对复杂问题解不出来也就有了借口!

*********

对某些人来说,如果不用动脑子,一遍遍重复简单的工作,还能拿高薪,简直是人间天堂。

如果被迫做前所未有的复杂思考,探索之前没有探索过的复杂问题,那就如同坠入了地狱。

这时,潜意识就会找出各种理由和手段来逃避思考。

例如,故意选择比较粗糙的工具,不想用更专业的建模工具,张嘴就说“太重”,以此为由逃避艰难的思考。更乐意在白板上随便画画,在墙上贴纸。白板就这么大,所以客观上你总不好意思让我用白板剖析复杂的逻辑吧?

我确信我发现一种美妙的证法,可惜这里的空白处太小,写不下。——费马

例如,不愿意学习严谨的思考方法,喜欢打哪指哪,思维一会飞到天际,一会飞到地底,更麻烦的是,他根本不知道自己的思维目前是在哪里,但没关系,这样自由。

例如,和其他人宣传“干就完了”,让其他人也不思考,以免发现自己的破绽。

例如,把自己懂得的叫做“实践”,把自己不懂的通通称为“理论”。

*******

不止一个开发人员和我说,现在流行微服务,建模就不需要了。因为很可能一个功能就是一个微服务嘛,一个一个做,需求也不用写,类图也不用画。

首先,“只做一个功能所以不用做需求也不用做分析”这个认识是错误的。

需求永远是只做一个——最值得马上做的那一个,需求的建模工作就是要把“那一个”找出来。

另外,内外不是一一映射的,一个功能涉及到的类就少吗?AlphaGo功能够单一的,内部逻辑多复杂。

其次,也是更要命的,“微服务”成为了借口。

以前的开发难道不是一个一个用例这样做过去的吗,如果“一个用例一个系统,不用做需求也不用做分析”这个方法真的好,为什么不早点这样做,何必等到“微服务”呢?

“微服务”之后,整个系统应该是比之前要更复杂吧?按道理,不应该需要更多的思考吗,怎么会思考反而减少了呢?难道开发人员吃了什么神药,或者工具突飞猛进了?

除了“微服务”之外,之前开发人员用过的各种各样的借口还有“我这是一个遗留系统”、“我这是一个移动互联网系统”、“我这是一个二次开发的系统”、“工期很紧”……反正强调自己的系统很特别,来不及思考或者不需要思考就对了。

例如这篇《“精打细算”不用UML的奇怪脑洞》

*******

鸵鸟心态也导致下一个脓包:废话迷。


脓包(4)废话迷

如果有人告诉你,有一件事情很容易做好,而且做好了还能赚不少钱。听到这样的话,你可能会嗤之以鼻:幼稚!如果有这种便宜事,前面的人早拿走了,还能留到现在?

到了软件开发上,却有很多人犯这样的幼稚病,以为不需要付出艰苦的思考就能解决自己手上的软件开发项目。

【场景一】

问:这个系统改善什么组织的工作?

答:医院。

问:那么多医院,你认为哪家医院最适合引进这个系统去改进呢,能不能举一家你能想到的最合适引进的医院?

答:全国的医院都可以,哪家合适就哪一家。

上面的问答中,第一个问题很容易回答,第二个问题就比较难了,回答者回避了这个难题,回答了一句“正确而无用的废话”。如果再沿着这个问题追问下去,回答者可能就抵触了:干嘛要想这个问题?谁爱用谁用呗!

【场景二】

问:这个系统有哪些用例?

答:有新增设备、编辑设备、删除设备、查询设备……

问:这些用例怎么得来的?

答:我觉得应该有这些用例。

怎么来的?很可能是这样来的:想到数据库里可能会有设备的信息,所以给它刷上4个CRUD用例。同理,数据库里可能会有人员的信息,也刷上4个CRUD用例。一下子就找到了好多用例,需求规约就多了几十页,代码也可以写好一阵了,而且不用做什么思考,就可以刷这么多工作量,真爽!

【场景三】

问:“计算运费”这个责任需要哪些类?

答:简单,我有“运费计算器”类。

问:“运费计算器”类为什么能计算运费?

答:因为里面封装了“计算运费”的算法。

问:“计算运费”的算法具体是什么逻辑?

答:……(一旦无可逃避,可能就卡住了)

很多“面向对象”、“领域驱动设计”就是这样干的,车轱辘话转来转去,真正的复杂性却没有能力或不敢触碰。期望这样的做法能解决复杂问题,那真是见了鬼了。


有同学给我发了一个网络上的“领域驱动设计”课程让我评点一二,看完只能说一声叹息。

fhm01.png

图1 某“领域驱动设计”课程愿景截图

图1的“愿景”还真是“得来全不费工夫”,几句车轱辘话就搞出了一大段文字。

图1的文字类似于:

为了满足病人吃奥美拉唑和阿莫西林的需求,医生给病人开了奥美拉唑和阿莫西林,为什么呢?因为奥美拉唑有奥美拉唑的药效,阿莫西林有阿莫西林的药效。

这样的“思考”有什么价值呢?有价值的思考应该类似于:

为了解决病人胃酸返流的问题,医生给病人开了奥美拉唑和阿莫西林,奥美拉唑可以阻碍胃壁细胞上的离子通道,减少胃酸的分泌……

针对图1,不容易的思考是:

(1)哪家组织最适合引进该系统?

有价值的回答类似于:BJ市MTM公司。理由:MTM公司一年前创立,目前处于业务上升期,人员从**人增加到***人。

(2)该系统解决组织当前存在的什么问题?

有价值的回答类似于:

问题一、批假周期过长。经统计,过去一年,MTM公司从员工提出申请到最终审批结束平均需要***时间。

问题二、不合规的批假较多。经统计,过去一年,MTM公司的批假不符合公司规定的比例占*%。

图1中可能有价值的内容是淹没在车轱辘话中的“无差异管理”,不过光说“无差异管理”还远远不够。既然要追求“无差异管理”,那就说明目前的管理是“有差异”的,那请问是根据什么指标来判断目前“有差异”?达到什么样的指标才算是“无差异”?还有,“管理”到底指什么,是顺口带出来的还是有特定的意思?

(3)MTM公司当前是怎么请假和批假的,造成以上两个问题的原因是什么呢?

有价值的回答类似于:通过序列图或活动图画出MTM公司请假和批假的流程,找出其中的改进点。因为只是示意,我就不画图了,给出一张其他领域的图:

shoujike02.png

图2 业务序列图示例

而网络上这个“领域驱动设计”课程是怎么做的呢?

fhm03.png

图3 某“领域驱动设计”课程战略设计截图

(1)拉“一群专家”来风暴?闭门造车?难道不应该是深入第一线去调研目标组织当前存在的问题吗?

(2)注意到那一堆创建、修改、查询了吗,刷工作量的嫌疑。

再看下面这个:

fhm04.png

图4 某“领域驱动设计”课程的分层

(1)同样的文字批量刷了三遍。

(2)最需要思考的困难部分:审批规则,却是一笔带过。看下图列出的源代码文件确实是如此,应该是变成了一个长长的“算法”放在了LeaveApprovalRule里面。

fhm05.png

图5 某“领域驱动设计”课程的源代码文件

(3)还可以看出一个问题,Leader就是Person,只不过在和另一个Person的关系中扮演Leader的角色,单独一个类不合适。

真正有价值的思考的结果,要能够把复杂的领域逻辑显式表达出来,类似图6。

fhm06.png

图6 显式表达请假审批规则

图6中灰色部分显式表达了“请假审批规则”。

现在把“领域驱动设计”挂在嘴边的人里面,有多少人能给出这样的图呢?

“微服务”更是为不动脑子刷工作量提供了绝佳的借口,几十年前的“功能分解”借尸还魂了。例如要做一个“人”,思路特别简单。走路功能→走路服务→走路器官,游泳功能→游泳服务→游泳器官,什么人体解剖学不用管就可以刷出好多工作量,爽死。


没有免费的午餐,如果你觉得不用经过复杂的思考,就能解决一个能带来利润的问题,别高兴太早了,很可能你的答案是错的,甚至很可能你以为的问题根本不是真正的问题。

就像高考一样,前面几道题扫一眼就搞定可以理解,往后面做,如果觉得题目还是扫一眼就搞定,甚至觉得压轴题挺简单,那得好好想想了,是谁的问题。更何况,在市场上搏杀,做的何止是高考题,简直是竞赛题,哪有那么简单的!

所以,当我们得到某些答案的时候,要尽量想一想:这样的答案轻易想得到吗?如果轻易想得到,说明也许思考得还不够,还要继续思考。我们写的每一个字,画的每一张图,都应该是思考的结晶。

但这并不容易,不是所有的团队和人员都乐意和胜任这样的思考。人性使然,想那么多干什么,浑水摸鱼就好了,而且严密的思考需要一定的逻辑思维能力,许多人并不具备。

只有少数有“冠军的心”的团队和人员,希望自己的产品成为领域的冠军,才会有质量的诉求,从而带来提升建模技能的渴望。

退一步说,即使环境不允许你有“冠军的心”,如果你了解了这些用废话刷工作量的套路,当你需要应付了事刷工作量的时候,有意识地说废话也要比无意识说废话要“高效”——拿去哄人没问题,至少没有哄自己就行。


接下来是

脓包(5)发明家

不学习,不思考,动不动就说“我发现***”,弄出各种伪创新。

weixinpanjiayu2.jpg