Я использую аналогичный подход к Джеку, за исключением того, что я разделяю его дальше.
Похоже, излишнее (и может быть в некоторых случаях), но это дает вам большую гибкость в будущем.
Я бы создал два класса:
ProductViewModelFactory
(создает ProductViewModel
)
CategoryViewModelFactory
(создает CategoryVieWModel
)
ProductViewModelFactory
может внутренне использовать любое количество репозиториев, сервисов или других необходимых фабрик моделей представления для построения своих данных.
В этом случае ProductViewModelFactory
будет внутренне вызывать CategoryViewModelFactory
для создания CategoryViewModel
. ProductViewModelFactory
также, вероятно, вызовет ProductRepository
или ProductService
и отобразит возвращенный Product
, извлеченный из какого-либо постоянного хранилища, в модель представления.
Это может вызвать и другие вещи - если этого не произойдет сейчас, велика вероятность, что это произойдет позже, когда будет добавлено больше функций.
CategoryViewModelFactory
, вероятно, вызовет CategoryService
или CategoryRepository
и отобразит эти данные в CategoryViewModel
.
Итак, какие преимущества дают нам эти дополнительные слои? В конце концов, это больше работы.
Конечно, есть YAGNI, но, по моему опыту, этот подход дает наибольшую гибкость в обработке неожиданных требований при минимальном объеме работы.
В те времена, когда вы думали о YAGNI, но вы только что узнали, вам действительно понадобится , это может вызвать некоторые катастрофические ситуации - так что, ИМХО, стоит приложить дополнительные 20% усилий, чтобы создать простую последовательная структура, которая в большинстве случаев гарантирует, что вы не рисуете себя в углу.
- ViewModelFactories полностью отделены от репозиториев или сервисов, которые фактически получают данные.
Это означает, что когда требуется совершенно иное представление, вы не перебираете свои сервисы или репозиторий - они должны возвращать самые необработанные данные.
Они также могут вызывать другие ViewModelFactories, что становится удобным, так как во многих случаях по мере роста приложения вам нужно включать другие ViewModel в ViewModel внутри ViewModel внутри ... вы получаете точку.
- Становится очень просто макет поддельного ViewModelFactory, Repository или Service и внедряет его с помощью внедрения зависимостей, когда вам нужно что-то протестировать или вы не можете использовать реальную реализацию по какой-либо причине.
Это происходит чаще, чем вы думаете, когда:
- есть ошибка при определенных условиях, которую нужно проверить,
- еще один зависимый компонент не завершен,
- вам нужно вернуть определенный набор данных для просмотра для разработки веб-интерфейса,
- вы хотите создать серию тестов,
- вам нужно вернуть конкретные данные для демо клиента и т. д.
- Работа с любым классом в приложении становится простой, поскольку все является черным ящиком.
Вам не нужно заботиться о том, как фабрика, служба или хранилище модели представления получают свои данные или возвращают их. Вам не нужно заботиться о том, что потребляет его вне класса, над которым вы сейчас работаете.
Если вам нужен кусок данных, вы просто внедряете его фабрику, сервис или хранилище модели представления в зависимости от того, что вам нужно, передаете некоторые аргументы, и все работает в предсказуемом, согласованном порядке по всему приложению.
Итак, подведем итог , вот примерный жизненный цикл:
- Клиент делает запрос к действию контроллера.
- Действие контроллера вызывает фабрику модели единого представления, чтобы получить данные для представления действия.
- Фабрика модели представления вызывает любое количество других служб, репозиториев или других фабрик моделей представления (которые, в свою очередь, могут вызывать свои собственные службы, репозитории и фабрики моделей просмотра ...)
- Фабрика модели вида возвращает готовую модель вида.
- Действие контроллера берет возвращенную модель представления и помещает ее в представление.
- Клиент получает отрендеренный HTML.
Это также может дать вам несколько интересных опций для автоматической обработки вещей на основе соглашений об именах с фильтрами действий, что приводит к очень пустым действиям контроллера.