如何处理域类中的依赖行为? [英] How to handle dependent behavior in a domain class?

查看:93
本文介绍了如何处理域类中的依赖行为?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

比方说,我有一个域类,它具有要按顺序调用的功能。每个函数都执行其工作,但如果序列中的上一步尚未完成,则会引发错误。另一种方法是每个功能完成其运行所需的步骤,然后执行自己的逻辑。我觉得这种方式不是一个好习惯,因为我要添加多个职责,并且调用方在调用方法时将不知道所有操作都会发生什么。

Let's say I've got a domain class, which has functions, that are to be called in a sequence. Each function does its job but if the previous step in the sequence is not done yet, it throws an error. The other way is that each function completes the step required for it to run, and then executes its own logic. I feel that this way is not a good practice, since I am adding multiple responsibilities, and the caller wont know what all operations can happen when he invokes a method.

我的问题是,如何处理DDD中的依赖方案。调用者有责任按正确的顺序调用方法吗?还是我们让方法在依赖逻辑之前处理依赖的操作?

My question is, how to handle dependent scenarios in DDD. Is it the responsibility of the caller to invoke the methods in the right sequence? Or do we make the methods handle the dependent operations before it's own logic?

推荐答案

TLDR;滚动到底部寻找答案,但背景故事会提供一些良好的上下文。

TLDR; Scroll to the bottom for the answer, but the backstory will give some good context.

如果进入您域的呼叫者必须知道呼叫的顺序,那么您错过了将业务逻辑封装到您的域中的机会,这是贫乏域的症状

If the caller into your domain must know the order in which to call things, then you have missed an opportunity to encapsulate business logic in your domain, which is a symptom of an anemic domain.

@RobertBräutigam提出了一个很好的观点:

@RobertBräutigam made a very good point:


需要一个序列技术调用是时间耦合的一种形式,被认为是一种不好的做法,与DDD没有直接关系。

Requiring a sequence of technical calls is a form of temporal coupling, it is considered a bad practice, and is not directly related to DDD.

,但是在您使用域模型进行操作时,这会变得更糟 ,因为非域关注点与域关注点混杂在一起。在非业务逻辑的海洋中,意图迷失了。如果可以,您会寻找封装顺序的较高阶集合。借用罗伯特(Robert)的例子,您可以让 Vacation (假期)汇总并同时进行验证,而不是先预订航班然后再预订酒店房间,然后强迫客户这样做。

This is true, but it is worse when you do it with your domain model because non-domain concerns get intermixed with domain concerns. Intent becomes lost in a sea of non business logic. If you can, you look for a higher-order aggregate that encapsulates the ordering. To borrow Robert's example, rather than booking a flight then a hotel room, and forcing that on the client, you could have a Vacation aggregate take both and validate it.

我知道您的情况听起来错误,我怀疑您是对的。显然存在不能同时发生的依赖性,因此我们不可能成为故事的结局。当您对必须在最终状态之前发生的中间事务有明确的依赖性时,我们就可以进行…编排(考虑sagas,分布式事务,域事件和所有这些好处)。

I know that sounds wrong in your case, and I suspect you're right. There's a clear dependency that can't happen all at once, so we can't be the end of the story. When you have a clear dependency with intermediate transactions that must occur before the "final" state, we have... orchestration (think sagas, distributed transactions, domain events and all that goodness).

使用文件操作描述的内容涉及事务。域的操作(状态更改)在分布式事务中的每个点都是事务性的,但不是整体事务性的。因此,当@ choquero70说

What you describe with file operations spans across transactions. The manipulation (state change) of a domain is transactional at each point in a distributed transaction, but is not transactional overall. So when @choquero70 says


时,您描述的是领域模型操作的编排。这就是应用程序层(基于域模型的层)的工作。

you are describing is the orchestration of domain model operations. That's the job of the application layer, the layer upon domain model.

这也是正确的。编排是关键。每个步骤必须一次,仅一次操纵域的状态,并将其保持在有效状态,但是可以有多个步骤。

that's also correct. Orchestration is key. Each step must manipulate the state of the domain once, and once only, and leave it in a valid state, but it OK for there to be multiple steps.

时间轴上的每个单独点都是您所在域状态下的有效时刻

因此,回到模型。如果您公开了一个接口,并且可能对 all 步骤进行了多次调用,那么您将无所事事。使它不可能或至少不可能。编排不仅是要做什么,而且是要防止发生什么。创建较小的接口/类,以避免意外增加可能被误用的内容的表面积。

So, back to your model. If you expose a single interface with multiple possible calls to all steps, then you leave yourself open to things being called out of order. Make this impossible or at least improbable. Orchestration is not just about what to do, but what to prevent from happening. Create smaller interfaces/classes to avoid accidentally increasing the "surface area" of what could be misused accidentally.

通过这种方式,您可以指导调用者下一步操作通过向它们提供有效的中间状态。但是,这是重要的部分,按呼叫顺序的呼叫负担不是呼叫者上的。当然,调用者知道该怎么做,但是为什么要强制执行。

In this way, you are guiding the caller on what to do next by feeding them valid intermediate states. But, and this is the important part, the burden on what to call in what order is not on the caller. Sure, the caller could know what to do, but why force it.

您的基本算法是相同的:上载,转换,下载。

Your basic algorithm is the same: upload, transform, download.


调用者是否有责任按正确的顺序调用方法?

Is it the responsibility of the caller to invoke the methods in the right sequence?

不完全是。给定您域的状态,呼叫者有责任从合法选择中进行选择。通过正确建模的瞬间/间隔聚合适合调用者使用。

Not exactly. Is the responsibility of the caller to choose from legitimate choices given the state of your domain. It's "your" responsibility to present these choices via business methods on your correctly modeled moment/interval aggregate suitable for the caller to use.


还是让方法处理

Or do we make the methods handle the dependent operations before it's own logic?

如果您已正确设置业务流程,则不需要这样做。不管怎么说,这样做还是有意义的。

If you've setup orchestration correctly, this won't be necessary. But it does make sense to validate anyway.

另一方面,业务流程的每个步骤本质上都应该是线性的。我告诉开发人员对其中包含 if 语句的编排步骤感到怀疑。如果存在 if ,则最好将其作为另一个编排步骤的一部分或封装在业务逻辑中。

On a side note, each step of the orchestration you do should be very linear in nature. I tell my developers to be suspicious of an orchestration step that has an if statement in it. If there's an if it's likely better to be part of another orchestration step or encapsulated in business logic.

这篇关于如何处理域类中的依赖行为?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆