【问题标题】:DDD: is accessing repository from aggregate root considered bad practice?DDD:从聚合根访问存储库是否被认为是不好的做法?
【发布时间】:2017-02-15 04:57:15
【问题描述】:

我读过从聚合根访问存储库被认为是不好的做法。 如果是,请考虑以下示例:

class User {
   private String username;
   public void changeUsername(String newUsrname) {
     // How will I persist username to database if I don't have access to repository from aggregate root?
     ...
   }
}

如果我无权访问存储库,我将如何将用户名保存到数据库 从聚合根?

我是这样看的:

class User {
    private String username;
    private UserRepository userRepository;
    public User(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    public void changeUserName(String newUsername) {
       this.username = newUserName;
       userRepository.save(this); 
    }
}

或者我错过了 DDD 概念中的某些内容?

【问题讨论】:

  • 您的示例显示 ActiveRecord 而不是 DDD。
  • @dit,您将如何以 DDD 方式实现这一目标?
  • 检查这个 DDD 示例:github.com/citerus/dddsample-core
  • @dit,从您提供的示例中,我应该介绍 UserService,在该 userService 中我应该有 UserService.changeUserName(userId, username) 它将从存储库中获取用户,调用 user.changeUsername 并且服务将存储用户返回...所以与域的交互应该通过服务来完成?我的方法有什么问题?
  • Repository 有getByIdupdate(user)delete(user) 之类的方法,并且不执行任何逻辑,仅执行 CRUD 操作。逻辑将在 Service 中实现。

标签: java domain-driven-design ddd-repositories aggregateroot


【解决方案1】:

如果我无法从聚合根访问存储库,我将如何将用户名保存到数据库?

当前的做法通常在应用程序组件中处理 I/O,而不是在域模型中。

Application {
    void when(ChangeUserName command) {
        User user = this.userRepository.getUserById(command.userId);
        user.changeName(command.name);
        this.userRepository.save(user);
    }
}

推荐阅读:Vladimir Khorikov 论域模型隔离。

【讨论】:

    【解决方案2】:

    只是为了扩展@VoiceOfUnreason 给出的答案(这是完全正确的),这里快速解释一下为什么不建议通过构造函数将存储库注入聚合根:

    存储库应该依赖于它返回的对象,而不是相反。这样做的原因是您的“域对象”(稍后会详细介绍)可以存在(并且应该是可测试的)而无需加载或保存(即依赖于存储库)。

    基本上,您的设计表明,为了拥有一个用户,您需要提供一个 MySQL/Mongo/XXX 实例连接,这是一个基础架构细节。你的域不应该知道它是如何被持久化的。您的域了解行为、不变量、业务规则等。

    这些概念只是帮助您创建更易于维护的代码,并帮助您应用 SRP(单一职责原则)等最佳实践。

    【讨论】:

    • 在这种情况下,域现在不会涉及基础设施,因为我传递的只是存储库接口,而存储库接口是域的一部分。
    • 想想User类的单元测试。假设为了更改用户名,您有一些不变量,例如它不能为空,也不能超过一定长度等。确保不变量是您的用户 AR 的责任,但如果您还添加了持久化、获取等,你正在破坏 SRP,使得 AR 类和单元测试的维护变得更加困难。
    猜你喜欢
    • 2012-08-04
    • 2010-12-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-30
    • 1970-01-01
    相关资源
    最近更新 更多