如何在DDD中管理某些域“静态数据”

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何在DDD中管理某些域“静态数据”相关的知识,希望对你有一定的参考价值。

一段时间以来,我了解了DDD并发现这种方法非常有趣。

上下文

我为Dungeon&Dragon角色表创建者和管理者启动了一个项目,并对域“静态数据”的实现提出了一些疑问。

我知道DDD与数据无关,但是我无法为我的问题找到另一个词。

实施

我简化了以下代码,将重点放在我的询问上。例如,我没有写空检查。

字符

我的角色是一个总的根,我们可以从这个班级中选择他的课程和2个技能

public class Character : IAggregateRoot

    public Guid Id  get; 
    public string Name  get; private set; 
    public Class Class  get; private set; 

    ...

    // class is a keyword, so I use @class
    public void ChooseClass(Class @class)
    
        Class = CharacterClass.Create(@class);
    

    public void ChooseClassSkill(Skill skill)
    
        Class.ChooseSkill(skill);
    

    ...

班级

Class是另一个聚合根。在《地牢与龙》中,类的数量是有限的,它们的行为是不同的。我想在领域中实现它们以代表这些行为。有些班级可以使用咒语,有些班级可以穿重型盔甲,...

public abstract class Class : IAggregateRoot

    public string Id => GetType().Name;
    public abstract ICollection<Skill> AvailableSkills  get; 

战斗机

战斗机类别是已实施的类别之一。我认为单身是个好主意,因为所有战斗机角色都可以使用相同的东西。一个字符的特异性在CharacterClass中。在阅读了一些说单例是反模式的文章之后,我对此不太确定。

public class Fighter : Class

    public override ICollection<Skill> AvailableSkills => new List<Skill>()
    
        Skill.Acrobatics,
        Skill.Athletics,
        Skill.Perception
    ;

    private static Fighter instance = null;

    internal static Fighter Instance
    
        get
        
            if (instance == null)
                instance = new Fighter();

            return instance;
        
    

角色类

字符类是一个实体,引用类的聚合根。我读了一些有关DDD的文章,他说对另一个聚合根的引用应该与他的ID有关。

public class CharacterClass : Entity

    public Guid Id  get; 
    public Class Class  get; 
    public ICollection<Skill> Skills  get; 

    public CharacterClass(Class @class)
    
        Id = Guid.NewGuid();
        Class = @class;
        Skills = new List<Skill>();
    

    public static CharacterClass Create(Class @class)
    
        return new CharacterClass(@class);
    

    public void ChooseSkill(Skill skill)
    
        // These business rules can be check with this class properties
        if (Skills.Contains(skill))
            throw new Exception();
        if (Skills.Count > 1)
            throw new Exception();
        // This business rule need to check another Aggregate root
        if (!Class.AvailableSkills.Contains(skill);
            throw new Exception();

        Skills.Add(skill);
    

审讯

  • 单身人士可以满足我的需求是个好主意吗?
  • 我的CharacterClass应该仅通过id还是引用来引用该类?
  • 如果我通过id引用,如何在ChooseSkill函数中检查该技能是否适用于该班级?

先谢谢您。

编辑

我计划在blazor应用程序上重用域程序集。这就是为什么我要为类实现某些域“数据”和特定行为。我的业务逻辑将被写入一次。

答案

[确定,我可以使用服务的一种方式。

我将重命名一些内容,并忽略某些继承-并采用其他方法。

  1. 将“班级”重命名为SkillsClass
  2. 添加可用的技能工厂
  3. 观察:技能只是一个枚举
  4. 我将使用另一个枚举-CharacterType 1 = Fighter
// This is dummy code without input, such as a test - but could be in a Service etc.
SkillsClass availableSkills = AvailableSkillsFactory.Get(CharacterType.Fighter);

Character character = new Character(CharacterType.Fighter);
character.ChooseSkill(Skill.Perception, availableSkills);

在角色类中,我将选择技能更改为此...

public void ChooseSkill(Skill skill, SkillsClass availableSkills)

    ...

    // This business rule need to check another Aggregate root
    bool isSkillAvailable = availableSkills.IsAvailable(skill);

    if (!isSkillAvailable) 
        // action
    

    Skills.Add(skill);


然后是SkillsClass ...


public class SkillsClass 

  public IEnumerable<Skill> AvailableSkills  get; private set; 

  public SkillsClass (IEnumerable<Skill> skills) 
     this.AvailableSkills = skills;
  

  public bool IsAvailable (Skill skill) 
    var doesExist = this.AvailableSkills.Contains(skill);

    return doesExist;
  



还有工厂...

public static class AvailableSkillsFactory 

   public static Get(CharacterType characterType) 

      if (characterType == CharacterType.Fighter) 
         var availableSkills = new Fighter().AvailableSkills;
         return new SkillsClass(availableSkills);
      

   



为了确定它的简单性,我反复来了几个名字,并决定不进行过多的重构。

有多种方法可以做到这一点。

以上是关于如何在DDD中管理某些域“静态数据”的主要内容,如果未能解决你的问题,请参考以下文章

如何在 DDD 中使用 EF DbContext 分离我的聚合

干净的领域驱动设计(DDD)是乌托邦吗? [关闭]

如何将我的 DDD 模型中的“用户”与身份验证用户集成?

DDD和“洋葱架构”之间有什么关系?

DDD设计中的Unitwork与DomainEvent如何相容?

DDD学习笔录——简介DDD的战术模式问题空间和解空间