DDD在何处放置业务规则,例如“一个成员只能有两个存储段列表”

时间:2018-10-15 15:22:57

标签: architecture domain-driven-design

嗨,我目前正在玩DDD(PHP)项目,并且遇到了以下问题。

假设有一条业务规则规定:成员只能有两个存储段列表。成员对象已在系统中广泛使用。

我的问题是该业务规则放在何处?

选项以及我的想法和关注点:

将其放入应用程序服务中:

由于这是一条业务规则,我认为它应该在域层而不是应用程序层。除非该规则绝对是特定于应用程序的,否则即使如此,我仍然认为它应该在由应用程序服务调用的域服务中使用。

将其放置在Factory中:(域层作为简单工厂或抽象类)

我可以使用规范模式通过查询数据库的实现来检查我的规则,以查看该用户是否已有存储桶列表。工厂的工作是创建对象,因此感觉就像检查规则一样。尽管其他团队成员愿意的话可以绕开工厂,并且不会强制执行此规则。

将其放入域服务中

该服务将检查规则,然后致电工厂以构建对象。但是再次可以绕过该服务。

将其放在存储库中:(域层作为抽象类)

我可以使用与此处工厂建议的方法相同的方法,但是存储库的工作是使其看起来像一个内存中的集合。在这里检查规则感觉很不对劲,尽管这样可以确保在向集合中添加某些内容时强制执行该规则。

将其放置在实体中:

检查应在对象构造函数或其中调用的setMemberId方法中进行。这样可以确保甚至都无法构造无效对象,这对我来说似乎是最好的情况,但是该实体将依赖于BucketListMustBeUniqueForMemberSpecification,这对我来说是错误的。

将其放在值对象中:

MemberId由系统的许多其他部分使用,因此我不会将其放置在此处,但是我可以制作一个OwnerId值对象并将规则放置在其中,并将memberId-> id()用作构造函数输入。该规则将被强制执行,但同样会与BucketListMustBeUniqueForMemberSpecification产生依赖关系,该依赖关系将注入到构造函数中:/

class SQLBucketListMustBeUniqueForMemberSpecification implements ...
{

    public function isSatisfiedBy($memberId)
    {
        // sql to try to find a bucket list of the members id

        return $bucketList ? false : true
    }
}

1 个答案:

答案 0 :(得分:0)

  

“一个成员只能有两个存储桶列表”

为什么不将规则放在Member本身内?除非您期望大量的关联,否则这是保护不变量的简单解决方案。

class Member {
    ...
    final Set<BucketListId> bucketListIds;

    public Member(...) {
       bucketListIds = new HashSet<BucketListId>();
    }

    associateBucketLists(Set<BucketListId> bucketListIds) {
        if (bucketListIds.size() > 2) throw ...;
        bucketListIds.clear();
        bucketListIds.addAll(bucketListIds);
    }
}

您也可以这样做,以便从BucketList个文件中创建Member

class Member {
    int bucketListCount = 0;

    public BucketList newBucketList(final BucketListId id, final BucketListDetails details) {
        if (bucketListCount == 2) throw ...;

        bucketListCount++;

        return new BucketList(id, this.id, details);
    }
}

class BucketList {
    final BucketListId id;
    final MemberId ownerId;
}

class MemberApplicationService {
    public void newBucketListFor(memberId, ...) {
        Member member = memberRepository.memberOfId(memberId);
        BucketList bucketList = member.newBucketList(...);
        bucketListRepository.add(bucketList);
    }
}
相关问题