软件架构编年史:洋葱架构

2023-03-23 16:41:06 浏览数 (3)

覃宇,Android开发者/ThoughtWorks技术教练//译者,热衷于探究软件开发的方方面面,从端到云,从工具到实践。喜欢通过翻译来学习和分享知识,译作有《Kotlin实战》、《领域驱动设计精粹》、《Serverless架构:无服务器应用与AWS Lambda》和《云原生安全与DevOps保障》。

2008 年 Jeffrey Palermo 提出了洋葱架构。在我看来,它在端口和适配器架构的基础上贯彻了将领域放在应用中心,将传达机制(UI)和系统使用的基础设施(ORM、搜索引擎、第三方 API...)放在外围的思路。但是它前进了一步,在其中加入了内部层次。

我们从通常拥有四个层次(表现层、应用层、领域层、持久化层)的分层架构发展到了端口和适配器架构,它只是含蓄地提到了两个同心圆层次:

  • 代表传达机制和基础设施的外层;
  • 代表业务逻辑的内层。

端口和适配器架构与洋葱架构有着相同的思路,它们都通过编写适配器代码将应用核心从对基础设施的关注中解放出来,避免基础设施代码渗透到应用核心之中。这样应用使用的工具和传达机制都可以轻松地替换,可以一定程度地避免技术、工具或者供应商锁定。

另外,它还有着脱离真实基础设施和传达机制应用仍然可以运行的便利,这样可以使用 mock 代替它们方便测试。

然而,洋葱架构还告诉我们,企业应用中存在着不止两个层次,它在业务逻辑中加入了一些在领域驱动设计的过程中被识别出来的层次:

此外,它明确了端口和适配器架构中关于依赖方向的暗示:

  • 外层依赖内层;
  • 内层对外层无感知。

也就是说耦合的方向是从外层指向中心,它提供了一个完全独立的对象模型(领域模型),该模型位于架构的核心,不依赖其它任何层次。我们拥有了在不影响内层的情况下改变外层的灵活性。它在架构层面运用了依赖倒置原则。

洋葱架构的关键原则: 围绕独立的对象模型构建应用 内层定义接口,外层实现接口 依赖的方向指向圆心 所有的应用代码可以独立于基础设施编译和运行 —— Jeffrey Palermo 2008, The Onion Architecture: part 3

还有,任何一个外部层次都可以直接调用任何一个内部层次,这样既不会破坏耦合的方向,也避免了仅仅为了追求分层模式而创建一些没有任何业务逻辑的代理方法甚至代理类。这和 Martin Flowler 表达的偏好一致。

[…] 上层可以使用它们下面的任意层次,而不仅仅是它们直接的下层。——Jeffrey Palermo 2008, The Onion Architecture: part 3 张逸按:这一方式遵循松散分层架构的做法,但它有可能会破坏必要的封装,导致内部的模型泄漏出去。要知道,变化的影响是双向的,包括外部变化对领域模型的影响,领域模型变化对外部产生的影响。领域驱动设计的上下文映射只建议针对确定稳定的领域模型,采用直接调用的共享内核,否则,直接调用领域模型会被认为是遵奉者反模式。

洋葱架构在端口和适配器架构的基础之上增加了一些的应用业务逻辑的内部组织,这些组织基于领域驱动设计的概念划分的。

这又是一次职责分离的更深入的演化,带来了高内聚低耦合,反过来也带来了更好的可测试性和可维护性。

引用来源

  • 2002 – Martin Fowler – Patterns of Enterprise Application Architecture
  • 2008 – Jeffrey Palermo – The Onion Architecture: part 1
  • 2008 – Jeffrey Palermo – The Onion Architecture: part 2
  • 2008 – Jeffrey Palermo – The Onion Architecture: part 3
  • 2013 – Jeffrey Palermo – The Onion Architecture: part 4 – After Four Years

1 人点赞