赞
踩
构建有效的软件并不困难。
真正困难的是构建持续多年的软件,尽管业务需要,用户需要,新技术需要变化,但该软件仍可以继续工作。构建能够永久准备好进行更改的软件,并永久准确地反映业务…这是棘手的部分。
有许多原则和技术可以帮助实现这一目标,如SOLID,GRASP,STUPID,KISS,Demeter定律等。DDD是一组有助于实现这一目标的模式,原则和实践。
领域驱动设计(DDD)是Eric Evans在他的开创性著作《领域驱动设计:解决软件核心的复杂性》(Addison-Wesley Professional,2003)中定义的一种开发理念。DDD是一种软件开发方法,使团队能够有效地管理复杂问题域的软件构建和维护。
在DDD哲学中,软件变得复杂且难以管理的主要原因是领域概念不明确,它们往往会变得混合,不准确,因此会腐烂。它们变成了没有结构化,草率,耦合,不透明,意大利面条的代码(一团乱),实际上是Brian Foote和Joseph Yoder在他们的论文"Big Ball of Mud"中定义的Big Ball of Mud(BBoM)。
然后,沟通是关键。业务经理和开发人员需要一种通用语言来讨论业务概念。这是创建反映业务意图和业务概念的代码库的关键。在DDD中,这种通用语言被称为**泛在语言(UL)。**当领域专家和开发人员合作构建业务概念模型(领域模型)时,UL 是关键,该模型可以编码并准确反映业务意图。
我无法在博客文章中对DDD进行详尽的评论。与DDD相关的重要概念太多了。幸运的是,这也不是这里的目标。然而,我要做的是列出我发现与我喜欢的组织代码的方式以及我对架构的看法更相关的DDD概念:构成功能开发基础的系统范围概念。
在这篇文章中,我将写以下内容:
软件开发中反复出现的问题围绕着理解代码,它是什么,它做什么,它是如何做的,为什么这样做…如果代码使用的术语与领域专家使用的术语不同,则理解代码甚至会更加复杂,例如,如果领域专家谈论老年用户,而代码谈论主管,这可能会在讨论应用程序时带来很多混乱。然而,大多数这种歧义可以通过正确命名类和方法来解决,使它们表达对象是什么以及方法在域的上下文中做了什么。
使用泛在语言的主要思想是使应用程序与业务保持一致。这是通过在代码中采用业务和技术之间的通用语言来实现的。该语言的来源是公司的业务方面,他们有需要实现的概念,但术语然后与公司的技术方面进行谈判(这意味着业务方面也不总是选择最佳命名),目的是创建一个可供业务使用的通用术语, 技术和在代码本身没有任何歧义,一种无处不在的语言。代码、类、方法、属性和模块命名必须与无处不在的语言保持一致。如果需要,值得重构代码!
我已经在上一篇文章中讨论过分层,但我发现在这一点上,记住DDD标识的层是重要的:
负责绘制用户用于与应用程序交互的屏幕,并将用户的输入转换为应用程序命令。重要的是要注意,"用户"可以是人类,但也可以是连接到我们的API的其他应用程序,这完全对应于EBI架构中的边界对象。;
编排域对象以执行用户所需的任务:用例。它不包含业务逻辑。这与EBI 体系结构中的交互器有关,不同之处在于交互器是与 UI 或实体无关的任何对象,在这种情况下,应用程序层仅包含与用例相关的对象。此层是应用程序服务所属的位置,因为它们是使用存储库,域服务,实体,值对象或任何其他域对象进行用例编排的容器;
这是包含所有业务逻辑、域服务、实体、事件和包含业务逻辑的任何其他对象类型的层。它显然与 EBI 的实体对象类型有关。这是系统的核心。域服务将包含不太适合实体的域逻辑,通常编排多个实体来完成某些域操作;
支持上述层的技术功能,即。持久性或消息传递。
在企业应用程序中,模型可以增长很多,并且处理代码库的团队的规模也会很大。这给我们带来了两个问题:
换句话说,手头的问题变得太大了。
一个大问题的通常解决方案是把它分解成更小的部分,而这正是"有界上下文"发挥作用的地方。
两个子系统通常服务于非常不同的用户社区
Eric Evans 2014,领域驱动设计参考
有界上下文定义应用模型的隔离部分的上下文。隔离可以通过解耦技术逻辑、代码库隔离、数据库架构隔离以及团队组织来实现。像往常一样,我们隔离有限上下文的程度取决于实际情况:我们拥有的需求和可能性。
有趣的是,这并不是一个全新的概念。伊瓦尔·雅各布森(IvarJacobson)在1992年的书中写道子系统,比埃里克·埃文斯(Eric Evans)早十一年!
那时,他已经对这个主题提出了一些非常具体的想法:
防腐层基本上是两个子系统之间的中间件。它用于隔离两个子系统,使它们依赖于反腐败层,而不是直接相互依赖。这样,如果我们重构或完全替换其中一个子系统,我们只需要更新反腐败层,而另一个子系统保持不变。
当我们有一个需要与遗留系统集成的新系统时,这尤其有用。为了不让旧式结构决定我们如何设计新系统,我们创建了一个反腐败层,该层将使旧子系统的API适应新子系统的需求。
它有3个主要问题:
当我们不控制一个或所有子系统时,使用这种技术更合乎逻辑,但是当我们控制所有涉及的子系统时,使用它也可能是有意义的,即使它们设计得很好,但只是具有非常不同的模型,并且我们希望防止从一个模型泄漏到另一个模型(更改一个子系统以满足另一个子系统的需求)。
在某些情况下,尽管我们希望拥有完全隔离和解耦的组件,但某些域代码由多个组件共享是有意义的。
这将允许组件彼此分离,尽管耦合到相同的共享代码,即共享内核。
例如,由一个组件触发并由另一个或多个组件侦听的事件就是这种情况。但是,服务接口甚至实体也可能出现这种情况。
尽管如此,我们应该保持共享内核的小,并且在更改它时要非常小心,这样我们就不会无意中破坏使用它的其他代码。重要的是,在未与使用它的其他开发团队协商的情况下,不会更改共享内核中的代码。
子域是域中非常隔离的部分。通用子域是一个子域,它不是特定于我们的应用程序,它可以在任何类似的应用程序中使用。
因此,如果我们有一个应用程序,其中有一部分是关于金融的,也许我们可以在应用程序中使用现有的财务库。但无论哪种方式,即使我们不能使用现有的库并且需要构建自己的库,如果它是一个通用的子域,它就不是我们的核心业务,它应该被认为是必不可少的,但不是至关重要的。它不是我们应用程序中最重要的部分,因此它不是我们最好的专家应该关注的地方,它甚至应该明确地在主源代码之外,可能与依赖关系管理工具一起安装。
同样,我选择在这里处理的DDD概念主要是关于单一职责,低耦合,高内聚,隔离逻辑,以便我们的应用程序变得更加一致,更容易和更快地更改和适应业务需求。
如果对您有所帮助,记得给小编点个赞哦,也可以店家小编的微信,372787553,进入程序猿/媛交流群!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。