Domain driven design DDD-构造函数中的问题和实体设计中的方法
我有一个关于实体设计的问题。正如我所读到的,在设计DDD实体时,构造函数应该包含实体“存在”所需的值。例如,在我正在处理的域中,类实体在没有节和级别的情况下无法存在:Domain driven design DDD-构造函数中的问题和实体设计中的方法,domain-driven-design,Domain Driven Design,我有一个关于实体设计的问题。正如我所读到的,在设计DDD实体时,构造函数应该包含实体“存在”所需的值。例如,在我正在处理的域中,类实体在没有节和级别的情况下无法存在: public class Class { public Class(short id, string section, Level level) { ID = id; Section = section; Level = level; } //
public class Class
{
public Class(short id, string section, Level level)
{
ID = id;
Section = section;
Level = level;
}
//
// Properties
//
public short ID { get; private set; }
public string Section { get; private set; }
public Level Level { get; private set; }
//
// Methods
//
public static IList<Class> GetClassesByTeacher(short teacherID)
{
List<Class> classes = new List<Class>();
classes.Add(new Class(1, "a", null));
classes.Add(new Class(2, "b", null));
classes.Add(new Class(3, "c", null));
return classes;
}
}
公共类
{
公共类(短id、字符串段、级别)
{
ID=ID;
截面=截面;
级别=级别;
}
//
//性质
//
公共短ID{get;private set;}
公共字符串部分{get;private set;}
公共级别{get;private set;}
//
//方法
//
公共静态IList GetClassesByTeacher(短teacherID)
{
列表类=新列表();
添加(新类(1,“a”,null));
添加(新类(2,“b”,null));
添加(新类(3,“c”,null));
返回类;
}
}
在这里,级别也是一个实体。由于我还没有完成设计,Level的构造函数可能还包含一个实体学年。困扰我的是调用GetClassesByTeacher方法,我需要实例化一个类和其他实体(Level,以及Level构造函数中需要的学年)
这是正确的吗?当我只想调用这个方法时,我觉得很麻烦。还有其他方法吗?我曾考虑将其设为静态,但其他人说可测试性将受到影响。我不确定CQRS是否是我想做的事情的解决方案之一,因为我还没有读到太多关于它的内容,但如果是,除了CQRS之外,还有什么其他技术我可以使用,或者是在使用DDD时,这就是它的实际情况吗?还是我的实体设计不正确?您应该重新考虑您的域模型,因为您实际上说它似乎有问题 我可以提到单一责任原则(SRP),其中任何类别都应该有一个改变的理由。在您的示例中,如果我们在“类”中添加了一个新字段,我们将自己修改“类”,这是正确的,但是如果我们决定列表应按反转顺序排列,或者如果您需要一个只考虑临时教师的新列表类型,会发生什么情况。。。您应该更改“类”,但“类”与列表无关 要回答您的问题,您可以看看。存储库是您可以要求提供这些类型列表的地方 我可以把班级分成两部分:
- 一个是“类”模型
- “类”存储库的其他
public class Class
{
public Class(short id, string section, Level level)
{
ID = id;
Section = section;
Level = level;
}
//
// Properties
//
public short ID { get; private set; }
public string Section { get; private set; }
public Level Level { get; private set; }
}
public class ClassRepository
{
private IList<Class> contents;
//
// Methods
//
public IList<Class> GetClassesByTeacher(short teacherID)
{
List<Class> classes = new List<Class>();
for (Class elem: contents) {
if (elem.getTeacher().equals(teacherID) {
classes.Add(elem);
}
}
return classes;
}
}
repository = new ClassRepository;
level1 = new Level();
repository.Save(new Class(1, "a", level1));
repository.Save(new Class(2, "b", level1));
repository.Save(new Class(3, "c", level1));
result = repository.GetClassesByTeacher(1);
公共类
{
公共类(短id、字符串段、级别)
{
ID=ID;
截面=截面;
级别=级别;
}
//
//性质
//
公共短ID{get;private set;}
公共字符串部分{get;private set;}
公共级别{get;private set;}
}
公共类类存储库
{
私有IList内容;
//
//方法
//
公共IList GetClassesByTeacher(简称teacherID)
{
列表类=新列表();
用于(类元素:目录){
if(elem.getTeacher().equals)(teacherID){
类。添加(元素);
}
}
返回类;
}
}
repository=newclassrepository;
级别1=新级别();
Save(新类(1,“a”,level1));
Save(新类(2,“b”,级别1));
Save(新类(3,“c”,级别1));
结果=repository.GetClassesByTeacher(1);
还有其他一些细节,比如使用ClassRepositoryInterface并使用InMemoryClassRepository实现,你也会错过课堂上的教师信息,只要一位教师驾驶课堂,如果没有,你可能会改变如何按教师过滤,等等
我不是Java开发人员,代码不会编译,但我希望您能理解。GetClassesByTeacher方法确实属于某种存储库或服务类。您的
类
实体是用来表示现实世界中该事物的实例。实体不是用来提供实例的(比如说,从一些底层持久性)-它们只是用来表示它们。ClassRepository
是一种将Class
实体的实例提供到您的域中的方法
您还提到,类
如果没有级别
,就不可能存在。您在这里谈论的是聚合。在线上有很多关于设计聚合的DDD材料。以下是一些:
- 为什么要提高性能?您可能正在为某个聚合根在内存中加载一个巨大的数据图。对于正在发生的任何工作单元,您很可能只需要处理该聚合的一小部分,而不是所有涉及的实体
- 什么是一致性问题?聚合越大,在将数据检索到内存时,系统另一部分中的数据越有可能被更改。保存时,可能会发生数据丢失