3.2.1 从文档到程序
我方向感比较强,去一个新地方之前,必须先简单研究一下地图,有个大致脉络,才不会晕头转向。同理,你让我冒然去阅读或审核一大堆代码,我会立马陷入细节中,晕头转向了。
我们人类的大脑擅长逻辑分析,擅长关联推理,擅长脉络架构,但唯独不擅长记忆,更难以同时关注多个对象。
很不巧,如果不加控制,大多数产品的代码都是粗暴的碎片化堆砌。缺个子函数,前面堆一个,但阅读时不会先读后面在跳前面;少个新功能,随意找个文件安置,但审核时要频繁查找跳来跳去;类似的情况比比皆是,也经常导致代码审核在大多数情况下会成为瞎眼流程。
我刚加盟跨国研发团队时,首先是产品架构培训,这部分主要是图和语言交流,接受起来相对容易。架构培训完毕后,当我计划信心满满的面对代码时,但看到数以百计的程序文件后,立马就蔫了。
一个特殊的培训救了我,这个培训叫程序映射清单,用于完成设计文档和程序之间的映射,当然里面要考虑的因素很多,我会在第6章给大家详细演示这个过程。目前,我们仅需要知道,通过这个映射清单,我们阅读任何一个函数代码时,可以很方便的将其放入整个框架设计中。本章侧重于约定某一个模块的程序文件长啥样,第6章架构设计部分侧重于如何组织这些模块的源文件。
一句话概括:我们读代码时,有方向感了。
◇◇◇
从架构文档到程序代码,首先面对的就是程序文件。
我们团队的嵌入式产品大多是用c语言实现的,c语言包含两类,头文件(.h)和源文件(.c)。头文件涉及c语言的一个基本概念,所有的函数、变量、结构等在使用前必须声明。
以前,我经常采用如下一些做法,如:
- 感觉一个模块代码量不大,索性就将几个模块塞在一个文件中了;
- 省略头文件,到处使用extern引用,或者用到什么函数时,就近写声明;
- 模块和c文件干脆就是n:n的映射关系。
……
稍微复杂的产品,其模块都非常多,一大堆模块堆在一起,容易混乱。此时,最常见的做法就是分层,将整个架构分为多层,每一层包含了若干个模块,上层模块通过层接口调用下层。
为了应对这种情况,每一层应该有自己的独立层声明头文件,其中会罗列一堆模块头文件,如下所示:
#include “ai.h”
#include “ao.h”
#include “di.h”
#include “do.h”
……
如果整个产品架构分为多层,一般情况下,层之间的接口是清晰的,但层内各模块之间或多或少会存在着各种耦合,如遥测模块越限生成遥信数据等等之类。此时,需要在层内增加一个私有的头文件,便于层内模块引用。借鉴C++语法习惯,我们项目组习惯将该头文件命名为“层名Private.h”,统一的名称不仅便于记忆,也便于后期代码级复用。该文件内部会罗列一堆私有头文件,如下所示:
#include “aiPrivate