Объекты данных, доменные объекты и репозитории в DDD

Я пытаюсь разобраться с DDD, но я застрял. Вот как я настраиваю свой проект:

Data Access Layer
 -Entity models that map to the db
 -Db connection stuff
 -Repositories implementations

Domain Layer
 -Models that represent the DAL entity models
 -Repositories interfaces

Application Layer
 -MVC application that uses Domain models

Первая проблема, которую я вижу здесь, состоит в том, что модели предметной области в точности совпадают с моделями сущностей, и у меня есть серьезная проблема с этим: модели сущностей, очевидно, имеют настроенную валидацию, такие вещи, как "максимальная длина", "обнуляемый", "требуется" и т. д. Теперь, чтобы соответствовать DDD, я не могу напрямую использовать эти модели нигде, кроме DAL, поэтому я создал свой уровень домена. На уровне домена все эти правила проверки дублируются для проверки пользовательского интерфейса, и что еще хуже, если мне нужно изменить правило, мне придется изменить его в двух местах: DAL и домен.

Пример:

User Entity in DAL
Name (required)
Last name (required)
Email (required, maxlen 120)
Username (required, maxlen 120)

User Domain Model
Name (required)
Last name (required)
Email (required, maxlen 120)
Username (required, maxlen 120)

Еще одна вещь, которую я нахожу очень странной, заключается в том, что организация репозиториев в этой архитектуре. Следуя тому, что я прочитал, я создал интерфейс GenericRepository и интерфейс UserRepository, который наследует GenericRepository, все на уровне домена. Я реализовал GenericRepository в DAL, и эта реализация создает DAO для типа объекта, используемого для создания хранилища. Все идет нормально.

Затем я приступил к реализации UserRepository, и здесь у меня возникла еще одна проблема: интерфейс UserRepository ожидает модель пользователя домена, а когда я пытаюсь реализовать интерфейс в DAL, мне нужно реализовать его с использованием модели пользователя домена, что вызывает DAO должен быть создан для модели предметной области, а не для модели DAL, и это не имеет никакого смысла. Единственное, что нужно исправить, это сослаться на DAL на уровне домена, что неверно.

Domain Layer:

public interface IGenericRepository<TEntity>
{
    TEntity FindById(TKey id);
}

public interface IUserRepository : IGenericRepository<Domain.User>
{
    Task<User> FindByUserNameAsync(string userName);
}


DAL:

public abstract class GenericRepository<TEntity> : IGenericRepository<TEntity>
{
    protected DbContext ctx;
    protected DbSet<Entity> dbSet;

    public GenericRepository(DbContext context)
    {
        ctx = context;
        dbSet = ctx.Set<TEntity>();
    }

    public virtual TEntity FindById(TKey id)
    {
        return dbSet.Find(id);
    }
}

 public class UserRepository : GenericRepository<Domain.Models.User>, IUserRepository
{
    public UserRepository(DbContext context)
        : base(context)
    {
       // THIS WILL CREATE A DAO FOR A DOMAIN MODEL
    }

    // rest of code...
}

Кто-нибудь может пролить свет на то, что мне не хватает в DDD?

2 ответа

Решение

Ваш вопрос и ваши сомнения в отношении DDD имеют смысл, потому что вы подходите к предмету с точки зрения кода.

Кажется, вы застряли в своем "дублировании кода", и вам не хватает общей картины.

Из определения Википедии:

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

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

Как думать о DDD: DDD - это философия разработки (определенная Эриком Эвансом), которая сосредоточена на командах разработчиков, пишущих программное обеспечение для сложных областей. Этим командам нужны четкие границы, потому что изменение, которое должно произойти в одной модели, не должно влиять на модель другой команды, прогресс и т. Д. (Следовательно, у вас есть дублирование кода).

Как не думать о DDD: это не каркас с предопределенным шаблоном применимого кода.

Общие проблемы для команд, начинающих DDD:

  • Подчеркивая важность тактических шаблонов: вместо решения вашей реальной бизнес-задачи сосредоточьтесь на совокупных корнях, ценностных объектах и ​​т. Д.
  • Сосредоточение внимания на коде, а не на принципах DDD: код должен быть последней итерацией процесса DDD. Настоящая работа - это понимание бизнес-проблемы и попытка найти простое для понимания решение (устранить сложность проблемы).

Дополнительные подводные камни, а также советы о том, как научиться применять DDD, вы можете найти в " Шаблонах, принципах и практиках доменного проектирования"(примеры ошибок взяты из главы 9 этой книги)

Кто-нибудь может пролить свет на то, что мне не хватает в DDD?

Вы ничего не пропускаете. DDD предназначен для случаев, когда вы не хотите, чтобы ваша модель Entity (Storage) была такой же, как ваша модель домена в памяти. IE, когда модель вашего домена имеет много сложного поведения и не используется в основном как модель данных для поиска справочных данных и записи транзакций.

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

Другие вопросы по тегам