领域驱动设计 微服务
重点(Top highlight)
Domain-Driven Design (DDD) concept was introduced by first Eric Evans in 2003. The concept of microservices did not exist at that time. So basically DDD was introduced to solve the problem of a large monolithic code base. In the monolithic world, once the codebase starts growing with the growth of the business, it becomes difficult to maintain the code organized and structured as it was originally designed. Monolithic applications designed using MVC architecture have good separation between the business layer and the presentation layer. But in the absence of the strict architectural guidelines, the business layer does not provide specific rules to maintain responsibility boundaries between different modules and classes. That’s why as the code base grows it increases the risk of logic breakdown, responsibility leakage between the different components of the application.
域驱动设计(DDD)概念由第一位Eric Evans于2003年提出。微服务的概念当时还不存在。 因此,基本上引入了DDD来解决大型整体代码库的问题。 在单片世界中,一旦代码库随着业务的增长而开始增长,就很难维护其最初设计的组织和结构化的代码。 使用MVC架构设计的单片应用程序在业务层和表示层之间具有良好的分隔。 但是在缺乏严格的体系结构准则的情况下,业务层不提供特定的规则来维护不同模块和类之间的责任界限。 这就是为什么随着代码库的增长,它增加了逻辑崩溃,应用程序不同组件之间的责任泄漏的风险。
DDD attempts to solve the above challenges by keeping your application close to the REAL-WORLD system or more precisely to the concerned business. In DDD, application logic revolves around the business problems with defined boundary contexts. DDD focus on domain modeling. Let’s discuss the key characteristic of DDD
DDD试图通过使您的应用程序靠近REAL-WORLD系统或更准确地说与相关企业联系来解决上述挑战。 在DDD中,应用程序逻辑围绕具有定义边界上下文的业务问题展开。 DDD专注于领域建模。 让我们讨论DDD的关键特性
- Collaborative: DDD is collaborative. Business entities, stakeholders, and developers work together to solve a specific business problem. It is more like an AGILE methodology where collaboration is the key. 协作:DDD是协作的。 业务实体,利益相关者和开发人员共同解决特定的业务问题。 它更像是一种以协作为关键的敏捷方法。
- Data Modeling: Data Modeling defines that the structure of your code should map to the structure of the domain. Here, the domain is not referred to as a business, this can be referred to as the part of the business. The domain can be accounting, storefront, warehouse, etc. The idea behind keeping the code model mapped to the domain is to keep the high-level structure of the application understandable to business users. So when a business expands and one of the domains of the business needs some enhancements in the application, you can change models and logics associated with that domain and keep the other part of the application intact. 数据建模:数据建模定义代码的结构应映射到域的结构。 在此,域不被称为业务,这可以被称为业务的一部分。 该域可以是会计,店面,仓库等。将代码模型映射到该域的背后思想是使业务用户可以理解应用程序的高层结构。 因此,当业务扩展并且业务的某个领域需要对应用程序进行某些增强时,您可以更改与该领域相关联的模型和逻辑,并保持应用程序的其他部分不变。
- Incremental: DDD is incremental so you don’t need the entire architecture of the business to be designed upfront. You just need to solve the current problem and then evolve the code as the domain or business grows. Again DDD aligns with AGILE methodology with this characteristic of an incremental approach. An incremental approach is a process or releasing new features quickly and incrementally. 增量式:DDD是增量式的,因此您不需要预先设计整个业务架构。 您只需要解决当前问题,然后随着域或业务的增长而发展代码。 DDD再次与AGILE方法学保持一致,并具有这种增量方法的特征。 增量方法是一个过程或快速且增量地发布新功能。
什么是微服务? (What are Microservices?)
In simple words, microservices is about solving a specific problem. In Monolith design, we have a huge code base that is data-driven and tightly coupled. So whenever we need to change the data model the entire monolith design comes into the stake. Even the incremental approach is too cumbersome with a monolith as the entire application has to be tested with all circumstances and scenarios along with different dependency checks to make sure the update is not causing any failures. Microservice architecture solves this problem of monolithic design and provides the freedom to grow the application in any direction.
简而言之,微服务就是要解决一个特定的问题。 在Monolith设计中,我们拥有庞大的代码库,该代码库是数据驱动的并且紧密耦合。 因此,每当我们需要更改数据模型时,整个整体设计都会受到影响。 甚至增量方法也非常麻烦,因为整个应用程序必须在所有情况和场景下进行测试,并进行不同的依赖性检查,以确保更新不会引起任何故障。 微服务架构解决了单片设计的这一问题,并提供了向任何方向扩展应用程序的自由。
DDD与微服务有何关系? (How DDD is related to Microservices?)
Microservices is possibly the ideal way to implement the DDD because in Microservices we also talk about context and incremental approach which are the main characteristic of DDD too. Both DDD and microservices are modeled around the business concept. Some basic characteristics of microservices are following
微服务可能是实现DDD的理想方式,因为在微服务中,我们还讨论了上下文和增量方法,这也是DDD的主要特征。 DDD和微服务都围绕业务概念建模。 微服务的一些基本特征如下
1. Small: Microservice should be small enough to solve an individual problem. It can be as small as a class in OOPS terminology or a function in Functional design terminology.
1.小型:微服务应足够小以解决单个问题。 它可以与OOPS术语中的类一样小,也可以与“功能设计”术语中的函数一样小。
2. Independently deployable: A Microservice is independently deployable. So basically you do not need to update the entire application like a monolith for adding a new feature. You just change the related microservice and check its context boundaries and you are ready to deploy.
2.可独立部署:微服务可独立部署。 因此,基本上,您不需要像增加整体功能那样整体更新整个应用程序。 您只需更改相关的微服务并检查其上下文边界即可开始部署。
3. Decoupling: Individual microservice should be decoupled, isolated, and hide its implementation details from the world. Microservices should be accessible via services only to provide decoupling.
3.解耦:应该将各个微服务解耦,隔离,并向世界隐藏其实现细节。 只能通过服务访问微服务以提供去耦。
DDD的关键构建块 (Key Building Blocks of DDD)
1. Domain: It’s a logical area which defines the different business entities. For example, a shipping business may have an inventory domain, accounting domain, tracking domain, etc.
1.域:这是定义不同业务实体的逻辑区域。 例如,运输业务可能具有库存域,会计域,跟踪域等。
2. Bounded Context: It’s a logical boundary in the code which solves the specific problem of the domain. It can be a single class or a group of files which are coded to resolve a specific problem. The different bounded context is completely isolated from each other and does not know about each other existence. The easiest way to define context is to define the “Responsibilities” of the domain. For example, an e-commerce company can have two domains named “Warehouse” and “Store”. “Warehouse” has the responsibility of “Shipping the product” whereas “Store” has the responsibility of “Sales” so these can be treated as a bounded context.
2.有界上下文:这是代码中的逻辑边界,可以解决特定领域的问题。 它可以是单个类,也可以是编码为解决特定问题的文件组。 不同的有界上下文是彼此完全隔离的,并且彼此之间并不了解。 定义上下文的最简单方法是定义域的“职责”。 例如,一个电子商务公司可以有两个名为“仓库”和“商店”的域。 “仓库”负责“运输产品”,而“商店”负责“销售”,因此可以将它们视为有限的上下文。
3. Services: Service is the communication channel between different Bounded Contexts. You need services to keep different bounded contexts decoupled but still communicable.
3.服务:服务是不同边界上下文之间的通信渠道。 您需要服务来使不同的有界上下文脱开,但仍可通信。
4. Value Objects: A value object has no distinct identity and it is immutable. It is defined by its properties. For example Name, Address, etc are value objects.
4.价值对象:价值对象没有独特的身份,并且是不可变的。 它由其属性定义。 例如,名称,地址等是值对象。
5. Entities: Entities are domain objects. Entities do only specific things within the bounded context. These are identified by a unique identifier. Some examples of entities can be User, Order, Job, Message, etc. An entity is mutable and it can change its identity. For example, an order might change its statues from ordered to shipped and it has a unique identifier “order_id” to be identified.
5.实体:实体是领域对象。 实体仅在有限的上下文中执行特定的操作。 这些由唯一标识符标识。 实体的一些示例可以是用户,订单,作业,消息等。实体是可变的,并且可以更改其身份。 例如,一个订单可能会将其雕像从已订购更改为已发货,并且有一个唯一的标识符“ order_id”要识别。
6. Ubiquitous Language: This denotes the language-specific within the context. For example, if you talk about an object “book” in the “store” context then you are more concerned about properties like price, authors, etc which are related to “sell the product” whereas an object “book” in the “warehouse” context should be more related to properties like weight, size, etc which are related to “ship the product”. So clearly the same object might have different languages of conversation in different contexts. Ubiquitous Language is not just dependent upon the NOUN level or properties level as defined above, this is related to the VERB level too or in easy words, what you do with those objects. For example, the “book” object should be used to “sell or organize” the books in the “store” context whereas it should be used to “box and ship” the books in the “warehouse” context. Overall, ubiquitous language defines the language within the context and when someone talks about “book” in the “warehouse” context then it will be always about properties like weight and size and no one should talk about the name of the book at all in that context.
6.无处不在的语言:这表示上下文中特定于语言的语言。 例如,如果您在“商店”上下文中谈论对象“书”,那么您将更加关注与“出售产品”相关的属性,例如价格,作者等,而在“仓库”中的对象是“书” ”上下文应与重量,尺寸等与“运送产品”相关的属性更多相关。 因此很明显,同一对象在不同上下文中可能具有不同的会话语言。 无处不在的语言不仅取决于上面定义的NOUN级别或属性级别,这也与VERB级别相关,或者用简单的话来说,与您对这些对象的处理方式有关。 例如,“书”对象应用于在“商店”上下文中“出售或整理”书籍,而应在“仓库”上下文中用于“装箱”书籍。 总体而言,无处不在的语言在上下文中定义了语言,当有人在“仓库”上下文中谈论“书”时,它将总是与重量和大小之类的属性有关,而在此方面,任何人都不应谈论书的名称。上下文。
DDD如何实施? (How DDD can be implemented?)
DDD approach can be used to both analyze the domain as well as develop the code and this process is called “Event Storming”. We talk about domain and identify events that might happen at the domain level during “Event Storming”. Remember that its a collaborative and incremental, so you have to involve both businesses as well as developers to define the events and model around it. Let’s take an E-Commerce business as an example to determine the DDD approach. Please note that this is not a complete example. I am using this just as a reference. While adopting the DDD approach we should focus on three W’s and those are “WHEN”, “WHAT” and “WHO”.
DDD方法可用于分析域和开发代码,此过程称为“事件风暴”。 我们讨论领域,并确定“事件风暴”期间在领域级别可能发生的事件。 请记住,它是协作的和增量的,因此您必须让企业和开发人员都参与其中,以定义事件并围绕它进行建模。 让我们以电子商务业务为例来确定DDD方法。 请注意,这不是一个完整的示例。 我仅以此为参考。 在采用DDD方法时,我们应关注三个W,即“ WHEN”,“ WHAT”和“ WHO”。
You should start your DDD approach by first defining the domains of the business along with their responsibilities. An E-Commerce company might have different domains like “warehouse”, “store” etc. The next step is to define the responsibilities of those domains. For example, the “warehouse” has the responsibility to ship the books whereas the “store” domain has the responsibility to sell the books. Both domains have their bounded context and certainly need not interfere in each other work or know each other working style. So this is where we can decouple the context and keep individual context and its implementation hidden from the outside world.
您应该首先定义业务领域及其职责来开始DDD方法。 电子商务公司可能具有不同的域,例如“仓库”,“商店”等。下一步是定义这些域的职责。 例如,“仓库”负责运送书籍,而“商店”域负责出售书籍。 这两个领域都有各自的局限性,因此当然不必干涉彼此的工作或彼此了解工作风格。 因此,在这里我们可以分离上下文,并使单个上下文及其实现对外界隐藏。
Now we need to identify the events related to domains. In “Warehouse” and “Store” context that can be “Order placed”, “Shipping label generated”, “Order shipped” etc. These events can be either manually driven or automatic. In DDD, it’s an important concept that we do not care about the actor or individual, we care about the ROLE and its associated events. For example if a user login and create an invoice then we don’t care about that individual user, we care about the user’s role i.e. “accounts” and the event “create an invoice” which the user performs. Basically while deriving events we are defining the “WHEN” part of the domain.
现在,我们需要确定与域相关的事件。 在“仓库”和“商店”上下文中,可以是“已下订单”,“已生成发货标签”,“已发货订单”等。这些事件可以手动驱动也可以自动驱动。 在DDD中,这是一个重要的概念,我们不在乎演员或个人,我们在乎ROLE及其相关事件。 例如,如果用户登录并创建发票,则我们不在乎该个人用户,而是在关注用户的角色(即“帐户”)和用户执行的事件“创建发票”。 基本上,在派生事件时,我们定义域的“何时”部分。
Once events are identified then we determine “Actions”. Actions are triggered by events. For example “order initiated” event might trigger “Check inventory, Initiate the payment process &Issue invoice” actions in the business. By defining the actions we define “WHAT” will happen in correspondence to the events. We need to simply associate events and actions to create a flow and end the flow with “X” where you feel that flow ends and no action is required further.
确定事件后,我们将确定“操作”。 动作由事件触发。 例如,“订单已启动”事件可能会触发业务中的“检查库存,启动付款流程和开具发票”操作。 通过定义动作,我们定义了与事件相对应的“事件”。 我们只需要简单地将事件和动作相关联即可创建一个流程,并以“ X”结束该流程,在该流程中您会感觉到流程已结束且无需进一步操作。
Once events and actions are been determined then we need to determine the ROLE to define “WHO” will be doing that action or who will respond to those events. This definition of “WHO” is important to derive the boundaries as well as work associated with actions. There can be different actions associated with the same object in different contexts. For example, an Order entity means something different for both “store” and “warehouse” context. A new order means create an invoice and generate shipping labels from the store context. Whereas a new order means shipping the product in a warehouse context. So we have to define “WHO” will handle that object or event or action. By this action, you can even determine how many processes or actions are man power-dependent and how many actions can be automated.
确定事件和动作后,我们需要确定角色以定义“ WHO”将执行该动作或由谁响应这些事件。 “世界卫生组织”的这一定义对于得出界限以及与行动有关的工作很重要。 在不同的上下文中,可能有与同一对象关联的不同动作。 例如, Order实体对于“商店”和“仓库”上下文来说意味着不同的东西。 新订单意味着创建发票并根据商店环境生成运输标签。 而新订单意味着要在仓库中运输产品。 因此,我们必须定义“ WHO”将处理该对象,事件或操作。 通过此操作,您甚至可以确定有多少个流程或操作与人力相关,以及有多少个操作可以自动化。
编排 (Orchestration)
Bounded context can communicate via services. Orchestration of different bounded contexts can be done in two models i.e. Declarative model and reactive model.
有界上下文可以通过服务进行通信。 可以在两个模型中完成不同有界上下文的编排,即声明性模型和React性模型。
Declarative — As the name implies, this model works by declaring the work which needs to be performed by different entities. One entity tells other entities what to do. It has a natural flow of declaration in the top-down approach which creates a tight relation between different entities. This tight relation often leads to an inherent maintenance problem that if you change any downstream entity then all upstream context has to check and changed if required. For example, once an order is placed then it can invoke the services or methods or other microservices to “create shipping label” and “generate receipt”. Now if you want to make a change in “generating receipt” then you need to check the “order entity” too to make sure that the change in the “generate receipt” entity does not effect to “order entity”. In the declarative model “order entity” has to know about “generate receipt” to call its methods which makes this strongly bounded and non decoupled.
声明性的-顾名思义,该模型通过声明需要由不同实体执行的工作来工作。 一个实体告诉其他实体该怎么做。 自上而下的方法具有自然的声明流程,可在不同实体之间建立紧密的关系。 这种紧密的关系通常会导致一个固有的维护问题,即如果您更改任何下游实体,那么所有上游上下文都必须检查并在需要时进行更改。 例如,一旦下订单,它就可以调用服务或方法或其他微服务来“创建运输标签”和“生成收货”。 现在,如果您想更改“生成收货”,则还需要检查“订单实体”,以确保“生成收货”实体中的更改不会影响“订单实体”。 在声明性模型中,“订单实体”必须了解“生成收货”才能调用其方法,从而使此方法成为有界和非解耦的。
Reactive — In the reactive model, no two entities in different bounded contexts know each other implementation details. They are completely isolated and decoupled from each other and do not know about the existence of others in the world. They communicate via the PUB SUB model where the “order” entity publishes an event “order placed” and all other entities who are subscribed to that event are designed to perform defined work. In the reactive model if you change the “generate receipt” entity then you need not change anything in the “order entity” as the published event is still “order placed” and as long as the “generate receipt” entity can respond to that event and perform the assigned task then everything is normal.
React式-在React式模型中,没有两个处于不同有界上下文中的实体彼此知道实现细节。 它们是完全隔离和彼此分离的,并且不知道世界上其他人的存在。 它们通过PUB SUB模型进行通信,其中“订单”实体发布事件“已下订单”,而订阅该事件的所有其他实体均旨在执行定义的工作。 在React模型中,如果您更改“生成收货”实体,则无需更改“订单实体”中的任何内容,因为发布的事件仍是“已下订单”,并且只要“生成收货”实体可以响应该事件然后执行分配的任务,那么一切正常。
The right way to achieve the true microservice architecture is by Reactive Model. There are several services in the market like Kafka, RabbitMQ, ZeroMQ, AQS SQS, etc which can be used to create these event queues to achieve the decoupled architecture.
实现真正的微服务架构的正确方法是通过Reactive Model。 市场上有几种服务,例如Kafka,RabbitMQ,ZeroMQ,AQS SQS等,可用于创建这些事件队列以实现分离的体系结构。
域驱动设计的优势 (Advantages of Domain-Driven Design)
- Effective communication — Use of common language helps better collaboration between developers, business users, and stakeholders. Everyone can talk in the same language about an object in the defined context. 有效的沟通-使用通用语言有助于开发人员,业务用户和利益相关者之间更好的协作。 每个人都可以在定义的上下文中以相同的语言谈论对象。
- Effective Control — DDD approach helps business owners to keep control over the implementation of technology while not knowing anything about technology because of the common ubiquitous language. 有效控制-DDD方法可帮助企业所有者控制技术的实施,同时由于通用的通用语言而对技术一无所知。
- Incremental Approach — DDD allows business users and developers to focus on the current problems and provide quick incremental updates rather than waiting for a big release date. 增量式方法— DDD使业务用户和开发人员可以专注于当前问题并提供快速的增量式更新,而不必等待大量发布日期。
- Flexible — It is flexible because of the strong encapsulation of bounded contexts which make it less painful to adopt and deliver changes. 灵活-之所以灵活,是因为对有约束的上下文进行了强大的封装,这使采用和交付更改的过程变得更加轻松。
域驱动设计的缺点 (Disadvantages of Domain-Driven Design)
- High initial investment — DDD approach requires high investment initially to derive a DDD diagram. It also requires the active involvement of the business user which also increases the investment of the product. 高初始投资-DDD方法最初需要大量投资才能得出DDD图。 它还需要业务用户的积极参与,这也增加了产品的投资。
- Business user availability — It requires the continuous availability of business users to derive the correct language used in the content. It also requires developers to learn the domain before starting the code. 业务用户可用性—它要求业务用户具有连续可用性,以派生内容中使用的正确语言。 它还要求开发人员在启动代码之前先学习领域。
But overall, I feel that DDD along with microservices can be a good approach to design medium or large size applications to keep both business and developers involved actively in each incremental update but this can be an overhaul for small scale products.
但是总的来说,我认为DDD与微服务一起可能是设计中型或大型应用程序的好方法,以使业务和开发人员都积极参与每次增量更新,但这可能是对小规模产品的全面检查。
翻译自: https://medium.com/swlh/domain-driven-design-and-microservices-c62255790c3b
领域驱动设计 微服务