域驱动设计,如何实现这类规则

问题描述

我尝试练习 DDD,但我对我在下面写的这种类型的规则有疑问:

在域层下类 UserAggregator。

public class UserAggregator{
private UUID userId;
private String userName;
private String country;
//getter

boolean isUserNamePatternCorrect(){
  return this.userName.startsWith("TOTO"); 
}
}

领域层下的仓库接口。

public interface UserRepository {//User Table
     public UserAggregator findUser(UUID id);
     public void deleteUser(UserAggregator userToARchive);
}

public interface ArchiveUserRepository { //ArchiveUser Table
     public archiveUser(UUID id);
}

UserRepository/ArchiveUserRepository 使用 spring 数据在基础设施层下实现。

基础设施层下的服务。

public  class MyService {

@Autowired
UserRepository userRepo;

@Autowired
ArchiveUserRepository archiveUserRepo;

public void updateUserName(UUID userId){

       UserAggregator userAgg = userRepo.findUser(userId);
       if(Objects.nonNull(userAgg)){
         boolean isCorrect = userAgg.isUserNamePatternCorrect();
        if(!isCorrect){//-----------------------------1
            userRepo.deleteUser(userAgg);//-----------2
            archiveUserRepo.archiveUser(userAgg);//---3
           }
       }
//....
}
}

我的管理规则说,如果 userName 与模式不匹配,则将用户存档到存档表中并将其从用户表中删除

如您所见,规则(从 //1 到 //3)写入服务类中,而不是写入我的聚合器中!

这是正确的吗?或者如何管理?

解决方法

首先,它不是“Aggregator”,它是“Aggregate”,其次实际上并没有加上“Aggregate”后缀,它没有带来任何价值并且违背了业务驱动的语言(Ubiquitous Language)。

我的管理规则说,如果 userName 与模式不匹配,则将用户存档到存档表中并将其从用户表中删除

好吧,我认为问题在于这根本不是业务规则,而是技术规范。为什么业务专家会关心数据库表? DDD 有助于以与基础架构无关的方式对规则进行建模和描述,因此对技术规范的建模帮助不大。

有几种方法可以在消除基础设施污染的同时保留技术规范,例如存储库可以根据 archived 状态做出存储决策。

class User {
   boolean archived;

   void changeUserName(String userName) {
       this.userName = userName;

       if (!isUserNamePatternCorrect()) {
           this.archived = true;
       }
   }
}

class UserRepository {
    save(User user) {
        if (user.archived) ...
    }
}

如果您需要在技术上更加明确,那么您或许可以捕获域服务中的逻辑,并使用与您现有的类似的方法,或者甚至可以调度 UsernameChanged 之类的域事件并让其处理UserArchivingPolicy

,

这似乎是关于在用户名不正确的特定情况下如何表现的基础设施规则,我认为您的代码没有任何问题。 恕我直言,责任属于存储库,所以我认为这种方法非常正确。