【问题标题】:DDD and CRUD-type appsDDD 和 CRUD 类型的应用程序
【发布时间】:2012-07-23 03:30:17
【问题描述】:

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

【问题讨论】:

    标签: java domain-driven-design


    【解决方案1】:

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

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

    user.terminateAccount(dto.terminationReason);
    

    【讨论】:

    • @TTar 好吧,您不只是将复杂性转移到另一层吗?客户端现在必须根据用户选择知道必须在terminateAccountactivateAccount 之间调用哪个应用程序服务。是否更愿意将复杂性转移到那里而不是将其封装在应用程序服务中?
    猜你喜欢
    • 1970-01-01
    • 2012-05-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多