编程中有一种很重要的思想,就是分而治之(Divide and Conquer),N多的算法都采取了这种思想,比如Merge Sort和Quick sort,以及对Binary tree的递归前中后的Traverse。套用到数学公式里,比如说工作F的内容包含F1和F2,那么F1+F2小于F,也就是说将F1和F2分开处理的难度要比直接处理F的难度要小。
在软件开发中也常用到这种思想,不过这里叫做功能分解(Functional decomposition),比如说,如果给你一个任务,需要编写一段代码,访问数据库中存储的形状然后将其显示出来。按照正常所需要的步骤来思考是一种很自然的选择,比如说,你可能会这样分步骤解决这个问题:
1)在数据库中找到形状列表
2)打开形状列表
3)按某种规则将列表排序
4)在显示器上显示各个形状
然后就是逐步细化的过程,比如说步骤4可以被分解为下面的步骤:
4a)识别形状的类型
4b)识别形状的位置
4c)调用相应的方法,以位置作为参数,来显示形状
这就是一种很典型的"功能分解"的思想,因为分析人员把一个大的问题分解成了多个相对小的功能步骤(这些步骤就构成了这个问题的解决方案)。一般人都会这么做,因为直接解决整个问题的难度往往要比逐个解决子问题的难度要很多。
然而功能分解方法存在一个很大的问题:它通常会导致一个"主"程序负责控制子程序,当然这是将功能分解为多个子功能的自然结果。但是,主程序所承受的责任太多了,它不仅要确保一切子功能的正确工作,而且还要协调各个函数并控制它们的先后顺序,因此经常会产生非常复杂的代码。如果让一些子函数自己去负责自己的行为,并且可以告知主函数它们要去执行哪些任务,这种方式要比功能分解的方式容易得多。这就是委托(Delegation)的思想。
功能分解的另外一个问题在于:它很难应对未来可能出现的变化以及对代码进行合理的改进。变化是无法避免的:新功能的增加和新模型的引进都会导致代码发生变化。如果把实现各个步骤的所有逻辑代码都放在一个大模块中的话,那么这些步骤中哪怕是有一处变化,都会导致对整个模块进行修改。其实最麻烦的是不在于修改代码,而是在于变化往往会产生各种各样的Bug,也正如本书作者Alan Shalloway所提到的,许多Bug都源自与对代码的修改。
而且,无论事先的分析做的怎么好,也是无法从用户那里获得所有需求的,因为未来的变数太多了。因此对于阻止变化,我们是无计可施的,但是幸运的是我们对变化本事并不是无能为力的。
2008年11月12日星期三
订阅:
博文评论 (Atom)

没有评论:
发表评论