有人能举例说明域服务和应用程序服务之间的区别吗?而且,如果一个服务是一个域服务,我是否会将该服务的实际实现放在域程序集中,如果是的话,我是否也会将存储库注入到该域服务中?一些信息会很有帮助。
当前回答
域服务:表示不属于任何聚合根的业务逻辑的服务。
You have 2 Aggregate: Product which contains name and price. Purchase which contains purchase date, list of products ordered with quantity and product price at that time, and payment method. Checkout is not part of either of these two models and is concept in your business. Checkout can be created as a Domain Service which fetches all product and compute the total price, pay the total by calling another Domain Service PaymentService with an implementation part of Infrastructure, and convert it into Purchase.
应用程序服务:“编排”或执行域方法的服务。这可以像你的控制器一样简单。
这是你经常做的事情:
public String createProduct(...some attributes) {
if (productRepo.getByName(name) != null) {
throw new Exception();
}
productId = productRepository.nextIdentity();
product = new Product(productId, ...some attributes);
productRepository.save(product);
return productId.value();
// or Product itself
// or just void if you dont care about result
}
public void renameProduct(productId, newName) {
product = productRepo.getById(productId);
product.rename(newName);
productRepo.save(product);
}
您可以在这里进行验证,例如检查Product是否惟一。除非产品是唯一的,否则它应该是域服务的一部分,可能被称为UniqueProductChecker,因为它不能是产品类的一部分,它与多个聚合进行交互。
下面是DDD项目的完整示例:https://github.com/VaughnVernon/IDDD_Samples
你可以找到很多应用程序服务和一些域服务的例子
其他回答
域服务:表示不属于任何聚合根的业务逻辑的服务。
You have 2 Aggregate: Product which contains name and price. Purchase which contains purchase date, list of products ordered with quantity and product price at that time, and payment method. Checkout is not part of either of these two models and is concept in your business. Checkout can be created as a Domain Service which fetches all product and compute the total price, pay the total by calling another Domain Service PaymentService with an implementation part of Infrastructure, and convert it into Purchase.
应用程序服务:“编排”或执行域方法的服务。这可以像你的控制器一样简单。
这是你经常做的事情:
public String createProduct(...some attributes) {
if (productRepo.getByName(name) != null) {
throw new Exception();
}
productId = productRepository.nextIdentity();
product = new Product(productId, ...some attributes);
productRepository.save(product);
return productId.value();
// or Product itself
// or just void if you dont care about result
}
public void renameProduct(productId, newName) {
product = productRepo.getById(productId);
product.rename(newName);
productRepo.save(product);
}
您可以在这里进行验证,例如检查Product是否惟一。除非产品是唯一的,否则它应该是域服务的一部分,可能被称为UniqueProductChecker,因为它不能是产品类的一部分,它与多个聚合进行交互。
下面是DDD项目的完整示例:https://github.com/VaughnVernon/IDDD_Samples
你可以找到很多应用程序服务和一些域服务的例子
将域服务视为在域对象上实现业务逻辑或业务规则相关逻辑的对象,这种逻辑很难适合相同的域对象,也不会导致域服务的状态更改(域服务是一个没有“状态”的对象,或者更好的是没有具有业务含义的状态),但最终只会更改所操作的域对象的状态。
应用程序服务实现了应用程序级逻辑,如用户交互、输入验证、与业务无关的逻辑,而是与其他关注点相关的逻辑:身份验证、安全性、电子邮件等等。,将自身限制为简单地使用域对象公开的服务。
这方面的一个例子可能是以下场景,只是为了解释目的:我们必须实现一个非常小的domotic实用程序,执行一个简单的操作,即“当有人打开房间的门进入房间时打开灯,当有人关闭房间的门离开房间时关闭灯”。
简化很多,我们只考虑2个域实体,它们不是同一个集合的一部分:门和灯,它们每个都有2个状态,分别是打开/关闭和打开/关闭,以及在它们上操作状态更改的特定方法。实体需要是不同聚合的一部分,这样下面的逻辑就不能在聚合根中实现。
在这种情况下,我们需要一个域服务来执行当有人从外部打开门进入房间时打开灯的特定操作,因为门和灯对象不能以我们认为适合其业务性质的方式实现此逻辑。这个新的域服务需要封装一些应该总是发生的业务流程,由一些域事件/方法触发。
我们可以调用我们的域服务DomoticDomainService并实现两个方法:OpenTheDoorAndTurnOnTheLight和CloseTheDoorAndTurnOffTheLight,这两个方法分别改变对象门和灯的状态为打开/打开和关闭/关闭。
The state of enter or exit from a room it isn't present in the domain service object and either in the domain objects, but will be implemented as simple user interaction by an application service, that we may call HouseService, that implements some event handlers as onOpenRoom1DoorToEnter and onCloseRoom1DoorToExit, and so on for each room (this is only an example for explaining purpose..), that will respectively concern about call domain service methods to execute the attended behaviour (we haven't considered the entity Room because it is only an example).
这个例子,远远不是一个设计良好的现实世界的应用程序,有唯一的目的(已经说过很多次了)解释什么是域服务以及它与应用程序服务的区别,希望它是清晰和有用的。
同样,上面的示例域服务可以很容易地被用于显式实现跨一个或多个聚合的副作用的域事件所取代,但由于这些不是这个问题的主题,所以我在这里只提到它们,以便读者可以意识到它们的存在,然后决定哪种方法更适合它们。
域服务是域的扩展。应该只在域的上下文中看到它。这不是像关闭帐户之类的用户操作。域服务适用于没有状态的地方。否则它就是一个域对象。域服务只有在与其他协作者(域对象或其他服务)合作时才有意义。这是另一层人的责任。
Application service is that layer which initializes and oversees interaction between the domain objects and services. The flow is generally like this: get domain object (or objects) from repository, execute an action and put it (them) back there (or not). It can do more - for instance it can check whether a domain object exists or not and throw exceptions accordingly. So it lets the user interact with the application (and this is probably where its name originates from) - by manipulating domain objects and services. Application services should generally represent all possible use cases. Probably the best thing you can do before thinking about the domain is to create application service interfaces what will give you a much better insight in what you're really trying to do. Having such knowledge enables you to focus on the domain.
一般来说,存储库可以被注入到域服务中,但这种情况相当罕见。不过,大多数时候是应用层在做这件事。
帮助我理解应用程序服务和域服务之间区别的最好的资源是Eric Evans的cargo示例的java实现,可以在这里找到。如果你下载了它,你可以检查RoutingService(域服务)和BookingService, CargoInspectionService(应用服务)的内部结构。
我顿悟的时刻是由两件事引发的:
阅读上述链接中对服务的描述,更准确地说是这句话:
域服务用通用语言和表示 域类型,即方法参数和返回值为 正确的域类。
阅读这篇博文,尤其是这一部分:
我发现区分苹果和橘子有很大帮助的是 从应用程序工作流的角度考虑。所有关于 应用程序工作流通常以应用程序服务结束 考虑到应用层,而来自领域的概念 这似乎不适合模型对象最终形成一个或多个 域服务。
Domain Services : Methods that don’t really fit on a single entity or require access to the repository are contained within domain services. The domain service layer can also contain domain logic of its own and is as much part of the domain model as entities and value objects. Application Services : The Application service is a thin layer that sits above the domain model and coordinates the application activity. It does not contain business logic and does not hold the state of any entities; however, it can store the state of a business workflow transaction. You use an Application service to provide an API into the domain model using the Request-Reply messaging pattern.
米勒特,C(2010)。专业的ASP。NET设计模式。威利出版。92。
推荐文章
- “Layers”和“Tiers”的区别是什么?
- 一般来说,在一个组件中使用一个还是多个useEffect钩子更好?
- 何时以及如何在微服务架构中使用GraphQL
- 服务应该总是返回dto,还是也可以返回域模型?
- “协程”和“线程”之间的区别?
- 当Node.js内部仍然依赖线程时,它是如何固有地更快的?
- 允许PHP应用程序使用插件的最佳方法
- 会话锁导致ASP。网络网站速度慢
- 什么是领域驱动设计?
- 基于组件的游戏引擎设计
- 如何防止网站刮取?
- 软件设计与软件体系结构
- 领域驱动设计:领域服务、应用服务
- INotifyPropertyChanged vs. ViewModel中的DependencyProperty
- 什么是数据传输对象(DTO)?