【架构模式】揭开软件架构模式的神秘面纱
视频号
微信公众号
知识星球
在软件工程中,有几种方法可以设计系统,每种设计都有自己的优点和挑战。因此,有时不同的设计方法试图实现类似的目标。当我们考虑软件架构设计时,尤其是在面向对象的世界中,最受关注的三种模式是干净架构、六边形架构和洋葱架构。
当我观察这些模式时,我觉得这三种模式都在试图倡导类似的想法。它们都定义了一个松散耦合的可测试系统,在实现方面避免了任何直接依赖,但使用了自己的术语,并且每个术语都有特定的细微差别。他们都提出了使软件架构更易于管理和测试的方法,但都是以自己的方式实现的。
如果我们把它们放在一起看,它们提供了一些有用的架构要点,无论您选择使用什么设计方法,这些要点都是适用的。我们将很快对它们进行探索,但首先让我们看看这些模式中的每一种都是单独的,以及它们之间的比较。
六边形架构
六边形架构有时被称为端口和适配器架构。Alistair Cockburn于2005年推出了它,其核心思想是使应用程序独立于UI和数据库的直接依赖。这种隔离是通过端口和适配器的概念来支持的。
让我们举一个例子。作为一名开发人员,您需要设计一个与用户相关的业务逻辑,该逻辑将持久存在于数据库中。您希望在业务逻辑和持久性之间进行隔离,以便两者都能履行并成长为其核心职责。
- 特定于数据库的逻辑将被封装到适配器类中,例如UserDataAdapter
- 特定于用户的业务逻辑类,如“User”
- User和UserDataAdapter之间的契约,以便它们可以相互交互,例如:IUserDataPort。此联系人是一个端口。
正如Cockburn所解释的,之所以选择“六边形”一词,并不是因为数字6很重要,而是为了让设计架构的人有足够的空间根据需要插入端口和适配器,确保他们不受一维分层图形的约束。
洋葱式架构
Jeffrey Palermo于2008年引入了洋葱架构的概念。他希望通过强调整个系统中关注点的分离,为复杂的业务应用程序开发一种设计方法。这种模式在六边形架构之外迈出了重要的一步,因为它扩展了在应用程序及其周围的各个层中定义核心业务层的想法,从而使核心层独立于外层及其依赖关系。
中心层——域模型——包含所有业务规则。下一个层次是域服务,它类似于存储库和其他依赖关系的契约。最外层包含用户界面和与外部基础设施的连接。
简而言之,洋葱架构和六边形架构之间的关键区别在于,洋葱架构在应用程序中引入了不同的层以及核心业务层,并将与数据库和UI等外部依赖关系的连接转移到了外部。这意味着如果需要,可以更容易地更换它们。
干净的架构
罗伯特·马丁于2012年推出了清洁架构。核心概念与洋葱架构相似,但术语略有不同。在这里,域模型被称为“实体”。实体包含特定于业务的规则和逻辑,而特定于应用程序操作的逻辑位于用例中。这些用例在实体之上编排操作,以指导它们执行业务规则,从而实现用例的目标。
乍一看,与Onion Architecture相比,Clean Architecture提供了对边界的更好理解,并提供了更清晰的关注点分离。他们关系密切,主张相似的思想,但层次不同。干净的架构清楚地说明了为什么每个层都存在,以及它们各自的职责是什么。这就是为什么它也被称为尖叫架构——它让一切都变得清晰明了。
架构模式教会了我们什么?
正如我们所看到的,所有三种架构风格都有松耦合的原则,并试图通过适当地分层应用程序来最大限度地减少移动部分。
那么,这三种模式给我们带来的主要收获是什么呢?我们应该牢记哪些基本的架构原则?
集中式业务规则
Clean和Onion Architecture都建议将特定于业务的规则放在一个集中的位置。尽管它们对非常相似的概念使用不同的名称,但它们都鼓励我们以相同的方式思考业务逻辑。
应用程序特定规则
同样,Clean和Onion Architecture都指向相似的方向;他们建议在企业规则旁边应该有一个层来管理特定于应用程序的逻辑。
此层将包含应用程序的特定于操作的编排和相关逻辑。
依赖关系规则
这三种模式都是根据这一原则进行调整的;它强调源代码依赖关系应该只指向内部。外层只能指内层,反之亦然。
不同层之间的隔离
这三种模式都强烈主张应用程序的不同部分应该能够相互隔离地增长,并且应用程序的每一层之间都应该有适当的抽象。
最重要的是,核心业务规则应该独立于:
你是如何坚持的:
- 您对数据库的选择不应影响核心域
- 如果您将数据库类型(例如:SQL到NoSQL)切换,那么您的业务逻辑应该不会有任何变化。
- 域和持久性之间的交互将遵循定义的标准,并且与持久性细节无关。
如何曝光:
- UI逻辑和用例不应该激励您更改核心域。
- 无论您是通过JSON、XML还是GraphQL公开它,核心都不应该受到影响。
您正在使用哪个框架:
- 理想情况下,核心域应该独立于所使用的框架。这可能不是很简单,但可以通过仔细的抽象来实现。
- 例如,。如果您在Java中将Springboot更改为Micronaut,在Golang中将Zin更改为Martini,在.NETCore中将WebAPI更改为Nancy,那么在如何定义核心域方面应该不会有任何变化。
您的外部依赖关系是什么:
- 核心域不应受到基础结构和相关依赖关系的影响。例如,如果您正在使用AWS Kinesis,并且需要用Kafka流替换它,那么核心域应该不会受到任何影响。
- 电子邮件、短信和事件是此类依赖关系的几个例子
结论
架构模式是我们设计应用程序的核心。尽管我们可以选择不同的模式,但通过识别和识别它们的相似性,我们可以遵循一些基本原则,这些原则将为设计业务关键型应用程序奠定坚实的基础。根据我的经验,理解这些规则帮助我创建了可扩展、可测试和全面的软件系统。
- 120 次浏览