APP下载

基于领域驱动和服务化的复杂嵌入式系统软件架构设计

2024-05-30吴松森陈晓阳高春阳

无线互联科技 2024年7期
关键词:应用层嵌入式总线

吴松森,陈晓阳,高春阳

(洛阳电光设备研究所,河南 洛阳 471000)

0 引言

随着嵌入式系统在航空、航天、航海等领域的应用不断拓展,软件定义系统已成为一种趋势,未来嵌入式软件必然会承担越来越多的使命,同时也将面临越来越多的问题。现有嵌入式软件的规模急剧提升,而软件的复杂度与软件规模呈非线性正相关,在超10万行的软件规模下,已经引起了软件复杂度的“质变”,为软件开发与维护带来巨大困难。同时,为不断适应新的使用场景以及平台能力持续提升,嵌入式软件的需求频繁变更,部分产品软件甚至可每年变更数十次以上,在愈发庞大的软件规模体量下,任何软件变更都可能带来巨大的工作量与不可预知的改动风险,从而延伸出了以下问题:(1)传统的软件开发模式已不再适用,相似功能重复性开发带来巨大的人力开销,导致软件开发人员与软件任务之间的矛盾更加激化;(2)在软件复杂度不断提升的情况下,软件质量隐患逐渐加大,软件开发人员水平对软件质量的影响更加凸显,软件维护成本增加;(3)由于软件规模增大,在没有解决软件内部的复杂耦合关系之前,新增功能的影响域增大,新功能的集成、验证成本增加。

良好的软件架构可以在软件设计之初就规范好组件间接口、组件间关系、组件与环境之间的关系,能够有效降低系统复杂性所带来的各种影响。针对复杂嵌入式系统,如何建立一套高内聚、松耦合、易复用、能有效适应需求变化的软件架构,成为本文亟待研究的问题。

1 传统软件架构对比分析

复杂嵌入式系统软件架构要解决的主要问题可以概括为以下3点:(1)复杂度分解问题;(2)面对需求变化的适应性与灵活扩展能力问题;(3)成熟功能的移植复用问题。针对上述问题,本文结合领域驱动设计技术、面向服务架构、微服务架构等进行分析研究,致力于寻求一种解决软件复杂度问题的有效方案。

1.1 领域驱动设计

领域驱动设计(Domain-Driven Design,DDD)[1]是在2004年提出的一种开放的设计方法体系,其核心思想在于根据“领域”进行复杂问题拆分,总的原则是将原来复杂的问题拆分成多个单独的简单问题进行求解。DDD强调业务逻辑与技术实现分离[2],更加关注业务复杂度分解以及业务上下文边界的界定,对于解决复杂的软件问题具有重要参考价值。

1.1.1 DDD分层架构

典型的DDD分层架构如图1所示,该架构遵循了“关注点分离”原则[3],将属于业务逻辑的关注点放到领域层(Domain Layer)中,而将支撑业务逻辑的技术实现放到基础设施层(Infrastructure Layer)中,应用层确定了两者之间的边界,通过依赖注入(Dependency Injection,DI)的方式将二者有机结合起来。

图1 DDD分层架构

1.1.2 六边形架构

由Alistair Cockburn提出的六边形架构如图2所示[4],通过由内向外“剥洋葱式”逐级分离的方式,将核心领域业务放在了架构的核心位置,应用层作为领域核心与外围适配器的转换,由内向外依次从“稳定”到“易变”。该架构通过端口适配的方法[5],让外部易变的部分依赖于逐层稳定的模型,间接保证核心业务代码不受外部变化的影响,从而提升了系统灵活性。

图2 典型的六边形架构

1.2 面向服务架构

面向服务架构(Service-Oriented Architecture,SOA)[6-7]将应用程序的不同功能单元进行拆分,通过一系列接口和统一的协议来进行数据交互和互相依赖。SOA架构的核心思想是互操作、复用、松耦合。DDD更注重业务逻辑与技术实现分离以及业务逻辑层面的解耦,SOA更注重于功能的服务化以及良好接口设计,二者并不冲突,甚至可以有机结合,实现更好的效果。面向服务设计的思想对于实现功能单元界面划分及可复用功能组件具有非常大的借鉴意义。

1.3 微服务架构

微服务架构将应用程序构建为松耦合、可独立部署的一组服务[8-9]。相对比SOA思想,微服务架构对服务层进行细粒度的拆分,所拆分的每个服务只完成某个特定的业务功能,服务的粒度很小,所以称为微服务[10]。由于服务颗粒度细、职责单一,微服务更加有利于资源的重复利用。对于外部交联关系复杂的嵌入式系统,往往存在多种对外通信方式,如离散量、模拟量、FC总线、CAN总线、RS422总线等,因此非常适用借鉴微服务架构思想,为每种通信方式实现一种微服务,通过多种微服务组合支撑系统功能实现。

1.4 架构对比分析

上述架构的对比分析结果为复杂嵌入式系统的软件架构设计提供了可供借鉴的思路,具体如表1所示。

表1 软件技术分析对比

2 架构设计思想

不同利益相关角色对于软件架构的诉求和关注点各不相同。用户更关注产品运行的可靠性和易维护性;产品的总体设计人员要求软件架构能够快速完成高质量的软件开发,对需求有良好的适应性,同时出现产品故障时应能快速定位与解决;软件需求人员更关心软件需求与软件架构之间追溯关系清晰明确,能够支持关键需求的覆盖及实现;对于软件开发人员,软件架构应该内层次关系清晰明确,能够支持软件设计人员进行软件设计,减少设计工作量;软件测试人员则要求软件架构具备易读性、可观测性,功能、接口明确,方便测试。

结合上述设计目标,为满足业务场景、利益攸关方等需求,复杂嵌入式系统软件的非功能需求可定义如下。(1)开放性:架构应具备良好的开放性,各功能模块松耦合、高内聚,能够很好地适应变化、支持扩展。(2)服务化:架构应具有良好的服务化设计,能够为新功能集成提供稳定的服务化接口,支持新功能快速集成。(3)通用化:架构中的基础设施、服务化组件、应用层组件等应具有一定的通用化设计,支持跨产品移植复用。

综合上述分析,要实现复杂嵌入式系统下通用软件架构,本文拟采用领域驱动设计思想,结合领域专家业务经验以及面向对象的技术手段完成软件的服务化实现。具体设计思想可以概括如下。

(1)分治思想。分而治之思想是领域驱动设计思想中一项核心设计思想,就是把复杂问题分解为若干简单问题来简化。采用分治思想,会使每个小功能模块更加容易开发且不易出错,同时能够支持多人分布开发,提升开发效率。主要原则如下:采用分层设计,使不同业务关注点分离;遵循“单一职责”原则,应按照模块、类、函数等逐层分解,最小原子程序只完成一个功能;经分割后的两个功能模块之间的依赖关系应简单、稳定、弱相关;对于难以划分归属关系的功能,优先从适应变化方面考虑。

(2)适应变化。在嵌入式业务领域,一个最大的特点就是“变化”,因此,通用软件架构必须能够适应变化。主要原则如下:新增功能带来的变化应不影响原有软件功能,最好不涉及任何原有软件代码更改;任何功能模块对新增需求应具有良好的扩展性,最好只增加代码,不更改代码;任何需求变更的影响域应相对集中,最好一个需求变更应只影响一个功能模块,不影响其他功能模块。

3 软件架构设计方案

基于上述设计思路,结合复杂嵌入式系统特点,本文采用分层设计[11-13]将系统软件架构分解为应用层、服务层、资源层,同时整体架构依赖于基础设施实现系统功能,软件架构如图3所示。

图3 软件架构

3.1 资源层

资源层主要用于部署与运行平台相关的资源组件,包括操作系统、运行时库、离散量驱动、总线驱动、文件系统驱动等,通过完成驱动集成与封装,为应用层、服务层提供稳定的资源访问接口。一方面,资源层对上访问接口的统一封装有利于更换硬件平台时不影响应用层及服务层软件,另一方面,根据测试先行的设计理念,嵌入式软件在开发时需持续开展测试,资源层可兼顾全数字仿真环境下的测试激励注入,有利于摆脱硬件平台对核心逻辑测试的约束,更好地完成持续集成、持续测试。

3.2 服务层

服务层主要用于部署服务组件,向下通过资源层屏蔽与底层操作系统之间的耦合,向上通过服务接口向应用组件提供功能服务,是架构中的核心组成部分,包括领域服务和基础服务两种。(1)领域服务组件与特定应用领域相关,通过对系统中特定领域核心逻辑的抽象,确定领域内、外部功能剖面及统一的服务接口,通过可重用化设计方法提取共性,具备一定的跨平台移植的能力。领域服务组件可调用基础服务,包括但不限于软件版本服务、故障处理服务、健康管理服务等。(2)基础服务组件要用于为其他模块提供基础服务,包括但不限于以下服务。总线服务:用于对外提供FC总线、CAN总线、RS422总线等总线消息队列的统一管理、消息重发机制、消息发送间隔控制机制等服务。离散量服务:用于对外提供离散量信号的抖动滤波、多路决策等功能。模拟量服务:用于对外提供模拟量信号的滤波、平滑等功能;定时器服务:用于对外提供定时器、时间获取、时间间隔控制等功能;日志服务:用于对外提供系统运行过程中信息存储与记录功能。

3.3 应用层

应用层主要用于部署与具体外部接口相关业务逻辑相关的应用组件,完成系统的综合处理与控制功能,向上实现外部接口与服务层之间的适配转换,向下调用统一的服务接口,而不关心具体底层服务类接口的实现。相对于传统的分层架构,本架构内对应用层进行了功能弱化,主要负责外部接口与核心业务逻辑(服务层)之间的适配。

3.4 基础设施

基础设施主要用于部署支持软件框架运行的基础工具,包括各组件管理调度机制、服务管理调度机制、事件总线管理机制、通用算法支持库等,提供不同组件和服务的注册、初始化以及运行调用,完成快速集成,同时通过事件总线管理机制来解耦各软件模块,为整个软件架构提供底层的通用算法。基础设施层主要用于实现软件框架的质量特性,包括易读性、维护性、扩展性等。

4 关键技术分析

4.1 业务逻辑与技术实现分离

业务逻辑与技术实现分离的设计方法可以使软件设计人员更加关注业务逻辑的解耦,对于实现软件复杂度分解及适应需求变化非常有借鉴意义。技术实现是指实现一项业务功能的具体方法,比如:处理其他设备发送的消息,可以直接调用总线接收接口主动获取数据,也可以通过订阅-分发的方式被动获取数据。通过抽象应用层技术实现的接口,依靠依赖注入的方法脱离具体实现细节,应用层的核心业务就会大大提升稳定性,在更换平台或者需求发生变化时不会由于其他层的耦合特性从而导致核心代码的修改。

4.2 事件总线机制

事件总线机制[14]是对观察者模式的一种技术实现,通过订阅-分发方式来实现对数据以及事件的集中处理与分发,各应用组件通过订阅接口对所关注的事件进行注册。当事件处理中心监测到事件发生时,向各订阅方进行事件的分发,从而能够允许不同组件之间进行彼此通信而无需进行强依赖,从而达到降低耦合度的效果。除了系统外部接口触发的事件外,系统内可以根据领域业务分解来抽象定义出若干内部事件,依托该机制实现各组件间的信息交互。

4.3 面向对象的设计原则

在进行软件架构设计时,需要同时兼顾规范性和灵活性,而规范性与灵活性本身又存在着互相制约和互斥的关系。面向对象设计原则能够帮助设计者在进行软件架构规范性设计时,尽可能地提升软件重用性、灵活性和扩展性。常用的面向对象设计原则包括单一职责原则、开闭原则、里式代换原则、依赖倒转原则、接口隔离原则、合成复用原则、迪米特法则[15]。

5 结语

结合嵌入式系统的应用发展趋势,针对嵌入式系统复杂度不断提升带来的一系列问题,本文结合领域驱动及服务化设计思想,提出了一种高内聚、松耦合、易扩展、可移植的通用软件架构设计方案,有助于实现系统软件模块解耦、可快速适应不同开发平台、有助于分布式开发和独立部署。该软件架构已在多个项目与嵌入式设备上得到了充分验证。实践结果表明该软件架构体系有较好的应用前景,可以有效解决系统复杂性的问题,同时能够有效适应于需求频繁变化的业务场景,在不影响原有代码的基础上快速完成新功能的增加或修改。

猜你喜欢

应用层嵌入式总线
基于PCI Express总线的xHC与FPGA的直接通信
机载飞控1553B总线转以太网总线设计
搭建基于Qt的嵌入式开发平台
基于分级保护的OA系统应用层访问控制研究
嵌入式软PLC在电镀生产流程控制系统中的应用
新一代双向互动电力线通信技术的应用层协议研究
物联网技术在信息机房制冷系统中的应用
多通道ARINC429总线检查仪
Altera加入嵌入式视觉联盟
倍福 CX8091嵌入式控制器