简体   繁体   English

当作用域对象而不是作用器时,如何使用方法表示域对象的行为?

[英]How do you represent domain object behaviors using methods when a domain object is acted upon and not the actor?

In Domain Driven Design, there is an emphasis of placing behaviors where they correctly belong. 在域驱动设计中,强调将行为正确地放置在它们的位置。 I'm not always sure what exactly constitutes "correct," though. 不过,我并不总是确定确切的含义是什么。

Consider this scenario: "The client withdraws an amount of money from a bank account." 请考虑以下情形: “客户从银行帐户中提取了一定数量的钱。”

Grammatically, we have that: 在语法上,我们有:

  • 'client' is a subject “客户”是一个主题

  • 'withdraw' is a verb “撤回”是动词

  • 'amount' is a direct object “金额”是直接对象

  • 'account' is an affected prepositional object “帐户”是受影响的介词对象

Classically, the client would execute this: account.withdraw(amount) . 传统上,客户端将执行以下命令: account.withdraw(amount)

This could be read as: "The client commands a bank account to withdraw an amount of money." 可以理解为: “客户命令一个银行帐户提取一定数量的钱。” However, this does not grammatically correspond to the original scenario, since 'bank account' is now the direct object and an infinitive removes 'withdraw' and 'amount' from the main clause so that the primary idea conveyed is that 'client commands account'. 但是,这在语法上与原始方案不符,因为“银行帐户”现在是直接对象 ,并且不定式从主要子句中删除“提款”和“金额”,因此传达的主要思想是“客户命令帐户” 。

To adhere to DDD, we should regard this code as precisely describing the original scenario. 为了遵守DDD,我们应该将此代码视为精确描述原始方案。 This implies that the 'withdraw' method does not model a behavior performed by the account (the account is not a subject ), but rather it models a behavior that indirectly affects it (the account is a prepositional object ) and could very well be renamed 'wasWithdrawnFrom'. 这意味着'withdraw'方法不会对帐户执行的行为进行建模(帐户不是主题 ),而是对间接影响帐户的行为进行建模(帐户是介词对象 ),并且很可能会被重命名“ wasWithdrawnFrom”。 Moreover, the method argument represents something being affected by the client as opposed to by the object (it is a direct object for a client subject , not an object subject ). 此外,方法参数表示受客户端影响而不是受对象影响某种东西(它是客户端主题直接对象 ,而不是对象主题 )。

If we extrapolate from this example, we can see that methods may represent behaviors that affect the object (object is not the subject) and method arguments may represent direct objects of a client subject . 如果从此示例进行推断,我们可以看到方法可以表示影响对象的行为(对象不是主题) ,方法参数可以表示客户主题的直接对象

However, whether or not methods should represent behaviors performed by objects is unclear. 但是,尚不清楚方法是否应表示对象执行的行为

So my question is: How should we use methods to model object behavior? 所以我的问题是: 我们应该如何使用方法来建模对象行为?

1) Methods should strictly represent behaviors that affect the object. 1)方法应严格表示影响对象的行为。 (The object cannot act as a subject, only a grammatical direct/indirect/prepositional object) (宾语不能充当主语,只能是语法上的直接/间接/介词宾语)

2) Methods may represent both behaviors that affect the object as well as behaviors performed by the object. 2)方法可以表示影响对象的行为以及对象执行的行为。 (The object may act as a subject or a grammatical direct/indirect object) (该对象可以充当主语或语法上的直接/间接对象)

You seems to be stuck in a theoretical thesis. 您似乎陷入了理论论点。 I'm not sure you can apply a theory that works for every scenario/project. 我不确定您是否可以应用适用于每个方案/项目的理论。 Behaviors usually appears when you start bombarding your Model with Use Cases. 当您开始用用例轰炸模型时,通常会出现行为。 I try to let the cases dictate behaviors. 我试图让案件决定行为。 To follow your example: 遵循您的示例:

Actor Customer want to withdraw money from Account. 演员客户想从帐户中提款。 The way to do it is like you do Account.Withdraw(Money amount) 这样做的方式就像您执行Account.Withdraw(Money amount)

But your question "How should we use methods to model object behavior?" 但是您的问题是“我们应该如何使用方法来模拟对象行为?” is a common DDD question. 是一个常见的DDD问题。 How to enrich your model with behavior? 如何用行为丰富模型? My best hints is to find your Value Objects. 我最好的提示是找到您的价值对象。 Value objects usually comes with behavior. 价值对象通常带有行为。

In example Account is and Entity (Aggregate root probably). 在示例中,Account is和Entity(可能是聚合根)。 Money (Value object with Currency and Amount) should be withdrawn from an Account. 钱(带有货币和金额的价值对象)应从帐户中提取。 That should be Account Single Responsible (Principle) to control that Account balance and all access to it. 这应该是“帐户单一负责人”(原则),以控制该帐户余额及其所有访问权限。 Regarding your (2) question in the end. 最后,关于您的(2)问题。 Methods are absolutely used for change the objects inner state. 方法绝对用于更改对象的内部状态。 But when it comes to behaviors performed by the entity/value object like Customer.Order(newOrder) or advert.Apply(candidateCV) we can make entities communicate with each other. 但是,当涉及到由诸如Customer.Order(newOrder)或advert.Apply(candidateCV)之类的实体/值对象执行的行为时,我们可以使实体彼此通信。 We can also create chained behaviors through Domain Events which can help us not to leak to much business logic to our application services. 我们还可以通过域事件创建链接的行为,这可以帮助我们避免泄漏过多的业务逻辑到我们的应用程序服务中。 See Udi Dahan's blog for that or my blog article regarding Anemic Domain model http://magnusbackeus.wordpress.com/2011/05/31/preventing-anemic-domain-model-where-is-my-model-behaviour/ 请参阅Udi Dahan的博客,或我的有关Anemic Domain模型的博客文章http://magnusbackeus.wordpress.com/2011/05/31/preventing-anemic-domain-model-where-is-my-model-behaviour/

I Hope you got some ideas. 我希望你有一些想法。 It's difficult to give concrete hints when we are so abstract here. 当我们在这里如此抽象时,很难给出具体的提示。 /Best regards Magnus /最好的问候马格努斯

I find that scenario too simple to be real, hence too simplistic to model too. 我发现这种情况太简单了,无法实现,因此也太简单了,无法建模。 I would reformulate the 我会重新制定

"The client withdraws an amount of money from a bank account." “客户从银行帐户中提取了一定数量的钱。”

to something like

"The client submits withdrawal request of value xxx $ from his account" (when I go to my bank I have to fill out a form in order to withdraw money where I state amount, the account number, date and my signature) “客户从他的帐户中提交了价值XXX $的提款请求” (当我去银行时,我必须填写一张表格以提款,并在其中注明金额,帐号,日期和我的签名)

There one can spot a request ( command ) to a service ( withdrawal service ) of an client ( client identified by ID ) from his account ( account identified by ID ) and the money value ( money as value object ). 在那里,可以从客户的帐户( 由ID标识的帐户 )和货币价值( 作为价值对象的货币)发现对客户( 由ID标识的客户)的服务( 取款服务 )的请求( 命令 )。

I don't care much about the grammar, as English is my second language so when trying to understand the Domain, I try to understand how the business sees the concepts (Account) and workflows (withdraw an amount) and not to do grammar analysis. 我不太在意语法,因为英语是我的第二语言,因此在尝试理解域时,我会尝试了解企业如何看待概念(帐户)和工作流程(提取金额),而不去进行语法分析。

The point of DDD is to model things like they are in the business, so behaviour shows up according to Domain understanding. DDD的目的是对业务中的事物进行建模,以便根据对域的理解来显示行为。

in this scenario, for me it's clear that we're working within the Account Operations Bounded Context and at least the Account aggregate root is involved. 在这种情况下,对我来说很明显,我们正在“帐户操作有界”上下文中工作,并且至少涉及“帐户聚合根”。 Of course, in banking terms, probably (I'm guessing here) there will not be a withdrawl but an operation to increase the Debit/Credit part of an account, so most likely the account will register that a debit/credit operation has happened. 当然,从银行业的角度来看,可能(我想在这里)不会进行取款,而是会执行一项操作来增加帐户的借方/贷方部分,因此该帐户很可能会记录发生了借方/贷方操作。 And a Domain Event is born and published. 域事件诞生并发布。 Then let the domain expert tell you what will happen next. 然后,让域专家告诉您接下来将发生什么。

"The client deletes an order" => order.delete “客户删除订单” => order.delete

Probably the order is never deleted, but its status will changed to 'canceled' or similar. 可能永远不会删除订单,但是其状态将更改为“已取消”或类似状态。 However for that case when an order really should be deleted, the order doesn't delete itself, the Orders repository deletes that order. 但是,对于这种情况,当确实要删除订单时,订单不会自行删除,而订单存储库会删除该订单。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM