决定把第8章一部分关于“伪创新”的内容移到第1章,因此此次也更新第1章。
第1章 建模和UML
牵着你走进傍晚的风里,看见万家灯火下面平凡的秘密。
《情歌唱晚》;词:黄群,曲:黄群,唱:曹崴;1994
1.1 利润=需求-设计
1.1.1 利润=需求-设计
利润=收入-成本。不管出售什么,要获得利润,需要两个条件:
(1)售价要高;
(2)成本要低。
妙就妙在,价格和成本之间没有固定的计算公式,这正是创新的动力之源。
放到软件业上,我也炮制了一个式子:
利润=需求-设计
在软件开发中,需求工作致力于解决“提升销售”的问题,设计工作致力于解决“降低成本”的问题,二者不能相互取代。能低成本开发和维护某个系统,不一定能保证它好卖。系统好卖,如果开发和维护成本太高,最终还是赚不了多少钱。
(有的读者可能会想:我做的项目是单位内部项目,不卖钱。那我只能说too simple, sometimes naïve了,可以继续往下看。)
同上,需求和设计之间不存在,也不应该存在有规律的映射——也幸亏如此,否则人工智能就可以取代人完成。人(即软件开发人员)存在的价值就是在很多种现有可行的映射方案中,努力挑选出其中最好的方案,甚至通过技术革新,创造出更好的方案。
我们先来看自古以来就有的一个系统,“人肉系统”。
人肉系统的功能(需求)是(人能够)走路、跑步、跳跃、举重、投掷、游泳……但是设计人肉系统的结构时,并不是从功能(需求)直接映射到设计,得到“走路器官”、“跑步器官”、“跳跃器官”……人肉系统的器官是眼、耳、心、肺、肝、胃、骨架、皮肤……这些器官和人肉系统的功能不是一一对应的,在互相协作以完成系统的功能时,它们和功能之间的关系是多对多的。
图1-1是某个人肉系统的需求和设计。可以看到,需求和设计的映射是多对多的。各个器官被各个功能共享,不能说“心脏是老板的”、“肺是老爸老妈的”。
图1-1 人肉系统的需求和设计
图1-1的映射只是造物主——用《异形(Alien)》的说法就是工程师(Engineer)——当初挑选的映射方案,今天,人类也成为造物主开始“造人”的时候,我们挑选的映射方案可能和人类的造物主(如果存在)制造人类的映射方案是不一样的,如图1-2。当然,目前人类的科学技术水平,连细胞都造不出来,想要做一样的方案也做不到就是了。
图1-2 人类和“新人类”
如果老板要雇一个民工扛煤气罐,他只要求这个民工能跑能扛,管他体内构造是心肝脾肺肾(如图1-2上部)还是电路板(如图1-2下部)——如果电路板民工更便宜,他会淘汰掉心肝脾肺肾民工;民工找工作也要从市场的需要来找——“有老板雇人扛煤气罐,我可以!”,而不是从自己的内部器官出发来找——“老板,我每天都管理我的心脏,你请我吧!”
以上所说的这些,总体意思就是:要学会把需求和设计分开,这也是贯彻全书的核心思想,后面还会反复强调——用词可能会有变化,例如“卖和做分开”、“外和内分开”。
软件开发中,如果从需求直接映射设计,会得到大量的重复代码,成本增加;如果从设计出发定义需求,会得到一堆假的“需求”,卖不出去。总之,利润就会缩水。
而这一点,很多软件开发人员并没有意识到。
1.1.2 常见错误
1.1.2.1 “子系统”其实是需求包
我们经常听到这样的说法,“本系统分为八大子系统,包括销售子系统、财务子系统、库存子系统……”,这就是需求和设计不分的一个例子。其实,正确的说法可能应该是“本系统的功能需求分为八大需求包……”。
需求包是基于涉众视角对系统功能分包而得到的,子系统(用UML的说法是组件)是基于内部视角根据系统部件的耦合和内聚情况切割而得到的,这两者不是一一对应的。所谓的“财务子系统”,其实可能是“把财务人员使用的功能放在一个包里”,如图1-3。
图1-3 “子系统”其实是需求的分包
1.1.2.2 “功能模块”是错误用语
另一个常见的需求和设计不分的说法是“功能模块”。
功能(Function)。当我们说起这个词的时候,一般指的是系统的功能需求。因为对于组织,一般说“组织的服务”,对于类,一般说“类的操作”。
不过,“功能需求”仍然不够精确。例如,以自助柜员机(ATM)为研究对象,“取现金”是“功能”,“登录”也是功能,“计算手续费”也是“功能”,到底“功能”有多大?用例的术语要严谨得多。“取现金”是一个用例,“登录”是用例中的一个回合,“计算手续费”是一个步骤。
因此,“功能”是一个模糊用语。本书在后文会尽量使用严谨的用语,不用模糊用语。
模块(Module)。当我们说起这个词的时候,研究对象一般是系统。模块表示系统的组成部分,但这个词也是模糊的。这个模块是一个控件?一个类?若干个类形成的组件?
如果说“功能”和“模块”是模糊的,那么连起来说“功能模块”就是错误的。“功能模块”意味着在意识里认为“功能”和“模块”有直接的映射关系,甚至认为“模块”是属于某个“功能”的模块,是为了完成某个“功能”而存在的。
我简要归纳需求和设计的区别如图1-4,在后面的章节中再慢慢进一步阐述这些区别。
图1-4 需求和设计的区别
高焕堂在他的书《USE CASE入门与实例》[1]中说过:用例是收益面,对象是成本面。本书基于他的思想做了扩展。
1.1.2.3 微服务的遮羞布
最近几年鼓吹的新词“微服务”造成一定的误导。有的人误以为“微服务”就是“需求设计一一对应”。
假设考虑到开发团队的结构,把系统分成多个“微服务”,分由各个小团队应用各自的技术栈独立完成。例如图1-1中的男士,可能会被分割为“996微服务”、“交作业微服务”、“扛煤气罐微服务”。
且不说这样划分是否合理,即使这样划分了,“微服务”内部也要通过自己的各个部件(可能是残缺的)协作完成,例如“做作业微服务”要完成“做作业”用例,也需要眼睛、耳朵、手、脚、心脏、**等(可能是残缺的)协作完成,并非映射一个“做作业模块”然后就搞定。更何况,有的用例需要若干个“微服务”协作才能完成。
另外,“微服务”是妥协的不良结构。如果这样的划分风格所得到的软件结构真的是良好的结构,我们几十年前就可以这样做。即使一个人做的项目,也不妨引入一个假设“由各个小团队应用各自的技术栈独立完成”来改善软件的结构,不必等到今天才大兴“微服务”之风。
我用盖大楼作类比:
两座大楼耸立在那里,要判断地震来了哪座大楼不容易塌,要考虑的是大楼的结构、所用的材料、所在位置的地质环境等,和这座楼是哪家公司建造的,要了多少钱,建造大楼的公司内部是怎样的组织结构,一共有几支工程队,当时怎么分工的,甚至大楼是猫建造的、狗建造的、外星人建造的,已经没有直接关系——因为大楼已经在那里了。
但要研究这些让大楼不容易塌的直接影响因素,涉及到艰深的工程力学、流体力学、岩土力学等知识。架构师李三没把这些知识学扎实,正在那里犯愁呢。
这时,伪创新专家张四出现了。张四说,时代变了,现在盖楼要讲“新建筑学”,要考虑到人际关系,要搞好团结。
于是,李三想着反正“老的”工程力学那些我也搞不懂,还是搞“人”轻松一些。这样吧,有几个包工队跟自己混,就分几个包,大家开干就是。
转换思想后,李三每天累并快乐着,灯红酒绿,推杯换盏。
而且,运气好的时候,盖出来大楼确实也能住人。
如果李三说,公司又不是我的,想那么多干什么,这可以理解;
如果李三和张四说,这么干盖楼快,反正老板要的就是在某某大日子到来之前有个样子货交差,这也可以理解;
如果李三和张四说,这么干有利于建筑团队的安定团结(虽然坑顾客),这也可以理解;
但如果李三和张四说,“新建筑学”盖出来的大楼更抗震,甚至到清华大学建筑学院开课“划时代革命性的工程力学”,取代原有的“工程力学”——这就是无耻了!