对很多人来,嵌入式软件开发过程中 模块化(Modularization)是一个海市蜃楼、是一个书面词汇、是一个过气的时尚——模块化似乎从未真正的实现过。吹牛时人们常不屑的说:没吃过猪肉,但还没看过猪跑么?事实上,如果讨论的对象是嵌入式软件,很多人可能真的没有看过猪跑。在话题变得更像都市传说的之前,我想问一个问题:
为什么要模块化?
有经验的人会说:
为了代码复用(Code Reuse)
进一步——“为什么模块化可以实现代码复用呢?”很多人会说:
你这不是抬杠吗?明摆着的,代码做成了模块,那么别的项目就可以直接使用了,模块里的这部分代码就得到了复用。
更进一步——“代码复用又是为了什么呢?”听到这里项目经理们深吸了最后一口烟屁股,顺手丢到脚边、踩灭、起身准备离开:
代码复用可以节省开发时间,加快项目研发速度。
为了把嘴边的那句“你们慢慢聊,我还有事”噎回去,我们再问一个问题:
实际项目开发中,用模块的时候,项目的进度真的加快了么?时间真的节省了么?
项目经理们不动了,抬起到半空中的屁股慢慢的坐了下来。这次,他们的语气是认真的:
不,使用模块通常并不一定能加快项目进度。老实说,用别人的模块,程序员常常要认真理解模块的功能和代码才能在调试的时候确认问题的范围。你知道,很多时候看懂他人代码所用的时间比自己重新设计一个更长。
周围不少程序员都投来赞同的眼光,有的甚至很认真的点了点头。实际上,这里我们已经发现,在实践中,抛开用于模块化的技术不谈,使用模块实现代码复用本身往往并不能加快一个团队的开发速度——那么我们要模块化做什么?
下结论还为时尚早。从项目经理们的描述可以看出:
根据我们在《什么是嵌入式(上)》中的描述,程序(软件)是“程序员尝试去固化的自己的思维”;而模块(硬件)则是“业已固化的逻辑”,读懂一段程序,实际上就是要通过死的代码逻辑去反推模块构作者的思维,这是一个逆向过程,这是一个人与人之间用代码进行间接交流的过程,当逻辑本身较为复杂时,显然比将自己的思维直接翻译成程序(重新开发一个)更为困难。
通过上面的分析,很容易看出,模块化就是为了通过复用代码来加快开发速度,而正是程序员阅读要复用的代码让这一努力付之东流。由此,我们可以非常直接的得出结论:
使用模块时,必须阻止程序员阅读要复用的代码
或者换一种说法:
使用模块时,必须专注于模块的使用,而必须有意忽视模块的实现逻辑,必须要在心理上信任模块。简而言之,必须把模块视作黑盒子!
很容易发现,上面的结论是站在项目经理的视角得出的,因为项目经理关注的是项目本身,是各类资源的合理利用,是项目的进度——项目经理唯一不需要也不应该关注的是具体的技术实现细节。那么从第一线程序员的视角来看这个问题:
为什么程序员要阅读模块的代码实现呢?
笔者问过不同从业时间/经验的程序员,从过来的的角度来看,无非是以下几个原因:
对于这种情况,就我个人来说,只有一条准则——不提供源代码!只提供库文件——相信我,通常面对汇编代码熟手无策的程序员会在调试的时候自动忽视模块的实现细节,专注于模块接口的输入输出行为——给什么输入,期望什么输出,实际获得什么输出——一目了然,简单直接。如果真的期望输出和观察到的实际输出不同,问题也就找到了:要么是文档没有读好,对输入输出的理解有误;要么是输入就有错;要么就是模块有问题。这绝对比读懂源代码以后再来调试要快得多!——除非这个别人写的模块需要你来维护……所以说,调试的时候
根!本!不!需!要!读!模!块!的!源!代!码!
根!本!不!需!要!读!模!块!的!源!代!码!
根!本!不!需!要!读!模!块!的!源!代!码!
以调试作为阅读模块的源代码的理由,根本就站不住脚!
既然在模块的使用过程中,无论是学习目的还是调试目的都不需要阅模块的源代码,那么可以明确的得出结论:程序员在使用模块的过程中完全不需要,也不应该浪费项目的时间来阅读源代码。一个团队只有做到了这一点,才能借助代码复用加快项目开发的速度。
当一个团队的项目经理理解了“阅读模块代码”对项目的巨大危害,并以制度的形式对程序员的这一行为予以了制止——移除了模块化实践的绊脚石;那么技术经理应该如何理解、设计和实践适合于当前团队和项目需求的模块化架构呢?
欲知详情,请听下回分解。