代码之家  ›  专栏  ›  技术社区  ›  Gabe

固件工程师能从软件工程师那里学到什么?[关闭]

  •  24
  • Gabe  · 技术社区  · 15 年前

    从我对固件工程工具、实践等历史的了解来看,它已经连续几年落后于软件工程领域。例如,据我所知,在固件世界中仍有相当多的争论关于C++是否真的值得为我们的应用程序使用,并且一些C++编译器明显缺少(Microchip)?!?).I设想这在很大程度上是由于固件和软件之间的需求差异造成的。同样,从历史来看,经过适当审查的工具和技术进入固件世界似乎只是时间问题。

    现代软件工程师经常使用的方法、工具、最佳实践等,固件工程师也可以利用哪些方法、工具、最佳实践来改进他们的工艺?

    具体来说,我是沿着以下轴思考(但不要让它们限制你):

    • 提高代码清洁度/可维护性
    • 减少缺陷引入,提高检测水平
    • 改进文档
    • 需求管理
    • 提高可重用性

    我也希望看到嵌入式商店对答案进行回答或评论,以提供关于理论可行性或更好的个人体验的反馈。

    更新
    我特别有兴趣跳到曲线前面一点。所以比较新的东西已经被很好地审核了(对大多数人来说都很好),比如C++、TDD等等。你一直在使用什么和爱?

    更新2
    到目前为止,我在答案中得到了很多很好的通用编程建议,这很好,但我确实在寻找更多的非常规方法,这些方法已经证明对人们来说是成功的。我试着挑逗敏捷实践者、开发人员,以及你们中的其他人,他们已经尝试过一些东西,并且看到它在黑桃中得到回报,或者失败得很惨。作为一名软件工程师,在过去的几年中,是否有一种工具或实践对您产生了显著的正面或负面影响?

    9 回复  |  直到 15 年前
        1
  •  22
  •   James Grenning    15 年前

    固件工程师能从软件工程师那里学到什么?很多!

    我很惊讶今天的固件开发实践与25年前我们首次使用C进行嵌入式开发时的相似。C是汇编程序向前迈出的一大步,但固件工程师可以也应该从中吸取更多的经验教训。是的,有些工具更好,但许多实践都停留在70年代和80年代。

    除了非嵌入式开发人员面临的挑战外,嵌入式软件开发确实增加了一些额外的挑战。但是,熟练的软件开发人员使用的所有原则和实践都适用于嵌入式开发。顺便说一句:不仅仅是嵌入式软件开发人员不具备这些最先进的实践,还有许多非嵌入式软件开发人员。

    我认识的和认识的做固件的人大体上是一个非常熟练的团队,致力于解决难题。不幸的是,无论出于什么原因,许多人都没有跟上软件世界的发展。我认为这与固件工程师建立的假想屏障有关。

    嵌入式和非嵌入式开发人员使用不同的语言,但解决了类似的问题。保持嵌入式代码独立于硬件设备基本上与保持应用程序代码独立于UI或数据库相同。基本原则是相同的。

    下面是一些我认为嵌入式开发人员应该注意的事情。这些原则和实践中的一些可以直接使用,而其他一些则可能需要一些调整来处理嵌入的挑战。如果你想用“固件”这个词来代替下面的“软件”,继续说吧,我并没有真正区分这两者。

    依赖管理

    必须管理模块之间的依赖关系。从软件到硬件的依赖性是一种特殊情况,必须由嵌入式软件开发人员主动管理。如果您不管理依赖关系,它将管理您。

    实际上,这意味着只有有限的软件模块子集才应该了解底层硬件(和操作系统)。随着硬件的发展,而且总是如此,对独立于硬件的代码的投资可以保留下来。 看到我 ah ha! 时刻。

    罗伯特·马丁写了大量关于固体设计原则的文章。嵌入式开发人员应该了解它们并将它们应用到他们的设计中。

    • S-单一责任原则
    • 开闭原理
    • L-Liskov替换原理
    • 界面分离原理
    • D依赖反演原理

    这些原则导致设计更好地经受住时间的考验。坚实的原则鼓励创建具有凝聚力和独立性的模块。它们建立在面向对象的思想之上,但是可以应用到C中。我们必须停止函数调用数据结构,因为这在嵌入式C代码中非常常见。

    C++与面向对象语言

    为什么你不能使用C++和OO?因为它们太慢或太大。事实是什么?C++是一种大而神秘的语言,但你不必使用它。看一看 Why are you still using C?

    C++弥补了C不太有用的一些问题,比如:

    • 封装和信息隐藏
    • 接口编程
    • 可替换对象
    • 临时初始化

    C++可以有效地用于嵌入式开发。你确实需要一个C++编译器和净空。也许这在你的世界里是不可能的,或者这是做生意的成本。从学习开始:

    • 类-这些是具有成员函数和成员数据的结构。
    • 构造器-这些可以随时正确地进行初始化。
    • 析构函数-如果你学习构造函数,你还必须学习析构函数来保持宇宙的平衡。
    • 继承-主要用于定义只包含纯虚拟函数的接口。接口提供了重要的依赖性中断和灵活性点。这些通常是不公正地阻止嵌入。这里不应该有神秘或偏见;虚拟函数是引擎盖下的函数指针。有效使用接口的替代方法是复杂的条件逻辑,嵌入式C程序通常有太多的条件逻辑。

    如果嵌入式开发人员使用C++的这些部分,他们可以构建更灵活的设计,而不会带来高成本。

    测试驱动开发

    这可能是最大的游戏改变者。我很高兴看到其他帖子也提到了这一点。TDD可以帮助防止现在和将来的缺陷。看看为什么TDD会有助于了解 The Physics of TDD .

    嵌入式确实为TDD带来了一些独特的挑战。例如,TDD需要一个非常快速的增量编辑/编译/链接/运行周期。对于许多嵌入式开发人员来说,这意味着要小心 依赖管理 首先在目标上运行单元测试。更多地了解 adapting TDD for Embedded .

    使用TDD,您将创建经过彻底测试的代码。全面的自动化测试覆盖范围充当一个安全网,允许随着需求的变化安全地更改代码。意外的后果立即被发现。

    同时,进行的测试 you get almost for free ,允许您无畏地重构代码…

    连续重构

    代码只写一次,但读了很多次。然后它被改变和调整,导致设计随着时间的推移而退化。如果开发人员不不断地重构以保持代码的整洁,那么代码就会变得一团糟。也许你们中的一些人正在处理这些乱七八糟的事情。TDD的自动化测试实现了低成本和低风险的重构。

    持续集成

    自动化构建过程。让它在每个工作区签入时运行。对于将编译后的代码放入目标中所需的异构工具集来说,这是一个挑战,但它仍然是正确的目标。

    嵌入式开发人员越早知道某个更改与其他工作不兼容,修复它的速度就越快,在痛苦的合并中花费的时间就越少。

    增量交付

    找到方法来分割工作,这样就可以避免大量痛苦的集成,并且可以尽早尝试设计思想。避免沿着体系结构线拆分,重点是提供可见功能的切片。

    协作

    嵌入式开发人员!离开那里,一起工作。当你只看到自己的代码时,你怎么能变得更好呢?当你是技术方面的专家,掌握了技术,并且没有机会在不同的领域工作时,你怎么能改进呢?

    在那里有很多东西要学。你有责任尽你所能

        2
  •  15
  •   kgiannakakis    15 年前

    我既做过嵌入式软件工程师,也做过软件开发人员。在这两个世界中,我已经了解到,无论您的系统拥有多少资源和您正在编程的语言,都有许多事情可以使您的生活更轻松。

    第一件事是你使用的工具。在嵌入式软件中,大多数时候您只处理编译器/链接器。不止这些。diff工具、正则表达式、脚本语言、文档工具可以节省大量时间。

    另一件事是代码质量。人们需要遵循样式约定,经历定期的重构周期,并且通常要记住,代码读取比代码编写更频繁,拥有更可读的代码确实是值得的。

    在嵌入式软件中,有时我们会完全错过设计阶段。嵌入式项目通常不如桌面/服务器项目大,但这并不能成为没有进行适当设计的借口。

    软件需要单独测试,而不仅仅是作为设备的一部分。为了测试软件是否符合要求的规格,为您的系统构建一个软件模拟器真的节省了很多时间。当整个系统、硬件和软件准备就绪时,这样做的成本要高得多。

        3
  •  7
  •   Simon P Stevens    15 年前
    • 源控制
    • 单元测试(TDD)
    • 持续集成(或夜间构建)
    • 缺陷跟踪

    我曾经合作过的固件工程师都不做这些事情。

    单元测试可能不适用于所有类型的固件。我想象当它在物理硬件上运行时很难进行单元测试。我想这取决于你是否有可用的模拟器。

        4
  •  5
  •   Community holdenweb    7 年前

    假设“固件工程师”是指“嵌入式软件工程师”,那么我的答案是:他们 软件工程师,所以在可能的情况下,他们应该和其他软件工程师做同样的事情。

    显然,为嵌入式系统编写软件需要一些不同的技能,例如目标处理器的详细知识,并且能够处理有限的资源(与PC或类似设备相比)。

    正如其他人所提到的,单元测试由于可能必须在运行在PC上的模拟器上进行这一事实而变得复杂,尽管这一事实非常有用,但决不能替代对真实系统的彻底测试,特别是考虑到嵌入式系统所受事件的异步性。

    我关心的一个问题是,为什么嵌入式软件看起来“落后于曲线”,是因为软件工程——作为其中的一部分,嵌入式软件——一般都没有在电子工程学位上进行任何深度的教学。考虑到如今电子工程师的职业生涯中有多少时间是花在编码上的,这似乎是一个巨大的疏忽。

    幸运的是,有些人正试图弥补这一点。我强烈建议你阅读杰克·甘斯勒的文章 his website 在他的专栏里 embedded.com )

    此外, MISRA-C 不久前,为了避免汽车工业中C软件中常见的错误源而创建的,自那以后,他的软件被许多嵌入式软件界所采用。添加静态分析检查器 PC-Lint ,而且您已经采取了一些方法来改进代码。

    在许多情况下,工具供应商也没有通过创建自己的IDE来帮助他们,而此时最好将精力集中在编译器和调试器上,并将IDE留给其他人,例如Eclipse。

    顺便说一下,关于嵌入式系统中不使用C++的更多信息,请参见 this question .

    最后:因为固件工程师是软件工程师,所以我们面临着许多相同的问题、挑战和关注,所以我们应该使用相同的资源;毕竟,周围有很多这样的资源,您正在阅读其中的一个!

    我经常访问的其他一些网站包括:

    编辑: 在回应Gabe的评论时,“我们应该寻找哪些工具来适应?”下面是几个例子:

    独立于编译器的IDE: plenty of IDEs 对于C,但是据我所知,如果没有兼容的编译器,它们中的很少一个可以发挥它们的潜力。我希望看到编译器开发人员和IDE开发人员融合在一起,这样,理想情况下,任何编译器都可以与任何IDE一起使用。

    在没有兼容编译器的情况下,我希望能够使用pc lint(或等效工具)作为我的“官方”编译器,并使用我选择的IDE。

    模拟和建模: 模拟工具如 Simulink 允许对PC和一些高端嵌入式处理器的软件进行模拟、建模和测试。像这样的工具对较小的芯片同样有用,所以很高兴看到它们扩展到市场的那个领域。

    附言:本周杰克·甘斯勒的专栏题为: What makes embedded different? “,因此(松散地)与上述问题相关。

        5
  •  3
  •   Eugene Yokota    15 年前

    不确定什么程度的软件被视为固件(BIOS、驱动程序或实用程序),但我听到的标准抱怨是UI是非标准的。意识到用户界面很重要,它应该遵循一些标准或传统,这是件好事。

    就C++而言,可以很容易地理解它,因为与C相比,有很多开销,就像是一个带有LIBC的汇编语言,而在C++中,甚至一个简单的函数调用也可以是虚拟的。鉴于语言的复杂性,实现完全C++运行时不是那么容易。

    在软件开发“最佳实践”方面有太多的事情要列出(我讨厌这个词)。为什么不从 The Joel Test: 12 Steps to Better Code.

    Joel Test

    1. 是否使用源代码管理?
    2. 你能一步完成一个构建吗?
    3. 你每天做建筑吗?
    4. 你有错误数据库吗?
    5. 在编写新代码之前,您是否修复了错误?
    6. 你有最新的时间表吗?
    7. 你有规格吗?
    8. 程序员有安静的工作环境吗?
    9. 你用的是钱能买到的最好的工具吗?
    10. 你们有测试人员吗?
    11. 新应聘者在面试时是否写代码?
    12. 你做走廊可用性测试吗?
        6
  •  2
  •   Indy9000    15 年前

    固件工程相当广泛。从pic到dsp,它们都有不同程度的物理资源。如今,DSP功能相当强大(与CPU的5年前相当),可以支持大量内存等,但您又可以使用几千字节的pics。资源越少,程序员就必须使用巧妙的黑客来充分利用设备。重点是“让它工作”,而不是“编写优雅的代码”。

    我想看到的是好的项目管理工具,包括代码和文档,因为您必须参考大量的数据表、分散在网络周围的设计文档和电子邮件blobs等。

    我也希望看到更好的DSPs的DeV工具(TI:请把CCS交给某个擅长制作IDE的人),还有更多的使用C++的图书馆生产商(我在看你的ATEME)来构建更好的库。

    而且,硬件工程师对目标定位有更好的理解,而不是脱口而出,“如果是C++,它会很慢”。

        7
  •  2
  •   dwhall    15 年前

    让我先谈谈你问题中的一个假设。假设是嵌入式软件工程师(ese)不知道或不知道现代软件工程实践,需要学习新的实践。这个假设应该马上被推翻。我相信你会发现与非嵌入式SES相同的统计分布,他们的技能和技术保持最新。

    所以,也许你的问题会变成一系列的问题,比如:

    1. 为什么ESES使用单独的代码编辑器和命令行编译器而不是IDE?
    2. 为什么在大多数嵌入式项目中C优于C++?
    3. 为什么嵌入式世界中没有那么多的编程实践实验?

    以下段落回答了这些问题。

    1. eses通常使用特定的代码编辑器,因为这是个人偏好,或者是他/她的公司所使用的。IDE并不常见,因为ESE与硅的工作非常密切,并非所有芯片制造商都为其芯片系列开发了一个IDE。只有ARM等市场渗透率最高的芯片才有足够的动力支持基于IDE的工具的开发。此外,一个IDE不能像桌面开发人员那样为ESE提供足够的帮助。IDE为大型API提供了黏合到GUI或代码完成的帮助;两者都不是常见的,也不像嵌入式世界那样标准。

    2. 我确信,在嵌入式系统中,C为什么比C++更适合编写,而不是我可以当场编写的。缺点是你用的是有效的。C工作更常见(更多程序员知道C而不是C++)。另一个原因可能是OO方法论是为了帮助程序员通过将解决方案抽象为可管理的概念对象来解决大问题而设计的。在嵌入式世界中,这些问题通常被简化为尽可能小的一个问题(和解决方案),这样嵌入式系统就可以通过更小的代码库变得更加可靠。

    3. 由于嵌入式产品通常比桌面程序更不容易出错,并且具有更高的可靠性,因此,ESES的实验较少。这意味着严格应用久经验证的实践,并在测试中花费更多的时间。为什么?因为通常没有可行的方法来升级嵌入式设备的固件;这可能是因为系统部署超出了范围,也可能是因为更新数百万设备的成本而不可信。

    总之, 与非嵌入式SE一样,eSE使用最适合其需求的工具和实践。 作为一个练习ese的人,我相信嵌入式软件的规则与我的非ese朋友所相信的要大得多。因此,编程实践的明显差异不在于ESE需要学习现代实践,而在于非ESE需要了解嵌入式编程有多不同。

        8
  •  2
  •   Gerhard    15 年前

    自动化测试
    不要用肉眼扫描你的模拟输出来检查是否一切正常。你需要全面的自动化测试,因为你总是会错过大量的波形。

    版本控制
    你不会记得工作版本是什么。使用版本控制软件,这样你就知道用什么来编程。

    缺陷追踪系统
    你迟早会忘记的。错误日志应该包含首先检测到问题的版本(请参阅版本控制)和修复问题的版本。

    哎哟! 我以为你的意思是固件在FPGA中,但同样适用于嵌入式软件。如果你已经有了这些流程,那就别想了。 unconventional approaches 直到把基础知识做好。

        9
  •  0
  •   nik    15 年前

    这可能有点离题。
    对固件列的简短引用,位于 Embedded ,

    我一直在Embedded上找到关于固件工程的好文章。
    可能很多人对这个问题也感兴趣…