DDD и оптимизация для отображения данных в представлениях - PullRequest
2 голосов
/ 05 декабря 2011

Это общее требование во многих веб-проектах: объект должен показывать информацию другому связанному объекту.Например, книга на сайте электронной коммерции должна показывать соответствующую информацию об ее авторе.

Допустим, я моделирую книгу и автора как сущность, как мне реализовать функцию, которая отображает книгу и информацию об авторе на одной странице.

  • Я могу сделатьвызов BookRepo для получения информации о книге, а затем другой вызов AuthorRepo для получения автора с использованием authorid внутри сущности книги.Это 2 запроса
  • Я могу написать запрос, в котором я объединяю таблицы Book и Author вместе и получаю обе информации в 1 запросе.Но какой репозиторий идет по этому запросу?Это нарушает DDD, потому что я предполагаю детали о Книге и Авторе?

Что такое «лучшие практики» и как я могу решить эту проблему другими способами?

(я предполагаю использование стандартных запросов SQL [таких как PHP +)MySQL], поскольку в EF 4 вы определяете ассоциации между Книгой и Автором, что довольно легко решит проблему).

Ответы [ 3 ]

1 голос
/ 06 декабря 2011

Если вы посмотрите на эту страницу , она описывает два способа загрузки и соотнесения совокупных корней.Связав это с вашим примером:

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

Если у вас есть сервисный метод с именем FindBookByTitle, то при загрузке сущности Book будет загружатьсясоответствующая информация об авторе из BookRepo.

class Author
{
  public Author(int authorID, FullName name) { }

  int AuthorID { get; }
  FullName Name { get; }
  List<BookDetails> AuthoredBooks { get; set; }
}

class BookDetails
{
  public BookDetails(int ID, string title) { }

  int BookID { get; }
  string Title { get; }
}

class Book
{
  public Book(int ID, string Title) { }

  int BookID { get; }
  string Title { get; }
  List<AuthorDetails> Writers { get; set; }
}

class AuthorDetails
{
  public AuthorDetails(int ID, FullName name) { }

  int AuthorID { get; }
  public FullName fullName { get; }
}

class FullName
{
  public FullName(string name, string surname) { }

  public string Name { get; }
  public string Surname { get; }
}
1 голос
/ 07 декабря 2011

Для этого не существует решения «серебряной пули», но у вас есть несколько вариантов.

Ваше первое предлагаемое решение о вызове в два репозитория совершенно правильно и происходит на практике постоянно.Например, для отображения страницы продукта Amazon требуется более сотни различных сервисов.Каждый сервис отвечает за предоставление данных, специфичных для его ограниченного контекста.Вы можете создать сервис, называемый чем-то вроде BookService, который вызывает два репозитория для возврата объекта отчетности или DTO, в котором есть все данные, необходимые для конкретного представления.Если вы чувствуете, что производительность связана с двумя вызовами из репозитория, это может стать проблемой, вы можете использовать кэширование или CQRS для создания подходящих моделей чтения, но не переходите к этим решениям преждевременно.

Но какой репозиторий выполняет этот запрос? Я бы просто добавил его в BookRepository или даже целый новый репозиторий под названием BookDetailsReportingRepository, возможно, метод с именем GetBookDetails.Этот метод возвращает не редактируемую сущность, а отчетный объект, который представляет собой проекцию значений из нескольких сущностей.

Это нарушает DDD, поскольку я предполагаю подробности о сущности Book и Author? Это не нарушает DDD и, по моему мнению, облегчает его применение.Просто считайте данные, возвращаемые вышеупомянутым хранилищем, объектами отчетности, а не объектами.

1 голос
/ 06 декабря 2011

Но даже если вы, кажется, не используете ORM, вам, вероятно, придется заполнять свои сущности из ваших SQL-запросов, и ваши сущности должны каким-то образом связываться друг с другом (коллекции, свойства навигации и т. Д.).Если в вашем домене есть объекты, которые не связаны между собой, я бы не назвал это DDD, поскольку у вас нет таких важных компонентов, как агрегаты, объекты значений, двунаправленные / однонаправленные отношения.Но что я знаю :-) Может быть, вы хорошо сделали свою головоломку, и эта последняя часть состоит в том, чтобы объединить сущности в «представление», которое может быть полезно для ваших клиентов.

Поскольку репозитории обычно работают в совокупности,В качестве корневого объекта вы можете использовать методы репозитория, такие как ListBooksByAuthor (BookRepository) или ListAuthors (AuthorRepository).

Если вы хотите отобразить сложные данные из разных агрегатов на веб-странице, я рекомендую использовать объекты передачи данных.Пусть этот объект DTO будет уникальным для этой страницы или варианта использования и будет «представлением», которое отображает все (или большую часть) данные, которые нужны веб-странице.Я также рекомендую НЕ использовать DTO везде, если вы не используете веб-сервисы.Совместное использование DTO дает как плюсы, так и минусы.Вместе с сервисным уровнем он дает вам собственный антикоррупционный уровень, а также дает вам возможность внедрить репозиторий Book и Author.Затем из сервисного уровня вы можете собирать и собирать DTO (посмотрите на AutoMApper или подобное ... вам очень поможет).НО многие DTO повсюду также дают вам накладные расходы на обслуживание приложения.Это добавляет еще один слой для поддержки.Я предпочитаю просто использовать его для определенных клиентов / веб-страниц.

Я надеюсь, вы понимаете, что я пытаюсь объяснить: -)

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