同一个公司的不同芯片,测试程序里有很多相似的东西:电源上电时序、开短路测试、漏电流测试、寄存器读写函数……很多人是这么做的:新开一个项目,把老程序复制过来,删掉不要的,加上新的。然后就有了好几个长得很像但又不太一样的程序。今天改了A程序的一个bug,明天发现B程序也有同样的bug,又得改一遍。 模块化设计就是为了解决这个问题。 一、什么是模块化 模块化就是把常用的功能封装成独立的模块,多个程序共用。而不是每个程序都自己写一遍。 举个例子,开短路测试。大部分芯片都要测。模块化以后,你只需要维护一份开短路测试的代码。所有用到这个功能的程序都调用它。今天发现开短路测试有个bug,改一个地方,所有程序都同步修复。 二、哪些东西适合模块化 硬件操作层 测试机底层的API,比如设置电压、测量电流、读写寄存器。这些是基础操作,所有程序都要用。可以封装成一层中间函数,隔离底层硬件的差异。以后换测试机,只需要改这一层,上层程序不用动。 通用测试项 开短路测试、漏电流测试、电源电流测试、上电复位测试……这些是几乎每个芯片都要测的。封装成独立函数,参数通过结构体传入。 计算和转换函数 电压转码值、电流转系数、温度补偿算法……这些纯计算的逻辑,封装成函数,方便单元测试。 配置和初始化 测试机初始化、Loadboard配置、通道映射、时序参数加载。这些放在独立的配置模块里,不要散落在主程序中。 三、模块化设计的原则 原则一:一个模块只做一件事 一个函数只干一件事。比如measure_leakage()只测漏电流,不要再在里面顺便测别的。单一职责的模块更容易理解,也更容易复用。 原则二:模块之间松耦合 模块之间尽量减少依赖。比如开短路测试模块不应该直接依赖某个全局变量,而是通过参数传入需要的数据。松耦合的模块更容易单独调试和替换。 原则三:用参数配置,不要硬编码 模块内部不应该写死具体的电压值、限值。这些通过参数传入。比如measure_leakage(vdd, limit_ua),而不是在函数内部写#define LEAK_LIMIT 1e-6。 原则四:模块要有文档 每个模块的功能、输入参数、输出值、使用示例,都写清楚。不一定长篇大论,但关键信息不能少。 四、常见错误 错误一:过度模块化 一个只有两行的函数也封装成模块。增加了阅读代码的跳转成本,得不偿失。 模块化的边界:如果这个功能只有一处用到,且逻辑简单,不需要封装。至少两处用到,或者逻辑比较复杂,再考虑封装。 错误二:模块之间有隐藏依赖 调用函数A之前必须先调用函数B初始化某个状态,但文档里没写。这是最坑人的。模块应该自己检查状态,或者在文档里明确写明前置条件。 错误三:参数通过全局变量传递 模块内部直接读写全局变量,而不是通过参数传入。模块和全局变量绑定,没法复用。改成参数传入,模块变成无状态的,哪里都能用。 错误四:没有版本管理 公共模块改了,但忘了通知所有使用它的程序,导致编译不过或者行为异常。公共模块应该有自己的版本号,并且在每个程序中记录使用的版本。 模块化不是一蹴而就的。可以从最简单的开始:把重复出现的代码段提取成函数。然后逐步把通用的功能移到公共模块。 几个要点再记一下: 重复两次以上的代码,考虑提取成函数 通用功能封装成独立模块,多个程序共用 模块之间松耦合,通过参数传递数据 公共模块要有版本管理 · 下次写新程序,先看看公共库里有没有能用的。没有的话,写完之后考虑放进去,方便下一个人。 |





