我们正在重新设计我们的API项目之一,从n层架构到洋葱体系结构。在前面的设计中,我们在一个公共库项目中的配置类跨所有层(UI、逻辑和数据访问层)进行引用。这些配置类应该如何适应洋葱体系结构?
发布于 2017-11-17 17:48:32
我在这里的指导原则是问我认为最重要的设计问题:
什么知道什么?

这是洋葱图。
和这个没什么不同:

但这张图显示了控制层内外的流动。注意右下角的紫色箭头。这在这里很重要,因为如果对象是不可变的,则控制流决定了构造的顺序。
Controller可以调用Use Case Interactor,后者可以调用Presenter。要做到这一点,他们需要参考他们所称的。这是他们知道的。这些引用只有在这些对象被构造后才存在。那么,首先必须建造什么呢?控制流中的最后一个对象。
这意味着,由不可变对象组成的洋葱的构造必须从外部层开始和结束。但如果你的控制流是..。有意思的?

在这里,我们看到控制俯冲到中间,从另一边出来,却又跳入水中。我们是否必须在这里逐步按照流向后构造所有东西?
不,你可以折叠它,直到它只潜入并出来一次。你不需要遵循每一个可能的控制流程。只要确保所有需要它的参考被传递到较低层的东西都在你下降的时候被构造,而当你提升的时候,需要它的所有的参考都通过了更高的层。
如果我们绘制结构图,以便可以使用控制流将其可视化,那么它可能如下所示:

我已经根据持久不可变对象的依赖关系来构建持久不可变对象的顺序来划分层。一旦建成,就不再需要将层分成两部分的水平线了。但是,如果您想要不可变的对象,那么这是必需的,这样所有的东西都能得到他们所需要的引用,这样他们就可以交谈了。
这确实对您的不可变对象设置了设计限制。但是这个模式在命令查询责任分离中运行得很好。
当然,所有这些都不能说明在程序运行时,如何处理那些突然出现和消失的传递对象。此外,允许可变对象学习和保留对在它们之后创建的对象的引用。这就是事件在观察者模式中的运作方式。不,这仅仅是为了能够构造一个持久的(在程序运行期间一直存在的)、不变的(不变的)对象图,这些对象图可以在端到端之间进行通信,但是仍然遵循依赖反转原则,这样内部层就不需要因为外层的变化而改变了。
现在,您可以将所有这些作为一堆主要的过程代码来完成。或者你可以用你的语言中的每一个工具把它分开一点。这是一个好主意,因为这些层的重点是,它们可以被剥离和替换,而不触及其他层。如果构造代码可以做类似的事情,那就太好了。
您甚至可以使用某个DI库强制您使用另一种语言编写将构造与行为代码分离。你没必要这么做。
如果您能原谅一些psudo代码,我的基本DI模式如下:
void main() {
InterfaceAdapterOutputs iao = makeDescendingFrameworksAndDrivers();
ApplicationBROutputs abro = makeDescendingInterfaceAdapters(iao);
EnterpriseBROutputs ebro = makeDescendingApplicationBR(abro);
EnterpriseBRInputs ebri = makeEnterpriseBR(ebro);
ApplicationBRInputs abri = makeAscendingApplicationBR(ebri);
InterfaceAdapterInputs iai = makeAscendingInterfaceAdapters(abri);
FrameworksAndDriverInputs fadi = makeAscendingFrameworksAndDrivers(iai);
fadi.start();
}当然,这太抽象了,但这就是模式。通常情况下,我会把它分解成不仅仅是层,还会有功能片段(有点像我的图标)。但这应该会让你觉得你自己的语言有能力使所有这些工作,而不需要添加任何特殊的魔法。
我只提到所有这些,因为这些需求可能会限制您合理地放置创建代码的位置。你越好地理解这些需求,你就会在满足这些需求时发现更多的灵活性。
那么,您将配置类放在哪里呢?再说一遍,问“什么知道什么?”
实体具有业务规则类、输入和输出接口,这些接口在层中一起更改。用例知道这一层,并且必须根据它的变化而改变。业务规则配置类(以及测试、日志记录和.)也必须如此。实际上,有很多东西需要内部层,但不关心应用程序的其余部分。这意味着将它们组合在一起,这样它们就可以很容易地从系统的其他部分分离出来,这可能是个好主意。每一层都可以这样说。
还有一些配置类知道多个层。这些应该与他们所知道的最外面的层一起分组。但是,除了这些之外,您还可以将配置代码组织到洋葱层,这与代码的其余部分非常相似。只是不要将Use Case代码与Entity构造代码分组。虽然依赖关系是相同的,但这是非常不同的代码。它应该分开。

然而,我并不是一个只喜欢逐层组织的人。正如我所说的,我的代码库将更像我的图标,有功能部分。这是按特性包装,不按层原则包装。但在我的特征中,事物是被分层的。所以对我来说,任何一个洋葱图都可能是一个特征。
https://softwareengineering.stackexchange.com/questions/360850
复制相似问题