  South Square test tube   substituting  pregnancy  well  Division M

  South Square test tube   substituting  pregnancy  well  Division Micro signal M █ █: 138-0226-9370█ █ █ surrogate packet success packet healthy surrogate ██

What is DDD

DDD is not the schema design method, not the details of each design concrete images, DDD is a system, determine its openness, the system can use any method to solve these problems, but if some of the key issues there is no specific programs floor, may let the team know what to do.

DDD does not solve the three problems

  • If the domain modeling
  • How to identify Bounded Context
  • How to find objects in the tactical level

DDD term

Strategic Modeling

  • Limit context (Bounded Context)
  • Map context (Context Mapping)

Tactical Modeling

  • Polymerization -Aggregate
  • Entity -Entity
  • Value object -Value Objects
  • Library -Repository
  • Field service -Domain Services
  • Field events -Domain Events
  • Module -Modules

Bound Context(BC)

BC is encapsulated in the field of high cohesive module, so this characteristic architecture of DDD is not much invasive. Architecture may be applied to the field of internal structure may be surrounded by a domain model, the system architecture may be employed a variety of styles.

Proposed BC (Bounded Context, context boundaries) on the strategic design of DDD. UL (Ubiquitous Language, universal language) is the team's shared language, as long as a team, you need to use the UL, you can ensure that all concepts unambiguous in their context. And UL BC are the two pillars of DDD, complement each other.

A business area is divided into a number of BC, BC between integration by Context Map, BC is a display boundary, the domain model within this boundary, the domain model is a software model of a particular business domain, domain model through the object model to achieve these objects contain both data and behavior, and expressed the exact meaning of business.
Broadly speaking, the field is everything an organization does its thing contained, represents the entire business system, field representation should create a unified system for the entire business, cohesive full-featured model, domain model exists in the BC.

BC by isolation system complexity, the complexity of the polyethylene within the boundaries.

A domain model for large systems complete reunification is not feasible, nor is it a cost-effective way. Any large project there will be multiple models, different model code organizations with software may appear bug, while more unreliable and difficult to understand. Communication also become confused between the teams.

When divided into multiple models within the model, the team can work freely, until their limits and abide by the limits. It is necessary to ensure that the model of purity, consistency and uniformity.
It is necessary to clearly define the application context model to model boundary set according to a team or organization or system software physical performance.

Context Map context diagram

Relationship occurs between multiple systems, there is an interaction, we need to create a global view of all the models in the context of the project, to reduce confusion. The system generally indicates an overall view of the relationship by Context Map.

U represents the upstream (Upstream) is relying party, D denotes relying party downstream (Downstream) a. Coating (ACL) on the downstream, upstream messages into the downstream domain model.

Context Map context characterized by the relationship between the limits following ways:

  • Sharing the kernel -Shared Kernel
  • Customer / Supplier -Customer / Supplier
  • Followers -Conformist
  • -Anticorruption Layer Coating
  • Public hosting services -Open Host Service
  • -Separate Way prevails

Sharing the kernel -Shared Kernel

When the team developed a number of different applications are closely related, the need for coordination between teams, it can usually be spun off to form a shared kernel (Shared Kernel) two teams share a subset of the two sides continuous integration (Continuous Integration). Sharing the kernel (Shared Kernel) is a common part of the business areas, but also between the team and must be easy to reach a consensus on the part of the field.

Customer / Supplier -Customer / Supplier

不同系统之间存在依赖关系时,下游系统依赖上游系统,下游系统是客户,上游系统是供应商,双方协定好需求,由上游系统完成模型的构建和开发,并交付给下游系统使用,之后进行联调、测试。这种模式建立在团队之间友好合作和支持的情况下。
当两个具有上游/下游关系的团队不归同一个管理者指挥时,Customer/Supplier这样的合作模式就不会奏效。勉强应用这种模式会给下游团队带来麻烦。

追随者-Conformist

当两个开发团队具有上/下游关系时,如果上游团队没有动机来满足下游团队的需求,那么下游团队将无能为力。出于利他主义的考虑,上游开发人员可能会做出承诺,但他们可能不会履行承诺。下游团队出于良好的意愿会相信这些承诺,从而根据一些永远不会实现的特性来制定计划。下游项目只能被搁置.直到团队最终学会利用现有条件自力更生为止。下游团队不会得到根据他们的需求而量身定做的接口。
这时候“客户/供应商”模式就不凑效了,那么下游系统只能去追随上游系统,下游系统严格遵从上游系统的模型,简化集成。
通过严格遵从上游团队的模型,可以消除在 BC之间进行转换的复杂性。尽管这会限制下游设计人员的风格,而且可能不会得到理想的应用程序模型,但选择 Conformist模式可以极大地简化集成。此外,这样还可以与供应商团队共享一种 UL。供应商处于驾驶者的位置上,因此最好使他们能够容易沟通。

防腐层-Anticorruption Layer

前面介绍了在两个BC之间集成时可以进行的各种合作,从高度合作的 Shared Kernel模式或 Customer/Supplier Team到单方面的Conformist模式。如果是一种更悲观的关系,假设一个团队既不可能与另一个团队合作也无法利用他们的设计时,该如何应对。
这时候我们需要使用防腐层(Anticorruption Layer)模式将上游系统的影响降低。

公开主机服务-Open Host Service

当一个子系统必须与大量其他系统进行集成时,为每个集成都定制一个转换层可能会减慢团队的工作速度。如果一个子系统有某种内聚性,那么或许可以把它描述为一组 Service,这组 Service满足了其他子系统的公共需求。
公开主机服务(Open Host Service)能够允许系统将一组Service公开出去公其他系统访问。定义一个协议,把你的子系统作为一组 Service供其他系统访问。开放这个协议,以便所有需要与你的子系统集成的人都可以使用它。当有新的集成需求时,就增强并扩展这个协议,但个别团队的特殊需求除外。

各行其道-Separate Way

当两个系统之间的关系并非必不可少时,两者完全可以彼此独立,各自独立建模,独立发展,互不影响。

领域事件

领域专家所关心的发生在领域中的一些事件。将领域中所发生的活动建模成一系列的离散事件。每个事件都用领域对象来表示...领域事件是领域模型的组成部分,表示领域中所发生的事情。

“重要的事件肯定会在系统其它地方引起反应,因此理解为什么会有这些反应同样也很重要。”

一个领域事件可以理解为是发生在一个特定领域中的事件,是你希望在同一个领域中其他部分知道并产生后续动作的事件。但是并不是所有发生过的事情都可以成为领域事件。一个领域事件必须对业务有价值,有助于形成完整的业务闭环,也即一个领域事件将导致进一步的业务操作。

领域事件可以是业务流程的一个步骤,例如订单提交,客户付费100元,订单完工等。领域事件也可以是定时发生的事情,例如每晚对账完成。或者是一个事件发生后引发的后续动作,例如客户输错密码三次后发生锁定账户的事件。

领域事件也是一种基于事件的架构(EDA)。事件架构的好处可以把处理的流程解耦,实现系统可扩展性,提高主业务流程的内聚性。

如果改为事件驱动模式,把订单提交后触发一个事件,在订单保存后,触发订单提交事件。通知和后续的各种服务动作可以通过订阅这个事件,在自己的实现空间内实现对应的逻辑,这样就把订单提交和后续其他非主要活动从订单提交业务中剥离,实现了订单提交业务高内聚和低耦合性。

  1. 首先是解决领域的聚合性问题。DDD中的聚合有一个原则是,在单个事务中,只允许对一个聚合对象进行修改,由此产生的其他改变必须在单独的事务中完成。如果一个业务跨多个聚合对象,领域事件会是一个不错的工具来解决这个问题。通过领域事件的方式可以达到各个组件之间的数据一致性,通过最终一致性取代事务一致性。

  2. 其次领域事件也是一种领域分析的工具,有时从领域专家的话中,我们看不出领域事件的迹象,但是业务需求依然有可能需要领域事件。动态流的事件模型加上结合DDD的聚合实体状态和BC,可以有效进行领域建模。

领域事件可以通过观察者模式和订阅模式进行实现。比较常见的实现方式是事件总线(Event Bus)。

事件风暴

事件风暴是一项团队活动,旨在通过领域事件识别出聚合根,进而划分微服务的限界上下文。在活动中,团队先通过头脑风暴的形式罗列出领域中所有的领域事件,整合之后形成最终的领域事件集合,然后对于每一个事件,标注出导致该事件的命令(Command),再然后为每个事件标注出命令发起方的角色,命令可以是用户发起,也可以是第三方系统调用或者是定时器触发等。最后对事件进行分类整理出聚合根以及限界上下文。

举个例子

在我们的一次产品的重构活动中也采用了事件风暴方法。系统代码维护了10几年,代码中存在大量的“坏味道”:重复代码,过长函数,过大的类,过长的参数列表,发散式变化,霰弹式修改,镀金问题,注释不清等问题。实际研发过程中也是经常出现一点改动都可能会引起不可预测的结果,重构势在必行。
但是在重构过程中,也没有人可以说清楚现有系统的逻辑,如何重构成为了一个难题。重构过程我们引入了咨询公司给我们的方法,采用了事件风暴的办法,通过对领域中所发生的事情(也就是领域事件)来探索这个领域,并且使用便签来描述领域中的事件,这些便签会沿着时间轴贴到一个很大的建模面板上。
举例来说,能够引发事件的事情包括用户行为、外部系统所发生的事情以及时间的流逝。事件也有助于找到领域的边界,对术语的不同阐述可能就意味着存在边界。

  • 准备工作,四色贴纸:
    橙色:事件,某个动作的结果,以“XX已XX”的方式表示,比如“用户信息已查询”
    蓝色:属性,事件相关的输入、输出数据等
    黄色:命令,某个动作,比如“查找用户信息”
    绿色:实体,命令的触发者

  • 开始梳理业务,将结果贴到白版上
  • 继续深入梳理,将整个过程的模型、关键数据等梳理出来,贴在白板上
  • 确定重构指导思路,执行重构动作,重构的同时引入单元测试保障重构的质量

实体和值对象

实体不仅需要知道它是什么?而且还需要知道它是哪个?而值对象只需要知道它是什么?

  • 实体:许多对象不是由它们的属性来定义,而是通过一系列的连续性(continuity)和标识(identity)来从根本上定义的。只要一个对象在生命周期中能够保持连续性,并且独立于它的属性(即使这些属性对系统用户非常重要),那它就是一个实体。

  • 值对象:当你只关心某个对象的属性时,该对象便可作为一个值对象。为其添加有意义的属性,并赋予它相应的行为。我们需要将值对象看成不变对象,不要给它任何身份标识,还应该尽量避免像实体对象一样的复杂性。

实体对象相对容易理解,我们常见的类的都可以看成是实体对象。值对象在DDD中相对而言是难以理解并且容易误用的。

为什么需要使用值对象,书中给了一个解释:

使用不变的值对象使得我们做更少的职责假设

使用值对象在不同的BC中进行数据交换,可以避免不同BC对实体对象的状态变更而引发的数据依赖关系,实现最小化的集成。

值类型用于度量和描述事物,DDD中建议应尽量使用值对象来建模而不是实体对象,因为值对象非常容易地对值对象进行创建、测试、使用、优化和维护。

领域服务

领域中的服务表示一个无状态的操作,它用于实现特定于某个领域的任务。
当某个揉作不适合放在聚合和值对象上时,最好的方式便是使用领域服务了。有时我们傾向于使用聚合根上的静态方法来实现这些这些操作,但是在 DDD中,这是一种坏味道。

《实现领域驱动设计》书中给出了一个例子,对User进行认证的例子。例子中给出的需求是:

  • 系统必须对User进行认证,并且只有当Tenant处于激活状态时候才能对User进行认证。
  • 必须对密码进行加密,并且不能使用明文密码

对以上的需求,我们可以把认证的方法写在User类或者Tenant类中,不过对于以上解决方案,似乎都给模型带来了太多的问题。

对于后一种方案, 我们必须从以下回种解决办法中选择一种:

  1. 在Tenant中处理对密码的加密,然后将加密后的密码传给User。这种方法违背了单一职责原则

  2. 由于一个User必须保征对密码的加密,它可能已经知道了一些加密信息。如果是这样,我们可以在User上创建一个方法,该方法对明文密码进行认证。但是在这种方式下,认证过程变成了Tenant上的Facade。而实际的认证 功能全在User上。另外User上的认证方法必须声明为Protected,以防止外界 客户端对认证方法的直接调用。
  3. Tenant依赖于User对密码进行加密,然后将加密后的密码与原有密码进行匹配。这种方法似乎在对象协作之间增加了额外的步骤。此时,Tenant依然需 要知道认证细节。
  4. 让客户端对密码进行加密。然后将其传给Tenant,这样导致的问题在于客户端承载了它本不应该有的职责。

UserDescriptor userDescriptor = 
          DomainRegistry
            .authenticationService()
            .authenticate(tenantID,userName,password);

模块

在DDD中,模块表示了一个命名的容器,用于存放领域中内聚在一起的类。

模块应该包含一組具有高内聚性的概念集合.这样做的好处是可以在不同的模块之间实现松耦合。否则,我们应该修改模型以重新划分这些概念。……由于模块名是UL的一部分,模块名应该反映出它们在领域中的概念。[Evans]

模块的设计是基于领域模型的,要符合通用语言的表述。其次,模块的设计要符合高内聚低耦合的设计思想。

模块和BC的关系

模块与子域和限界上下文并不是一致的概念,模块也是一种独立的建模方法。对于何时应该对领域模型进行分离,何时将领域模型建模成一个整体,应该仔细地思考与对待。有时通用语言可以很好地帮助我们做出正确的选择。但是另外的时候,其中的术语将变得非常含糊。在这种情况下,我们并不清楚如何划分上下文边界。此时,我们可以首先将它们放在一起,使用模块来对模型进行划分,面不是限界上下文。

但是,这并不意味着我们就应该限制对限界上下文的创建。我们应该通过通用语言的需求来划分模型边界。但限界上下文不是用来代替模块的。使用摸块的目的在于组织那些内聚在一起的领域对象,对于那些内聚性不强或者没有内聚性的领域对象来说,我们应该将它们划分在不同的模块中。

集成BC(界限上下文)

一个项目中会存在多个BC,业务需要对它们进行集成。有多种直接的方法进行集成。最简单的方式就是一个BC中暴露API,然后在另外一个BC中通过RPC进行调用。

另外我们也可以通过消息机制进行集成,系统通过消息队列或者发布-订阅机制进行通讯。

第三种方式是通过使用RESTful的方式进行集成。当然,还存在有其他的集成方式。

Guess you like

Origin www.cnblogs.com/DINGER01/p/10942526.html