Обработка совокупного корня - PullRequest
0 голосов
/ 21 мая 2018

Я новичок в DDD, поэтому я немного потренировался.У меня есть курс BC со следующими правилами:

  1. Сначала необходимо создать курс, а затем они могут создавать модули одного курса
  2. Каждый модуль будет закончен пользователем, когда онзагрузить домашнее задание
  3. Курс будет закончен пользователем, когда он закончит все модули

Определение: курс охватывает определенную тему и состоит из модуля.Например, в курсе sap есть 10 модулей, таких как: модуль 1: что это такое, модуль 2: как его использовать?…

После этого я понимаю, что курс является совокупным корнем модуля, посколькумодули закончены, я должен закрыть статус пользователя с курсом.

модель будет выглядеть так:

public class Course : AggregateRoot
{
    private string title;
    private List<Module> modules;
}

, но также модуль является совокупным корнем домашней работы, потому что когда пользователь загружает свою домашнюю работу, модуль должен быть закрыт.Это заставляет меня думать, что этот подход неправильный, потому что невозможно в DDD иметь вложенный агрегатный корень.Кто-то знает, что это не так?

[ОБНОВЛЕНО]

Хорошо, теперь я понимаю, как работает и почему вы разделили ее на 2 BC.Однако я сделал некоторые изменения, и некоторые вопросы приходят мне на ум.

-Я создал метод enroll как статический, и я поместил конструктор как private.

-Course должен быть массивом, потому чтоу одного ученика может быть больше одного.

- Я добавил больше параметров, связанных с курсом, а также с учителем.Конечно, учитель и сущность, верно?

-Я создал статус курса, чтобы обновлять его, когда модуль закончен таким образом, мне не нужно читать все модули, чтобы узнать его.все в порядке?

-Как я могу передать больше информации для каждого модуля, как заголовок и описание?и сущность курса, как создать все модули, верно?

public class StudentEnrolment: AggregateRoot
{
    private StudentId studentId;
    private Course courses;

    private constructor(
        StudentId studentId, 
        Course course, 
       ){
        this.studentId= studentId;
        this.courses[] = course;
    }

    public statuc function enroll(
        StudentId studentId,
        CourseId courseId, 
        string courseTitle,
        string courseLink,
        string teacherId,
        string teacherName,
        List<Tuple<ModuleId, string>> modules) {
        teacher = new Teacher(...);
        courseStatus = new courseStatus();
        new course(courseTitle, courseLink, courseStatus, teacher);
        return new self(studentId, course);
    }

    public function void uploadModuleHomework(ModuleId moduleId, Homework homework){ 
        /* forward to course.uploadModuleHomework */ 
    }

    public boolean isCourseFinished(){ 
         /* forward to course.isFinished */ 
    }

    public List<Tuple<ModuleId, string>> getModules(){ 
         /* forward to course.getModules */ 
    }
}

1 Ответ

0 голосов
/ 22 мая 2018

Существует два разных поддомена (поэтому у нас есть два ограниченных контекста):

1. Администрирование курсов и модулей, где учителя могут управлять ими;Здесь Course и Module могут быть агрегированными корнями, а course может содержать ссылки на Modules идентификаторы (не на экземпляры!).

public class Course: AggregateRoot
{
    private string title;
    private List<ModuleId> modules;
}

2. Студенческое участие в курсах.Здесь есть StudentEnrolment Совокупный корень, который содержит ссылки на Course и Module из другого BC, но как объекты Value;он моделирует участие студентов в одном курсе;в этом ограниченном контексте есть новая сущность, домашняя работа, которая отслеживает загрузку домашней работы ученика и статус участия в курсе.

public class StudentEnrolment: AggregateRoot
{
    private StudentId studentId;
    private Course course;
    private List<Homework> homeworks;

    // initialize a student enrolment as public constructor or make constructor private and use a static method
    // here is important to notice that only this AR creates its entities, it does not receive them as parameter
    public constructor(
        StudentId studentId, 
        Course course, 
        List<Module> modules){
        this.studentId = studentId;
        this.course = course;
        //build the the homeworks entity list based on the modules parameter
        //for each module create a Homework entity, that initially is not uploaded, like:
        this.homeworks  = modules.map(module => new Homework(module))
     }

    public function void uploadFileForHomework(ModuleId moduleId, string file){ 
        /* find the homework by module Id and upload file*/ 
    }

    public boolean isCourseFinished(){ 
         /*returns true if all homeworks are uploaded*/
         /*optimization: you could have a status that is updated when a homework's file is uploaded*/
    }

    public List<Tuple<ModuleId, string, boolean>> getHomeworks(){ 
         /* returns a list of readonly Homeworks, i.e. Tuple<ModuleId, string /*module title*/, boolean /*is uploaded*/> */
    }
}


public class Homework: Entity
{
    private Module module;
    private string file;
    public constructor(Module module){
        this.module = module;
    }

    public void upload(string file){ this.file = file;}

    public boolean isUploaded(){return (boolean)this.file;}

    public string getUploadedFile(){return this.file;}

    public ModuleId getModuleId(){return this.module.getId();}
}

public class Course: ValueObject
{
    private string title;
    private CourseId id;
    public constructor(id, title){...}
    public string getTitle(){return this.title;}
    public string getId(){return this.title;}
}

public class Module: ValueObject
{
    private string title;
    private string description;
    private ModuleId id;
    public constructor(id, title, description){...}
    public string getTitle(){return this.title;}
    public string getDescription(){return this.description;}
    public string getId(){return this.title;}
}

Если вам нужно подать заявку на получение домашних заданий, вам не следует возвращать списокHomeworks, потому что клиентский код будет думать, что он может напрямую вызывать Homework.upload(file), что недопустимо (только объединенный корень может изменять свои внутренние сущности).Вместо этого вы можете вернуть Tuple или лучше, вы можете создать неизменяемую версию класса Homework.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...