一、模块化原则
- 我本来想写基本的设计原则的,但是发现:
接口隔离原则 和 依赖倒置原则,我认为在C语言编码中,如果已经成功的划分了模块的边界,而且要尽可能的解耦合,是要自然而然要做的事情。
所以,改成写模块化。 - 模块化原则
模块化原则展开说,就是:
要编写复杂的软件,而且又不至于一败涂地的唯一方法,就是用定义清晰的接口把若干模块组合起来。如此一来,多数问题只会出现在局部,那么还有希望对局部的修改,不会影响到全部。
- 怎样划分模块
看你要怎么解决问题。
模块化-是要求面向API编程。模块之间,使用一组定义良好的调用和数据结构来通信
实际上,有能力的开发者,都是先定义接口。为其注释加以描述,而后再编写代码。
理论上,模块可以被划分的很大或者很小。但是很大和很小都会和 bug 有关联。
根据这个研究曲线,一个模块的代码逻辑行大概处于200-400最佳。那真实的代码中,考虑到注释,空行等,可能处于400-800的物理行数。
强行的满足这个区间,墨守成规,是有问题的。但是,设计的时候,可以考虑一下。
我们的目标是降低维护代码的人力成本,要程序员少做决策,如果一个模块大小符合人类科学认知范围,对减少bug会有很大的帮助。
没有bug,或者很少有bug,那是多么让人开心的一件事。
二、紧凑性和正交性
- 紧凑性
紧凑性一个设计能否装进人脑的特性。
如果一个大的程序总能被拆分成若干模块,模块之间通过定义良好的API通信。这样可以每次修改的时候,可以将修改控制在比较小的范围内。
而如果每个模块都是紧凑的,都是特别容易装进人脑的。程序员就可以更有效率的开发和维护整个模块,提升效率,并且减少bug.
正常人能够记忆的不连续的信息点的数量是7-2 到 7+2 。
这样分析,一个模块的API数量最好在这个范围内,一个结构体的成员数量在这个范围内。
这里必须指出,API不要只看数量,而是要看逻辑点。比如,对某一数据的get/set操作,虽然是要两个API,但是只要封装规范的,对于人来说,其实是一个信息点。
紧凑性不意味着小,关键目标是为了让人一看就懂,一用就会。也就是那些符合人类使用习惯的,就做成这样的。而不符合人类习惯的,要控制在7-2到7+2的范围内。
有时候,是必须要牺牲紧凑性的。但是要尽量考虑。
如果一个工具让你感觉简单好用,用起来很舒服,那就说明是紧凑的。
- 正交性
正交性是一个修改没有副作用的特性。
我认为,当前模块,定义好自己的职责,不要和其它模块耦合,例如:不要使用全局变量。只做好自己的职责,就是符合正交性的。
编写正交的系统,会得到两个好处,提高生产率和降低风险。
因为你改了A,就只影响A,你不用考虑其它的,所以减少了做的决策。
如果组件的定义明确,还能复用,减少了修改代码的数量。
三、在编写代码前,问问这些问题
- 有多少全局变量
全局变量是模块化毒药。很容易使得各个模块轻率混乱的耦合。
- 单个模块的大小有多大,是不是在合理的范围内?
- 模块内单个函数是不是太大了。其实是看这个函数内的信息量。不一定是看行数。
就我个人而言,如果局部变量太多了,我倾向于拆分成子程序。另一个方法是看代码行是否存在太多缩进,我几乎从来不看代码长度。 ----Ken Thompson
- API 的定义清楚吗?容易描述清楚吗?有副作用吗?
- API 入口点是不是超过7个?数据结构成员是不是超过7个了?