3. 系统设计阶段:架构设计原则、模块划分与接口规范

系统设计阶段,说白了就是把需求文档翻译成工程师能看懂的技术蓝图。我见过太多项目栽在这一步——需求写得天花乱坠,一到设计就漏洞百出。今天咱们就聊聊怎么把这块硬骨头啃下来。

3.1 系统架构设计三大原则

做架构设计这些年,我总结出三条铁律。你想想看,违背任何一条,后面都得返工。

原则 核心思想 我的经验
高内聚低耦合 模块内部功能紧密,模块间依赖最少 耦合度每降低10%,后期维护成本能省30%
关注点分离 不同功能域拆到不同模块 我曾经把通信和业务逻辑混在一起,改协议时差点重写整个系统
接口稳定优先 接口定义后尽量不变 接口每改一次,至少影响3个模块的联调

核心观点:架构设计不是画完图就完事,它要能指导编码、测试、集成全流程。好的架构,能让团队里最菜的工程师也写不出太烂的代码。

3.2 模块划分方法

模块怎么切?我个人习惯用「功能域 + 数据流」双维度分析法。先按功能划大块,再按数据流向细化。

3.2.1 功能域划分

  • 输入域:传感器采集、按键检测、通信接收
  • 处理域:算法运算、状态机管理、协议解析
  • 输出域:显示驱动、电机控制、通信发送
  • 管理域:电源管理、故障诊断、日志记录

小技巧:每个模块的代码量控制在2000行以内。超过这个数,我建议你考虑拆分子模块。我在一个项目里见过8000行的模块,后来没人敢动它。

3.2.2 数据流驱动划分

画一张数据流图,看看数据从哪来到哪去。每个数据转换点,就是一个潜在的模块边界。

// 不好的划分:功能混杂
void system_task(void) {
    read_sensor();      // 输入
    calculate();        // 处理
    send_data();        // 输出
    check_battery();    // 管理
}

// 好的划分:职责清晰
void sensor_task(void) { /* 只做采集 */ }
void process_task(void) { /* 只做运算 */ }
void comm_task(void) { /* 只做通信 */ }
void monitor_task(void) { /* 只做监控 */ }

3.3 接口定义规范

接口定义是系统设计的命门。我曾经因为接口没定死,导致两个团队联调了三个月。嗯,这里要注意几点:

3.3.1 接口命名规范

类型 命名规则 示例
全局函数 模块名_动作_对象 uart_send_byte()
回调函数 on_事件_模块 on_data_received_uart()
数据结构 模块名_类型_t uart_config_t
宏定义 模块名_含义 UART_BAUD_115200

3.3.2 接口文档模板

/**
 * @brief 通过UART发送一帧数据
 * @param port   UART端口号 (0-3)
 * @param data   数据缓冲区指针
 * @param len    数据长度 (字节)
 * @return 0: 成功, -1: 参数错误, -2: 发送超时
 * @note 调用前需确保UART已初始化
 *       发送超时时间默认为100ms
 */
int uart_send_frame(uint8_t port, uint8_t *data, uint16_t len);

避坑指南:我曾经在接口里用了可变参数,结果不同编译器处理方式不一样,导致现场崩溃。从那以后,我坚持接口参数必须明确、固定、可测试。

3.4 系统架构设计文档模板

文档不是写给领导看的,是写给三个月后的自己看的。我建议包含以下章节:

  1. 概述:一句话说清系统做什么
  2. 架构图:模块框图 + 数据流图
  3. 模块清单:每个模块的职责、输入、输出
  4. 接口定义:所有跨模块接口的详细说明
  5. 关键设计决策:为什么选这个方案,放弃了什么
  6. 约束条件:硬件资源、实时性要求、安全等级

我的习惯:设计文档里一定要写「为什么」。光写「我们用了RTOS」不够,要写「因为任务响应时间要求小于5ms,裸机无法满足」。这样后来者才能理解你的思路。

3.5 系统架构设计流程(SVG)

下面这张图是我做系统设计的标准流程。每个项目都走一遍,基本不会出大问题。

系统架构设计流程 需求分析 功能域划分 模块定义 接口设计 评审确认 文档归档 评审不通过,返回修改 每个阶段都要有产出物,评审通过后才能进入下一阶段

3.6 常见设计误区

做系统设计这些年,我踩过不少坑。挑几个典型的说说:

  • 过度设计:一上来就想搞分布式、微服务。其实嵌入式系统,很多时候一个MCU加个RTOS就够了。
  • 忽视非功能需求:只关注功能实现,不考虑功耗、实时性、可靠性。我有个项目就是功耗没算好,电池撑不过半天。
  • 接口定义太粗:只写了函数名,没写参数范围、返回值含义、错误码。联调时全靠猜。
  • 文档和代码脱节:设计图画得漂亮,代码里全变了。我建议每两周对齐一次文档和代码。

我的建议:系统设计阶段多花一周,后面能省一个月。别急着写代码,先把架构想清楚。你想想看,盖楼的时候地基没打好,后面装修再漂亮也白搭。