在包含大量CRUD功能的应用程序中实现DDD,再加上某种类型的Web-API,最终会出现这样一种情况:使用平台提供的工具可以使相对简单的事情变得更加容易难。例如:
假设我们有一个User对象,并且您正在努力不创建贫血域模型,因此您可以建模更具表现力的操作:
class User {
public void terminateAccount(TeminationReason reason);
public void reactivateAccount();
}
上面的类很好,因为它允许我们将帐户标记为已终止并立即设置原因。显然是对setEnabled(false)和setTerminationReason(..)的改进。
简而言之,假设我们有类似JAX-RS Web服务的东西,它可以对该用户进行GET / PUT。框架(JAX-RS,JAXB)将为我们轻松地序列化和反序列化我们的DTO对象。现在,我们以前可以做到的地方:
entity.setEnabled(dto.isEnabled);
entity.setTerminationReason(dto.getTerminationReason);
我们必须改为:
if (entity.isEnabled() && !dto.isEnabled()) {
entity.terminateAccount(dto.getTerminationReason);
} else if (!entity.isEnabled && dto.isEnabled) {
entity.reactivateAccount();
}
这里的大连接是域对象的面向业务的接口,以及RESTful API上的CRUD样式访问模式。既然DDD和REST都是他们自己权利的最佳实践,那么每个人都学到了什么教训,使上面的代码不那么痛苦/重复/等等?
PS - 我们正在使用DTO,因为在幕后使用ORM框架时,实际上将实体序列化为XML / JSON是个问题,因为我们无法限制延迟加载。您通常希望通过RESTful API(参考URL等)公开不同的属性,这些属性不属于域模型。我也愿意接受建议。答案 0 :(得分:4)
我认为这里的问题是您尝试使用单个DTO在所有API中表示User
实体。相反,如果每个操作都有一个单独的DTO,只包含所需的数据,那么代码就会简单得多。
例如,TerminateAccount
API会有一个只有终止原因的DTO,而您的代码只是:
user.terminateAccount(dto.terminationReason);