为什么需要六边形架构?- silkandspinach


传统应用程序架构的标准三层或四层模型似乎决定了系统中各种对象之间的依赖关系的方向:UI依赖于应用程序层,因为UI“驱动”后面发生的事情;应用程序层依赖于业务对象,业务对象执行所有特定于领域的事务,业务对象使用(因此依赖于)持久层和通信层,这两个层又使用并依赖于外部API。以这种方式实现分层模型好像很自然。

ui ---> application ---> domain --->(persistence,comms)

正是这种分层模型使许多应用程序难以或无法测试。这些感知的依赖关系中的每一层最终都体现在代码结构中,并且通过隐身设计已经具体化变成分层模型。在这一点上,像我一样的人会叮嘱开发人员提高他们的测试覆盖率,但是我会被告知:“我们尝试过,但管理和准备需要测试GUI的Oracle测试数据需要很长时间”。或者当业务决定切换到新的数据库或企业通信架构,需要重新设计大量的业务逻辑。

Alistair Cockburn的六边形建筑模型引入了一个对称轴,可以帮助我们了解如何解决这些问题:

我们应该使用内部 - 外部模型来查看一个应用程序架构,而不是使用分层模型的上下视角。领域对象位于中间,并通过我称之为适配器: 比如一个 GUI,CGI脚本,命令行,硬件控制器,打印后台处理程序等连接到现实世界。每个适配器将领域对象连接到不同的“真实”世界的一部分。

因此,让我们从“六角形”的角度来看待我们的不可测试或不可移植的应用程序。(请记住,我们在这里仍然在讨论相同的代码库:只是我们的话语模型已经发生了变化。)使测试变得如此困难的依赖性,以及对分层模型的天真解释而存在的依赖性,显然违背了六角形模型的对称性。

ui --->(app,domain)--->service

如果我们希望能够轻松移植应用程序以使用不同的服务,我们需要能够轻松地替换掉将我们连接到这些服务的适配器。

ui --->(app,domain)--->new service

如果我们希望独立于硬件测试领域对象,我们需要能够用stubs存根,分流器或模拟Mock 对象替换各种适配器。

fit ---> (app, domain) ---> mock services

我们目前无法做到这一点,因为该设计违反了Bertrand Meyer的开放式原则(“ 系统应该向扩展开放,但不能修改 ”)。为了解决这个问题,我们需要使用Uncle Bob的依赖倒置原则:我们在中间的六边形中引入抽象,以便目前的适配器实现这些抽象。

ui --->(app,domain ---> abstraction)<--- service

现在恢复了对称性:每个适配器都依赖于中间六边形,而中间六边形(我们的域对象)独立于使用它的物理上下文。

适配器--->中间<---适配器

现在我们可以更容易地看到如何剥离我们希望的任何适配器,并用模拟对象或不同的服务替换它们。适配器/中间对称轴是提高企业应用程序的可测试性和可移植性的关键因素。