>在系统内,需要有一种方法可以为有兴趣在该学校接受教学的新学生输入学生数据,我们可以假设学生可以通过网站访问此功能.
>部分注册过程询问学生她希望接受教学的乐器类型.
>由于输入了有关其首选乐器的信息,行为将是指派一名默认讲师分配给该组乐器.
>在完成注册申请之前,学生还可以将指定的教师更改为不同的教师,该教师也被列为能够为其所选的教学提供指导.
鉴于这种描述,我遇到一点麻烦的部分是如何管理可能的教师列表,这些教师可以在为新学生首先选择默认讲师方面为特定乐器提供指导,其次如何在提交注册之前验证选定的讲师时使用相同的数据.
其他技术限制是到目前为止我一直在使用一种自我验证技术,非常类似于Jimmy Nilsson的书Applying Domain-Driven Design and Patterns中提到的那种技术,所以对我来说,最好的方法是继续遵循自我验证技术.外部数据是必要的,我通常会将其视为被测试实体范围之外的有效性.
我知道的选项:
>将验证移到实体本身之外.也许验证被转移到一组服务或每个实体的单个服务,它分析整个实体的当前状态并认为它是否有效,并提供要发布的域事件或其他值对象,以便更好地了解验证规则具有哪些被打破了.在这种情况下,我仍然对服务如何获取有关教师的必要信息感到有些不安
>允许从试图执行此验证的必要实体访问讲师存储库.
>创建一个允许按工具类别访问教师列表的服务.或者创建两个单独的服务,一个返回给定教师是否在给定类别的教师列表中,另一个返回给定类别的默认教师.
>在我的聚合根目录(可能是学生或学生注册请求)中加载一个教师值对象列表,这些对象可以由根目录中包含的聚合根或实体进行验证.
在上面的前两种情况中的任何一种情况下,似乎使用教师存储库都是过度的,因为我不需要访问代表教师的聚合根,但在我的情况下,我会将教师视为一个值对象,描述学生注册请求并且有一个存储库吐出值对象似乎模糊了存储库应该做的行.对于最后两个选项,似乎错误两个允许在选项4的情况下从服务或工厂访问数据,因为不是应该负责数据访问的存储库,例如这个?如果存储库是这个逻辑的正确位置,那么访问或存储对存储库的引用的适当位置在哪里?我一直坚信有理由不直接在组成模型的任何实体或值对象中访问存储库,所以我想知道这是否是我可能不得不屈服于这个假设的情况.我还应该提一下,我对DDD很陌生,而且我现在正遇到一些令人头疼的问题,并试图不把自己包装进去,所以对这个主题的任何知识渊博的输入都是有价值的.
Move validation outside of the entity itself.
一位教师不应该了解所有其他教师.对一组教师的验证不是一个特定教师的责任.
Allow for access to a instructor repository from necessary entities that are attempting to perform this validation.
域模型应该是持久性无知的.需要打破,表明你的模型中存在缺陷.
Create a service that allows access to a list of instructors by instrument category.
这一点信息显示缺少聚合根 – 我称之为InstrumentClass.
将其引入您的模型可以解决您的一些问题. InstrumentClass将聘请教授特定乐器的教师.
接下来你需要弄清楚的是如何恰当地描述分配给班级的学生.不幸的是,我现在无法命名(也许是参与?).但该实体将用于InstrumentClass以确定哪些教师太忙.
在我的域建模中,这是我的“自由风格”(只是为了展示我所看到的):
using System; public class Main{ public Main(){ var instructor = new Instructor(); var instrument = new Instrument("saxaphone"); var saxaphoneClass = new InstrumentClass(saxaphone,teacher); var me=new Person("Arnis"); //here,from UI,I can see available classes,choose one //and choose according instructor who's assigned to it var request=me.RequestEnrollment(saxaphoneClass,instructor); saxaphoneClass.EnrollStudent(request); } } public class Person{ public IList<EnrollmentRequest> EnrollmentRequests { get; private set; } public EnrollmentRequest RequestEnrollment (InstrumentClass instrumentClass,Instructor instructor){ if (!instrumentClass.IsTeachedByInstructor(instructor)) throw new Exception("Instructor does not teach this music instrument"); var request=new EnrollmentRequest(this,instrumentClass,instructor); EnrollmentRequests.Add(request); return request; } } public class EnrollmentRequest{ public Person Person{ get; private set; } public InstrumentClass InstrumentClass { get; private set; } public Instructor Instructor{ get; private set; } } public class InstrumentClass{ public void EnrollStudent(EnrollmentRequest request){ var instructor=request.Instructor; var student=new Student(request.Person); var studies=new Studies(this,student,instructor); //TODO: this directiveness isn't good //student/instructor should listen for class events themselves //and class should listen if by any reason instructor or student cannot //participate in studies student.EnrollInClass(studies); instructor.AssignStudent(studies); Studies.Add(studies); } public bool IsTeachedByInstructor(Instructor instructor){ return Instructors.Contains(instructor); } public InstrumentClass (Instrument instrument,params Instructor[] instructors){ Instrument=instrument; Instructors=instructors.ToList(); } public IList<Instructor> Instructors{get;private set;} public IList<Studies> Studies { get; private set; } public Instrument Instrument { get; private set; } } public class Studies{ public Student Student { get; private set; } public Instructor Instructor { get; private set; } public InstrumentClass InstrumentClass { get; private set; } } public class Student{ } public class Instructor{ } public class Instrument{ }