一个栗子
自己前几天接收到一个需求,需求想要实现的功能十分简单:就是在某个表单内增加一个必填的下拉框,以提醒用户不要忘记做某一个动作(也许这就是表单设计太过简易的缺点吧@_@)。然后我就简单写了个功能设计文档,遂安排一名同学去完成这个工作。
第二天我去查看完成效果,这位同学笑嘻嘻的说这么简单的功能我已经开发、自测完毕了,准备测试和上线了。我很满意,让他给我演示了下。嗯。不错。
准备部署测试环境,突然发现他在confluence上传了份DB,我惊了,打开一看,DDL脚本在业务数据表内也新增了一个字段用来保存新增的下拉框用户所选的值。这个DDL完全是画蛇添足,造成的影响就是:原来仅仅只是修改前端逻辑判断,现在后台的vo、dao、mapping都增加了一套逻辑判断。我问他为什么要这么做,他回答我:根据自己的思考,后端做逻辑判断更加方便,代码开发起来更快(-ロ-)。
Impression
之前看过一篇文章,John Ousterhout (注,Tcl语言的设计者)在他的新书《A Philosophy of Software Design》中提到的观点:“战术性编程”和“战略性编程”的对立性。
- 战术性编程
追求以最快的速度完成可工作的功能。这看上去无可厚非。但是这种行为往往会增加系统的复杂性。引发大量的技术债。可以说这种做法以牺牲长远利益来获得眼前的利益。
- 战略性编程
不仅仅要求可工作的代码,以好的设计为重,未来的功能投资,认为现阶段在设计上的投入会在将来获得回报。
上面的例子中就是属于战术性编程:为了更快捷的实现功能(摒弃前端,采用更复杂的前后端交互设计),短期内可以增加开发效率,但是如果需求变动,比如不需要这个下拉框或者在新增一个呢?后续维护成本无疑越来越大,系统的代码也会越来越复杂。
- 引申:复杂性
作者也在书中提到了复杂性的本质:
软件设计应该简单,避免复杂,关于复杂性的定义,作者认为主要有两个量度
- 系统是不是难以理解
- 系统是不是难以修改
关于复杂性的症状:
- 当新增特性时,需要修改大量的代码
- 当需要完成一个功能时,开发人员需要了解许多知识
- 当新增/修改功能时,不能明显的知道要修改那些代码
引起复杂性的原因:依赖和晦涩。
最后,复杂性不是突然出现的,它是随着时间和系统的演进逐渐增加的。
当然这里面需要讲解的东西太深、太广了,今天不可能写完。
只是简单写出来自己的感想,怎么才能做到战略性编程,尽可能降低系统代码的复杂性呢?综合上面的例子来看,需要做到以下几点
- 清晰、透彻地明白功能的目的是什么,为什么要做这个功能。不能南辕北辙,画蛇添足。
- 设计与开发的时候尽可能为未来考虑,如:如果需求变化了,我们将要开发的代码是否能够方便的应对?
- 引申第二点,尽可能做到模块间解耦(前后端、业务模块等),防止某个模块地单独变化而引起蝴蝶效应。