固件工程师可以从软件工程师那里学到什么?很多东西!
我惊讶于现在的固件开发和25年前我们开始使用C语言进行嵌入式开发时的实践方式有多么相似。C语言是从汇编语言迈出的一大步,但还有很多固件工程师可以并且应该从中学习的经验教训。是的,有些工具更好了,但许多做法仍停留在70年代和80年代。
嵌入式软件开发在非嵌入式开发者面临的挑战之上增加了一些额外的挑战。但是熟练的软件开发人员使用的所有原则和做法都适用于嵌入式开发。顺便说一句:不仅嵌入式软件开发人员没有掌握这些最先进的做法,许多非嵌入式软件开发人员也是如此。
我认识的和遇到的从事固件开发的人大多数都是非常有技能的人,致力于解决困难问题。不幸的是,由于某种原因,许多人没有跟上软件领域的发展。我认为这与固件工程师树立的一种想象中的障碍有关。
嵌入式和非嵌入式开发者使用不同的语言,但解决类似的问题。使嵌入式代码独立于硬件设备本质上与使应用程序代码独立于UI或数据库相同。底层原则是相同的。
以下是我认为嵌入式开发人员应该更加关注的一些事情。其中一些原则和做法可以直接使用,而其他一些可能需要进行一些调整以应对嵌入式挑战。如果你想在下面将软件替换为固件,那就去吧,我实际上不区分两者。
依赖管理
模块之间的依赖关系必须得到管理。从软件到硬件的依赖关系是一种特殊情况,嵌入式软件开发人员必须积极管理。如果您不管理依赖关系,它将管理您。
实际上,这意味着只有一小部分软件模块应了解底层硬件(和操作系统)。随着硬件的发展,投资于与硬件无关的代码可以被保留。看看我的啊哈!时刻。
Robert Martin在SOLID设计原则方面写了大量文章。嵌入式开发人员应该了解并将其应用于他们的设计中。
- S-单一责任原则
- O-开放封闭原则
- L-里氏替换原则
- I-接口隔离原则
- D-依赖反转原则
这些原则导致更能经受时间考验的设计。 SOLID原则鼓励创建具有内聚性和独立性的模块。它们基于面向对象的思想构建,但可以应用于C语言。我们必须停止在嵌入式C代码中过于常见的函数调用数据结构自由混用。
C++和面向对象语言
为什么不能使用C++和面向对象?因为它们太慢或太大了。事实是什么?C++是一种庞大而神秘的语言,但您不必使用所有功能。看看你为什么还在使用C?。
C++弥补了C语言无法很好解决的一些问题,例如:
- 封装和信息隐藏
- 面向接口编程
- 可替换对象
- 特定初始化
C++可以有效用于嵌入式开发。当然你需要一个C++编译器以及足够的空间。也许在你的世界中这是不可能的,或者这是做生意的成本。开始学习:
- 类 - 这些是带有成员函数和成员数据的结构体。
- 构造函数 - 这使得始终正确地进行初始化成为可能。
- 析构函数 - 如果你学会了构造函数,那么你也必须学会析构函数来保持宇宙的平衡。
- 继承 - 主要用于定义仅包含纯虚函数的接口。接口提供重要的依赖关系断点和灵活性点。这通常在嵌入式系统中被不公正地反对。这里应该没有任何神秘或偏见;虚函数在底层是函数指针。有效使用接口的替代方案是复杂的条件逻辑,这是嵌入式C程序通常存在过多的东西。
如果嵌入式开发人员使用C++的这些部分,他们可以构建更灵活的设计而不会产生高成本。
测试驱动开发
这可能是最大的游戏改变者。我很高兴看到其他帖子也提到了它。TDD可以帮助预防现在和未来的缺陷。要了解为什么TDD可能有所帮助,请查看TDD的物理学。
Embedded做TDD确实存在一些独特的挑战。例如,TDD需要极快的增量编辑/编译/链接/运行循环。对于许多嵌入式开发者来说,这意味着需要仔细进行依赖管理,并首先在目标上运行单元测试。了解更多关于
如何为嵌入式适配TDD。
使用TDD,您正在创建经过彻底测试的代码。全面的自动化测试覆盖作为安全网,允许在需求变化时安全地更改代码。不良后果会立即被发现。
此外,拥有
几乎免费获得的测试,使您可以毫不畏惧地重构代码...
持续重构
代码只写一次,但会被多次阅读。然后它会被修改和调整,导致设计随着时间的推移而退化。如果开发人员不断重构以保持代码清洁,它就会变成一团糟。 TDD的自动化测试可实现低成本、低风险的重构。
持续集成
自动化构建过程。每次工作区检入时运行它。由于通常需要使用异构工具集将编译代码放入目标中,因此这是一个挑战,但仍然是正确的目标。
嵌入式开发人员越早知道更改与其他工作不兼容,就可以更快地修复它,并减少在痛苦的合并中花费的时间。
增量交付
找到分割工作的方法,以避免大量痛苦的集成,并尽早尝试设计想法。避免沿着架构线分割,专注于交付可见功能切片。
协作
嵌入式开发者!走出你们的小天地一起工作。当你只看到自己的代码时,如何变得更好?当你是技术XXX的专家并掌握它时,如何在不同领域工作并提高自己的能力。
有很多东西需要学习。你会为实现最大化自我价值而负责。