首先,我使用的是没有任何 ORM 框架的网络表单。
我一直在努力研究如何让我的域对象尽可能“智能”和“丰富”,同时又不允许它们访问我的服务和存储库层。我最近的尝试是为在线商店创建礼券模型。
我看到的主要反复出现的问题是:
服务层不断引入越来越多的逻辑。所有对存储库的调用都必须通过服务层,并且每次都验证参数(例如 - 存在于数据库中等)。结果我的服务层在增长,但我的领域对象只有一些简单的契约(Contract)验证。甚至对象验证也在服务层,因为如果项目的 ID 为空,它将检查数据库以确保代码是唯一的。 IHMO,系统的消费者不应该关心他们需要的功能是否处理持久性。
我有一个单独的 POCO 用于兑换礼券时的交易日志条目。我假设我应该将这些交易的列表或集合作为我的礼券模型的属性,但我仍然不确定何时应该填写该属性。我是否在服务上添加一个单独的方法来按需将交易加载到对象中(例如 - LoadTransactions(gc object)),或者是否应该在任何时候请求现有礼券或礼券列表时自动加载交易(或者可能getGCs 中的一个选项也可以加载事务)
像“可用余额”这样的计算字段怎么样……我什至应该在我的对象上有这样的属性吗?每当我使用该对象时,我都需要不断更新该属性以确保它是最新的。现在我只有一个服务方法 GetBalanceByCode(gc code)。
即使像兑换礼券这样的操作基本上也是 100% 以数据为中心的(获取一些输入参数,验证它们并将交易日志条目添加到数据库)。
最佳答案
More and more logic keeps being introduced in the service layer (...) Even object validation is in the service layer (...)
验证不是领域模型元素的最佳候选者。输入(我个人的偏好是它表示为命令)应该在应用程序服务级别进行验证。领域逻辑应该对业务的运作方式进行建模,并假设所有参数都是有效的。域逻辑的良好候选者是计算,例如:您希望将它们放在一个地方并对其进行良好测试。
I have a separate POCO for transaction log entries for when a gift certificate is redeemed.
这种对象称为事件。您可以从 Eric Evans 了解事件 'What I learnt since the Blue Book'推介会。事件基本上是一个不可变的实体。事件通常是自己聚合的,因为通常有很多事件。通过使它们聚合,您可以轻松地将它们作为其他对象集合的一部分进行延迟加载。
What about computed fields like "Available Balance"... should I even have properties like this on my object?
计算属性是一种自然适合域模型的逻辑,但是是否有更好的方法是每次计算值或在对象更改时计算值并将其保存在数据库中,这是值得商榷的。
Even actions like redeeming a gift certificate are basically 100% data-centric (take some input parameters, validate them and add a transaction log entry to db).
此操作将建模为创建 CertificateRedeemed 事件。此事件可能由证书聚合或其他一些对象创建。这blog post Udi Dahan 的文章可能会有所帮助
关于c# - 如何在保持持久性无知的同时创建丰富的领域对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6202856/