软件架构是体现在其组件中的系统的基本组织,它们之间的相互关系和环境,以及指导其设计和发展的原则[1]。软件架构不意味着一次就可以创建并固定下来。相反,在嵌入式开发中,软件架构应该在产品的整个生命周期中不断发展和变化。
在实施过程中经过思考并不断发展的软件架构有很多好处,例如:
充当正在建设的项目的路线图
提供可用于培训工程师和向管理层和利益相关者解释软件的软件图
最大限度减少不必要的返工
降低开发成本
团队可以使用五个步骤来开发和发展他们的软件架构:
1.分离软件架构
3.分解系统
4.界面和组件设计
5.模拟、迭代和缩放
今天让我们来了解一下第1个步骤。
步骤 1–分离软件架构
许多嵌入式开发团队将他们的软件架构视为一个单一的内聚架构,包括应用程序代码和硬件交互。以这种方式看待架构并不奇怪,因为嵌入式软件工程师通常从硬件的角度来看待他们的系统。嵌入式软件是独特的,因为它必须与硬件交互,这不同于所有其他软件工程领域。虽然这是真的,但是现代软件架构师将会并且应该把依赖于硬件和独立于硬件的软件分开,如图1所示。
图1——嵌入式软件架构分为硬件相关和独立架构,通过抽象层进行交互。(图片来源:嵌入式软件设计[2])。
传统上,开发人员将设计和实现他们的架构,以便硬件的独立层和依赖层紧密耦合。但是不幸的是,紧密耦合的架构有很多问题。
紧密耦合架构的问题
首先,它们不太便于携带。例如,如果微控制器突然变得不可用,会发生什么?如果代码是紧密耦合的,那么试图将应用程序代码转移到新的微控制器上运行就变得非常困难。应用程序代码与微控制器上的底层硬件调用紧密耦合!如果嵌入式开发人员不更新他们的架构,他们就不得不重新检查所有的代码,并修改与硬件交互的每一行代码。更新架构的公司通过抽象和依赖注入打破了架构耦合。
其次,在开发环境中而不是在目标硬件上对应用程序进行单元测试几乎是不可能的。如果应用程序代码直接调用硬件,大量的工作将进入测试工具以成功运行测试,或者测试将需要在硬件上完成。在硬件上进行测试是缓慢的,并且通常是手动的而不是自动化的过程。结果是软件没有得到很好的测试,整个系统的质量受到影响。此外,交付软件可能需要更长时间。
最后,紧密耦合的架构会有可伸缩性问题。紧密耦合的系统通常共享数据。随着软件系统试图增长和增加新的特性,每增加一个新的特性,增加新的代码就变得更加困难。组件之间的交互、访问共享数据的能力以及出现麻烦的缺陷的机会都急剧增加。因此,尽管嵌入式开发人员努力工作以完成工作,功能开发可能会停滞不前。
分离架构如何解决问题
将软件架构分成依赖于硬件的和独立的架构解决了紧密耦合架构的所有问题。例如,在硬件相关架构和独立架构之间创建一个抽象层,可以将应用代码从一个微控制器转移到下一个微控制器。抽象层打破了硬件依赖;换句话说,应用程序不知道也不关心硬件。相反,应用程序依赖于接口。新的依赖于硬件的组件只需要满足接口的要求,这意味着如果我们改变硬件,只有硬件模块改变!而不是整个代码库。
在两个架构之间添加一个抽象层也解决了单元测试的许多问题。有了抽象层,就更容易创建向应用程序代码返回预期和意外数据的测试替身和模拟。我们甚至不需要硬件就可以编写所有的应用程序代码!
当我们保持我们的体系结构独立,并专注于最小化耦合时,扩展软件就变得容易多了。然而,仅仅因为我们分解了架构并不意味着我们不能在每个架构中产生耦合和内聚的问题。我们仍然需要确保我们遵循固体两种架构中的原则。好消息是,它允许嵌入式开发人员独立关注每个架构,这意味着实时和硬件约束问题不会进入核心应用程序逻辑。
最后一个好处是,通过分离依赖于硬件和独立的架构,我们可以在硬件可用之前专注于开发和交付应用程序。这样做的好处是,客户和管理层可以提前访问应用程序并提供反馈。然后迭代应用程序并关注于确保它满足实际需求的能力变得更加易于管理。今天,太多的团队专注于首先准备好硬件,而核心应用程序是事后才想到的。这不是设计和构建系统的方法。
软件架构设计第1步结论
软件架构可以帮助团队控制他们的软件。成功的软件架构通常是通过迭代和演化创建的。设计软件架构的第一步是认识到嵌入式系统不只有一种架构。取而代之的是两种架构:硬件依赖型和独立型架构。有目的地分离这些架构允许嵌入式开发人员利用现代软件技术和方法来改进上市时间、质量和开发成本。