返回列表
工程
设备控制软件开发的若干建议
设备控制软件运行环境与常规软件不同 — 调试器最少化、日志策略、条件式编写规范、兼容性考量。多年现场总结的实战经验。
6 分钟阅读· ICT Engineering
设备控制软件开发与一般软件开发存在不同的环境约束。运行在量产设备上的代码的特殊性,以及一次失误带来的代价,让下面这些建议年年值得复读。
设备控制编码建议
设备控制 SW 开发有其特殊环境,以下方面与一般软件开发不同:
- 调试器最少化 — 设备运行时几乎无法附加调试器。请充分利用日志,并锻炼快速阅读源码的能力。
- 结构设计 — 先看大图,落到代码时再聚焦细节。
- 客户需求分析 — 不要只看表面请求,花时间找出根本原因。
- 导出共同条件 — 寻找能涵盖多种条件且抓住核心的简单共通条件,可以减少分支。
- 修改的副作用 — 一处修改可能引发十处问题。多加一个 checkbox 选项,测试用例与 bug 都会翻倍。
- 代码分支成本 — 同一台设备分两份代码维护,工作量增加 1.5 倍,但维护成本和 bug 翻倍。
- 新驱动测试 — 新增驱动先在一台设备上充分测试,再投入到量产设备。
- 发布清单 — 不要只发布可执行文件,确认版本升级所需的新增文件全部包含在内。
- 日志策略 — 关键条件、时序、数据务必记录日志。异常路径下尤其必要。无意义的日志请及时清理。
- UX 基础 — 归根结底,对使用者的体贴最重要。
条件式书写原则
让读者按自然顺序读出语义。
- 把最大的前提条件放前面。
- 同一层级时,把更不容易为
true的条件放前面(短路求值更快、更早失败)。 - 不要使用整体否定
!(...)— 读者得在脑子里再翻一次。
// GOOD
if (A == false && B == false && C == false) { ... }
// BAD
if (!(A || B || C)) { ... }比较表达式中,把变量放在左边,常量放在右边 — 与自然阅读顺序一致。
// GOOD
if (A > 2) { ... }
// BAD
if (2 < A) { ... }返回指针的函数设计
返回指针的函数在出错时若返回 NULL,调用者很容易漏掉空检查,结果通常是设备停机。
- 尽量返回有意义的 Dummy 数据指针,让程序不至于挂掉。
- 但必须记录日志,以便追踪哪里触发了 fallback。
UI / UX
- 添加
XEdit等输入控件时,设置合理默认值。空字段会迫使用户每次都重新填入。 - 未保存时离开画面,应让数据自动还原。"不保存" 的预期行为必须一致。
管理与优化
- 客户的要求过于轻易答应,它们就会成为理所当然的标准。
- 一旦发现重复代码,立即提取为函数。拖延一下,两份代码就会发生分叉。
- Include Path 应配置在每个项目中,而非全局。降低环境依赖。
- 项目过半后,就应开始考虑退出策略(交接、文档、日志整理)。
日志与可搜索性
日志中写函数名时,不要加括号 () — 会降低搜索效率。
// GOOD
LOG_PRINTF("", "DoFunc 执行中");
// BAD
LOG_PRINTF("", "DoFunc() 执行中");兼容性与场景
- 添加功能前,先考虑与现有数据的兼容性和对量产设备的可应用性。数据迁移的成本经常被低估。
- 时序出现问题时,在能清晰复现时序与场景之前不要停止追查。"偶尔会发生" 在量产后只会更贵。
开发工具与语言
请使用强大、便利的开发工具与语言。
- 通用: Visual Studio (C++, C#)
- 控制专用: BeckHoff TwinCAT、CodeSys
- ICT 自研一体化控制 IDE: QMachineStudio — 时序、GUI 与运行时调试集成在一起。
好的工具与强大的语言,会显著提升开发效率。即便已经习惯当前的工具链,也建议定期审视开发环境。
PC 控制自动化编码规范调试设备开发