2010-04-03 3 views
10

Просто создал согл на SO, чтобы спросить это :)В подходе DDD, этот пример правильно смоделирован?

Предполагая, что это упрощенный пример: создание веб-приложение для управления проектами ...
Приложение имеет следующие требования/правила.

1) Пользователи должны иметь возможность создавать проекты, вставляя название проекта.
2) Названия проектов не могут быть пустыми.
3) Два проекта не могут иметь одно и то же имя.

Я использую 4-слойную архитектуру (Пользовательский интерфейс, Приложение, Домен, Инфраструктура).
На моем прикладном уровне у меня есть следующий класс ProjectService.cs:

public class ProjectService 
{ 
    private IProjectRepository ProjectRepo { get; set; } 

    public ProjectService(IProjectRepository projectRepo) 
    { 
     ProjectRepo = projectRepo; 
    } 

    public void CreateNewProject(string name) 
    { 
     IList<Project> projects = ProjectRepo.GetProjectsByName(name); 
     if (projects.Count > 0) throw new Exception("Project name already exists."); 

     Project project = new Project(name); 
     ProjectRepo.InsertProject(project); 
    } 
} 

На моем домене уровне, у меня есть класс Project.cs и интерфейс IProjectRepository.cs:

public class Project 
{ 
    public int ProjectID { get; private set; } 
    public string Name { get; private set; } 

    public Project(string name) 
    { 
     ValidateName(name); 
     Name = name; 
    } 

    private void ValidateName(string name) 
    { 
     if (name == null || name.Equals(string.Empty)) 
     { 
      throw new Exception("Project name cannot be empty or null."); 
     } 
    } 
} 




public interface IProjectRepository 
{ 
    void InsertProject(Project project); 
    IList<Project> GetProjectsByName(string projectName); 
} 

На мой Уровень инфраструктуры, у меня есть реализация IProjectRepository, которая выполняет фактический запрос (код не имеет значения).


Я не люблю две вещи об этой конструкции:

1) Я прочитал, что интерфейсы хранилища должны быть частью домена, но реализации не должны. Это не имеет для меня никакого смысла, поскольку я считаю, что домен не должен вызывать методы репозитория (незнание персистентности), что должно отвечать требованиям служб на уровне приложения. (Что-то говорит мне, что я ужасно ошибаюсь.)

2) Процесс создания нового проекта включает в себя две проверки (не нулевые, а не повторяющиеся). В моем проекте выше эти две проверки разбросаны в двух разных местах, что усложняет (imho), чтобы увидеть, что происходит.

Итак, мой вопрос: с точки зрения DDD, это правильно смоделировано или вы сделаете это по-другому?

ответ

1

Я думаю, что часть путаницы с (1) заключается в том, что вам не хватает слоя - вставьте сервисный уровень в свою архитектуру, и ваша проблема исчезнет, ​​как магия. Вы можете поместить службу и реализацию репозитория в уровень сервиса - то есть у вас есть служба, которая использует конкретную реализацию репозитория. Другие службы могут свободно выбирать альтернативную реализацию репозитория, если они этого захотят. Ваше приложение может свободно выбирать любой сервис-интерфейс, который ему нравится. Сказав это, я не уверен, что это действительно важно в большинстве случаев. Почти во всех моих приложениях у меня есть один «домен/datalayer», который в основном исправлен. Я могу наложить на него репозиторий или нет, в зависимости от сложности бизнес-логики. То же самое с сервисом - это может просто не понадобиться, если проект не очень сложный. Если это станет так позже, я всегда смогу рефакторировать. Обычно я помещал свой репозиторий в тот же проект, что и мой контекст данных (используя LINQ), и, если бы он был сервисом, он был бы в отдельном проекте (потому что обычно он будет отображаться как веб-сервис).

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

+0

Что касается (1), я думаю, что мой уровень приложения может служить цели уровня сервиса, если бы у меня был другой слой, я думаю, что мог бы закончиться слоями, не имеющими смысла или ответственности, которые будут распределены между слоями. Когда вы говорите о сложности дизайна, я полностью согласен с вами. Я использую подход «Active Records Pattern» для большинства моих приложений, и этот шаблон может показаться более подходящим для решения этого примера. Я преднамеренно оставил этот пример упрощенным, но я пытаюсь научиться правильно моделировать шаблон шаблона репозитория, поэтому я отклоняюсь от шаблона AR. – Tag

+0

Что касается (2), ваше предложение имеет для меня прекрасный смысл, и я думаю, что это действительно лучший вариант в этом случае. – Tag

2

Процесс создания нового проекта включает в себя две проверки (не нулевые, а не повторяющиеся). В моем проекте выше эти две проверки разбросаны в двух разных местах, что усложняет (imho), чтобы увидеть, что происходит.

Проект не может и не должен быть в курсе всех проектов в приложении (сам элемент не должен быть в курсе всех других элементов в списке), поэтому. - это ответственность обслуживания домена (instead of application service проверить Эванс книгу, чтобы понять точную разницу).

Существует много видов проверки. И there can't be universal validation mechanism. DDD просто говорит, что вы должны поместить проверку домена в модель домена.

Смежные вопросы