сильно разрастается? Становится нужно это, нужно то, и вот это прикрутить, и получается, что с течением времени поддерживать всю полученную лапшу становится очень сложно. Окидываю щас взглядом сильно связные компоненты своего пет-приложения и думаю, ведь зачем-то же Б-г дал нам интерфейсы, DI, IoC-контейнеры. Но как лучше всю эту братию использовать в десктопных/мобильных нативных приложениях?
Можно биндить вьюхи не на конкретные классы, а на интерфейсы, это удобно, поскольку в будущем такое приложение можно будет с лёгкостью расширить, написать новые вьюмодели для этих вьюх с другим поведением (например одинаковый интерфейс текстбокса, но с разными вьюмоделями => можно использовать один UI для бокса сообщений, комментов туда, комментов сюда, диалоговых окон обратной связи).
Но также Б-г дал нам shared-прожекты, в которых можно хранить вьюмодели и шарить их между разными UI-провайдерами — андроидовским, эппловским, увпшным или каким-нибудь другим.
Однако какой подход лучше избрать, когда приложение очень большое? Более ста вьюмоделей хранить в папке ViewModels, как завещал нам Caliburn.Micro, как-то некруто, путано, эти списки файлов листать можно с ума свихнуться и спутаться. То же самое с вьюхами. Получается, следует структуру разбить на модули-неймспейсы и выстроить иерархию типа:
- ViewModels [separate project]
-- Audio
--- AudioCollectionViewModel
--- AudioPageViewModel
--- AudioItemViewModel
-- Video
--- <...>
- Views [separate project]
-- Audio
--- AudioView
--- AudioShareView
-- Video
--- <...>
С таким подходом становится возможно шарить кодовую базу между разными UI-провайдерами и при этом она довольно проста и очевидна. Но что тогда делать с DI и биндами контролов на интерфейсы? Заметив, что проект может неконтролируемо расширяться, стоит ли делать ещё один проект-схему или же интерфейсы вью-моделей следует складывать вместе вьюхами приложения? Или с вьюмоделями? Пожалуй, этот вариант логичнее всего. Но необходимо ли для каждого класса выделать интерфейс и нигде не использовать прямых биндингов на инстансы? Ведь вдруг нам понадобится использовать несколько реализаций поведения одного и того же элемента управления (а еще один такой же элемент управления нам копипастить лень — и это антипаттерно).
Что мы получим, имея ввиду всё вышесказанное? Какова будет структура нашего нового проекта со слабой связностью компонентов? Попробуем разобраться!
- ViewModels [shared project]
-- Audio
--- Implementation
---- AudioCollectionViewModel
---- AudioPageViewModel
---- AudioViewModel
--- IAudioCollectionViewModel
--- IAudioPageViewModel
--- IAudioViewModel
Соответственно во всех компонентах реализованных моделек мы обмазываемся выделенными интерфейсами и слабо связываем наши компоненты, ни в коем случае не используя ключевое слово new (конечно же, потому что это антипаттерн). Получилось у нас всё просто, тестируемо и по фен-шую (ну, почти). Некоторые интерфейсы можно явно не описывать (например, IAudioCollectionViewModel), если они являются потомками generic-класса (например, IFetchableCollection<IAudioCollectioViewModel>). Итого мы ещё чуть-чуть упростили себе жизнь. Или такое всё же лучше описать явно, что думаете?
Prism
Обсуждают сегодня