DDD和CRUD类型的应用程序

时间:2012-07-23 03:30:17

标签: java domain-driven-design

在包含大量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等)公开不同的属性,这些属性不属于域模型。我也愿意接受建议。

1 个答案:

答案 0 :(得分:4)

我认为这里的问题是您尝试使用单个DTO在所有API中表示User实体。相反,如果每个操作都有一个单独的DTO,只包含所需的数据,那么代码就会简单得多。

例如,TerminateAccount API会有一个只有终止原因的DTO,而您的代码只是:

user.terminateAccount(dto.terminationReason);