0

Я пытаюсь реализовать запрос для получения некоторой проекции данных в MVC view из базы данных, управляемой моделью домена.Ошибка доменной логики в запросах в приложении MVC.NET с использованием DDD

Я прочитал, что контроллеры MVC возвращающихся статические взгляды должны запросить DTOs из обработчиков запросов или так называемых чтения модели хранилища, а не с помощью агрегатные корневые репозиториев возвращаются полноценные объекты домена. Таким образом, мы максимизируем производительность (оптимизируя запросы для необходимых данных) и уменьшаем риск злоупотребления доменной моделью (мы не можем случайно изменить модель с DTO).

Проблема заключается в том, что некоторые свойства DTO не могут непосредственно сопоставить DB поля таблицы и могут быть заполнены на основе некоторых бизнеса-правил или быть результатом некоторого условия, не неявно указанными в БДЕ. Это означает, что запрос действует на некоторая логика, протекающая из домена. Я слышал, что это неправильно, и эти запросы должны напрямую фильтровать, упорядочивать, проектировать и агрегировать данные из таблиц БД (с использованием запросов linq и EF в моем случае).

Я предвижу 2 решения до сих пор:

1) прочитанной модель Хранилища внутри запрос полной модели предметной области объекты, использовать их для заполнения DTO свойства (важно, требующие некоторой бизнес-логику от их использования). Здесь мы не получаем преимуществ по производительности, так как мы действуем на модели экземпляров домена.

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

Примеры:

1) бизнес-правило может быть столь же просто, как строковое представление определенных объектов или данных (по всей системе), т.е. форматирование;

2) Бизнес-правила можно рассчитать поле возвращающегося логическое значение, как в простой модели домена ниже:

// first aggregate root 
public class AssignedForm 
{ 
    public int Id {get;set} 
    public string FormName {get;set} 
    public ICollection<FormRevision> FormRevisions {get;set} 
    public bool HasTrackingInformation 
    { 
     get 
     { 
      return FormRevisions.Any(
         fr=> fr.RevisionType==ERevisionType.DiffCopy 
          && fr.FormRevisionItems.Any) 
     } 
    } 

    public void CreateNextRevision() 
    { 
     if(HasTrackingInformation) 
     { 
     ....... 
     } 
     ....... 
    } 
} 

public enum ERevisionType { FullCopy=0,DiffCopy=1 } 

public class FormRevision 
{ 
    public int Id {get;set} 
    public ERevisionType RevisionType {get;set} 
    public ICollection<FormRevisionItem> FormRevisionItems {get;set} 
} 

И тогда у нас есть хранилище модели чтения, скажем, IFormTrackingInfoReader возвращение коллекции объектов

public class FormTrackingInfo 
{ 
    public int AssignedFormId {get;set} 
    public int AssignedFormName {get;set} 
    public bool HasTrackingInformation {get;set} 
} 

Вопрос в том, как реализовать IFormTrackingInfoReader и заполнить HasTrackingInformation свойство , придерживающееся принципа DRY и без утечки домена в запрос. Я видел, как люди просто возвращали объекты домена и использовали сопоставление для заполнения модели представления. Наверное, это путь. Спасибо за помощь.

+3

«Я слышал это ...», «Я читал это ...» Было бы хорошо видеть ваши источники. Личное мнение: Паттернит затрудняет вашу способность просто ладить с ним и писать код. – spender

+0

+1 для форитов. –

ответ

0

Мне не нравится решение 1, модель домена не является постоянным невежественным.

Лично я предпочитаю решение2. Но «когда-либо требуемые данные» могут быть проблемой. Если возникнет требование нового запроса, возможно, вам понадобится миграция данных (я слышал, что повторное воспроизведение событий будет делать трюк при использовании источника событий). Поэтому я думаю, есть гибридное решение: используйте объекты значений для реализации выводов. И мы можем создавать новые экземпляры объектов значений с помощью dto.

public class SomeDto { 

    public String getSomeDerivation() { 
     return new ValueObject(some data in this dto).someDerivation(); 
    } 
} 

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

Update1:

Гибридное решение не подходит вашего конкретного случая FormTrackingInfo, но ваше решение два делает. Одним из примеров является (извините, я не .net парень, в Java)

public class CustomerReadModel { 
    private String phoneNumber; 
    private String ....//other properties 

    public String getPhoneNumber() { 
     return phoneNumber; 
    } 

    public String getAreaCode() { 
     return new PhoneNumber(this.phoneNumber).getAreaCode();//PhoneNumber is a value object. 
    } 
} 

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

+0

Можете ли вы подробнее рассказать о том, как вернуть ICollection с помощью гибридного подхода со значениями объектов? – ddv

+0

@ddv ответ обновлен, я боюсь, что это решение не работает, если данные не нужны в readmodel. – Hippoom

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