Доменные объекты, имеющие доступ к репозиториям - PullRequest
2 голосов
/ 04 июля 2011

Продолжая обсуждение:

DDD - правило, согласно которому сущности не могут получить прямой доступ к хранилищам

Допускается ли для сущностей доступ к репозиториям?

Есть еще ситуации, когда домену удобнее обращаться к хранилищу. Возьмите этот пример, который предполагает, что мне нужна таблица TaskStatus в базе данных, которая содержит описание для целей отчетности:

public class TaskStatus
{
    public long Id {get;set;}
    public string Description {get;set;}
}

public class Task
{
    public long Id {get;set;}
    public string Description {get;set;}
    public TaskStatus Status {get;set;}

    public void CompleteTask()
    {
        ITaskStatusReposity repository = ObjectFactory.GetInstace<ITaskStatusReposity>(); //Or whatever DI you do.
        Status = repository.LoadById(Constants.CompletedTaskStatusId);
    }
}

Я знаю, что у меня могут быть объекты CompletedTaskStatus и OpenTaskStatus, но в некоторых ситуациях это может быть ненужным и может привести к взрыву класса.

И вообще, почему интерфейсы репозитория хранятся в Домене, если не для такого рода вещей?

1 Ответ

4 голосов
/ 04 июля 2011

Допустимо ли для сущностей доступ к репозиториям?

Нет.Пожалуйста, не делайте этого.

Во-первых, идея доменной модели состоит в том, чтобы отделить бизнес-логику от приложения.Изолировать его от вашей базы данных, хранилищ и вашего приложения.Это позволяет вам отделить бизнес-логику от других и позволить ее тестировать и изменять отдельно от вашего приложения.

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

ddd-the-repository-pattern.aspx

Во-вторых, существуют и другие практические причины не внедрять ваши репозитории в ваши нужды.

  1. Ваши объекты должны быть модульно-тестируемыми, введя свои репозитории в вашу сущность, вы создали зависимость от своего репозитория.

  2. Использование метода GetInstance () нарушает закон Деметры, высоздаем тесную связь ITaskStatusRepository с вашей сущностью.Это означает, что при создании новой задачи и написании модульных тестов не очевидно, что для создания задачи требуется ITaskStatusRepository.Это затрудняет модульное тестирование вашей бизнес-логики.

  3. С точки зрения DDD, хранилище связано не только с взаимодействием с БД, оно может быть извлечено из хранилища в памяти,Или Список.

  4. В вашем хранилище не должно быть отношения 1: 1 с таблицами.Если вам нужен ваш репозиторий задач для выполнения внутренних объединений с другими таблицами для выполнения сложных запросов, и он возвращает список элементов задач, то вы предоставляете метод из своего репозитория, который выполняет этот запрос.(Я думаю, что это распространенное заблуждение о шаблоне хранилища).

  5. Ваши лица не должны беспокоиться о выполнении действий с БД.

См. Изображение, размещенное здесь:

DDD: как слои должны быть организованы?

public class TaskStatus
{
   public long Id { get; set; }
   public string Description { get; set; }

   public TaskStatus() {
      Description = "Incomplete";
   }
}

public class Task
{
    public long Id {get;set;}
    public string Description {get;set;}
    public TaskStatus Status {get;set;}

    public void CompleteTask()
    {        
        Status.Description = "Complete";
    }
}

Внутри прикладного уровня ваш репозиторий отвечает за постоянство (или нет).Репозиторий представляет собой Список <> совокупных корней.И это работает на уровне совокупного корня.

Пример использования ваших задач внутри TaskService.Сервис действует на сущности из вашего уровня приложений.

public class TaskService 
{
    private readonly ITaskRepository _taskRepository;

    public TaskService(ItaskRepository taskRepository){
      _taskRepository = taskRepository;
    }

    public List<Task> CompleteAllTasks()
    {
      List<Tasks> getTasks = _taskRepository.GetTasks();
      getTasks.ForEach(CompleteTask);
      return _taskRepository.Save(getTasks);
    }    
}
...