DDD 中的域对象是“自我验证的”。换句话说,客户端代码不可能破坏域规则,因为对象强制执行其内部不变量。例如:
public class Invoice {
private Money _amount;
private InvoiceState _state;
public void ChangeAmount(Money newAmount) {
if(_state == State.Booked) {
throw new InvalidOperationException(
"Unable to change amount for booked invoice.");
}
_amount = newAmount;
}
// Methods like this can be used by external code (UI) to check business
// rules upfront, to avoid InvalidOperationException.
public Boolean CanChangeAmount() {
if(_state == State.Booked) {
return false;
}
return true;
}
}
另一个例子来自DDD样本:
public HandlingEvent(final Cargo cargo,
final Date completionTime,
final Date registrationTime,
final Type type,
final Location location,
final Voyage voyage) {
...
if (type.prohibitsVoyage()) {
throw new IllegalArgumentException(
"Voyage is not allowed with event type " + type);
}
永远不要让你的 UI 框架将域对象视为哑数据容器。不幸的是,互联网上的大量示例以及 C# 对 getter 和 setter 的强调都鼓励了这一点。如果您更改对象状态而不强制执行业务规则,您最终将得到“损坏”的对象。对于 NHibernate 来说尤其如此,因为它的 Session 会“记住”所有对象,并且会在下次提交或刷新时将它们转储到数据库中。但这只是一个技术问题,主要原因是您需要能够仅通过查看 Invoice 类来推理 Invoice 相关的业务规则。另请注意,代码应基于无处不在的语言。您应该看到“发票”、“预订”、“金额”等字样,而不是通用的“字段”、“财产”、“验证器”。
更新:empi,感谢您重述您的问题。您可能想提出一个新问题。这是我强调的引用
正如我在一条评论中所说 - 这个问题是一个更大的问题的一部分
我遇到的问题。我正在寻找定义域的标准方法
仅在域中的逻辑和约束,然后将其转换为 GUI
和其他层。我没有看到以下任何常见模式
常见需求:域声明该字段不可编辑,并且这
规则自动转换为GUI逻辑禁用该字段
并使其只读。我正在寻找 mvc 堆栈中的示例解决方案。我
感觉就像我在重新发明轮子,而大多数开发人员只是放弃
并复制 gui 中的逻辑
我认为您正在寻找一种方法来陈述域中的所有内容,然后“生成”UI。就像是裸露物体 for MVC?我从未使用过这种方法,但我怀疑生成的 UI 是否会赢得美观或可用性竞赛。在我看来,UI 中总会有一些业务逻辑的“重述”。一些领域不变量太复杂,涉及多个领域,需要存储库,甚至可能需要外部服务。我不确定是否可以自动生成高质量的用户界面。我认为尝试这样做可能会开始改变你的模型以符合 UI 基础设施。