之前所论的各个环节:管理、流程、开发模型、估算、需求开发所产生的一切后果,无论好的或坏的都会在设计编码中体现出来。而设计编码对其他环节的影响则往往只能在项目结束之后。
这其中开发模型、需求开发和管理对设计和编码影响最大。
开发模型决定后,设计做到什么程度的问题将得到澄清;需求则不但决定了设计编码中要做什么,有时也决定了设计编码的风格。比如,是否使用测试驱动开发,是否使用结对编程等。
设计和编码中有些问题是对错问题,有些则是选择问题。
对错问题的处理依赖于设计编码的能力,比如,增加了不必要的复杂度是一个对错问题,但能不能优化掉不必要的复杂度则依赖于当事人的能力。
选择问题的处理大多时候则只能到需求中找答案。比如说,在特定的项目中,需要分别定义两组UI来完成对一组数据的添加和编辑工作。
这个时候的解决方案至少会有两种,一种方法是以数据操作为中心,在数据操作的类中提供显示不同UI的接口,如下:
Database.Add()这个时候添加数据的UI将被显示出来。
Database.Edit()这个时候编辑数据的UI将被显示出来。
在这种方法下,UI从属于数据操作。
另一种方法是把UI和数据操作进行更彻底的分离。
在对UI消息进行相应的时候,调用Database.Add()或Database.Edit()这类的方法进行内部数据操作。
第一种方法的优势在于UI是数据操作的一部分,便于集中定义不同的事务(Transaction)。(在《敏捷软件开发:原则模式与实践》的12.5章中举了这样一个例子。)
第二种方法的优势在于把UI看成一个整体概念,并独立出来,便于对UI整体进行优化。
在这种情况下,单纯地判断哪种设计方法更好是没有意义的。如果想判断哪种设计更好则需要的是回到这次设计的具体应用场景,才能进行判断。
如果项目中存在着这样一种变数,日后所有的UI都希望能够统一进行处理,有可能使用绘图工具来设计UI。这个时候显然第二种方法是合适的,因为使用这种方法的时候,UI是作为一个独立的概念存在的,任何UI的变化都将被隔离,而不会影响到数据操作本身。
根据热力学第二定律,孤立系统总是趋向于熵增,最终达到熵的最大状态,也就是系统的最混乱无序状态。这个规则对应到软件,可以表述为:
如果我们什么都不干,只是向软件中追加或调整各种功能,那么软件必然会趋于混乱,即不必要的复杂度持续增加。只要我们持续调整代码,那么与前一节的结论(概念正交分解)不相吻合的设计和代码必然会出现,并导致代码越来越不可维护,这其实是要求代码必须是“活”的。也就是说,管理和流程这样的环节要保证鼓励寻找相对安全的手段(重构、自动回归测试等)对代码的修改,而非相反。否则在没有力量阻遏熵增的情形下,垃圾代码只能越来越多,修改一行代码的单价也只能越来越大。这是一个非常有意思的两难课题。
假设这是一个性命攸关的软件,由于担心触发不良后果,通常没人敢对代码进行优化。由此而导致的结局必然是程序越来越复杂,也就越来越容易出错,最终会更容易导致不良后果。本质上看,这并非技术问题,需要在更高层面来解决,项目级人员很可能对此无能为力。
设计编码有问题的典型症状如下。
●程序员普遍焦虑。一旦改了点代码,很难准确知道会有什么后果。(www.xing528.com)
●没人敢改代码,也没人愿意改代码。
●不太可能写出真的UT。
●新人介入成本极大,往往需要了解整个程序。
●功能无法拆装拼接。
●......
重构与《扁鹊见蔡桓公》
重构的想法并不复杂。Martin Fowler自己这样描述重构:所谓重构是这样一个过程:在不改变代码外在行为的前提下,对代码做出修改,以改进程序的内部结构。
而与重构对冲的则是担心出问题,影响商业利益,所以很多时候重构启动不起来,大家只能对着垃圾代码抱怨。
这点并不难理解,再垃圾的代码只要存在,并完成了特定功能,保证了一定性能,其在用户的眼里和好的代码差别并不大。而任何对其的修正则可能导致直接影响用户的不良后果。
这场景有时候会让人想起《韩非子·喻老》中《扁鹊见蔡桓公》这篇寓言:
扁鹊第一次见蔡桓公的时候说:“你的皮肤纹理间有点病,不治会变严重地。”
蔡桓公根本不相信,说:“哪有这回事,你不要胡扯。”等扁鹊走了后,蔡桓公对身边的人说:“医生就喜欢说没病的人有病,这样好显着自己有本事”。
过了十几天,扁鹊再见到蔡桓公,道:“你的病已经在肌肤里面了,不治会更严重的。”
结果蔡桓公没搭理他。
又过了十几天,扁鹊见到蔡桓公后,道:“你的病已经在肠胃里面了,不治后果会相当严重。”
结果蔡桓公相当生气。
再过了十几天,扁鹊再看到蔡桓公后,什么也不说,转身就跑了。这下蔡桓公很奇怪,忙派人去问他跑什么。扁鹊道:“你们老板的病,之前是治起来麻不麻烦的问题,所以我提醒下还有意义。现在是神仙来了都没办法,我不跑还能怎么地?”
再过了五天,蔡桓公病发了,再找扁鹊,扁鹊已经跑到秦国去了。于是蔡桓公只好去世了。
程序的最初版本往往很像文中得了小病的蔡桓公,大多时候是一定有点问题的。如果没法开启重构,代码一定会变成垃圾代码,而上规模的代码垃圾到一定程度后是完全没法改的,很像文中的病入膏肓的蔡桓公,你只能看着它慢慢死去—只是维护他的人要跟着葬送很多时光。
而重构本身并不难,难的是启动重构,并持续做下去,这并非是技术问题。
免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。