DDD泄漏封装问题

本文关键字:问题 封装 泄漏 DDD | 更新日期: 2023-09-27 18:06:32

故事可由提名者授予(一)。因此,我的Nominator实体有以下方法:

public void GiveAward(StoryBase story)
{
    if (story.HasAward())        
        throw new InvalidOperationException("...");
    if (BusinessUnit.HasAwardsToGive() == false)
        throw new ...
    story.SetAward(new Award(AwardType.Results));
}

到目前为止,我对如何实现这个问题不太清楚。SetAward()是公开可见的,所以它可以从提名人之外的人调用,但是提名人必须知道这个故事是否已经获得了奖项。

任何想法都会很棒!

DDD泄漏封装问题

SetAward测试一个奖项是否被授予不是更有意义吗?记住:告诉,不要问。

我还有一个建议。

StoryNominator作为输入。

public class Story
{
    public void GiveAward(Nominator nominator)
    {
        if (this.Award != null)
            throw new ...
        var award = nominator.CreateAwardForStory(this); 
        this.SetAward(award); // SetAward can now be private
    }
}
public class Nominator
{
    public Award CreateAwardForStory(Story story)
    {
        if (BusinessUnit.HasAwardsToGive() == false)
            throw new ...
        return new Award(AwardType.Results);
    }
}

现在,如果我们假设CreateAwardForStory(…)函数保证返回一个新的Award实例(名称暗示它确实如此),Story还隐式地验证相同的Award实例没有给多个故事。

与其让故事获得奖项,不如让奖项指向故事?

public class Award
{
    public Award(Story awardedTo, Nominator awardedBy)
    { ... }
}

不了解你的领域(因此不知道什么是故事和奖项),我很难知道什么是有意义的,但这个模型将允许一个故事获得多个奖项。如果这个故事是一部电影,奖项可以是金球奖或奥斯卡奖等,那么这个模型也允许一个故事获得多个奖项。但既然你在原始代码中明确禁止了这一点,那么这可能在你的域名中无效。

你应该遵循"告诉不要问"的原则,如果这是StoryBase类中期望的行为,就设置奖励并抛出异常