Как стать автором
Обновить

Комментарии 9

Монструозненько, так и получается с сервером: Customer (Domain entity) -> CustomerDTO -> (JSON/whatever) -> CustomerDTO -> Customer (client domain entity) -> CustomerViewModel.
Нужно больше обьектов на одну сущность!
+CustomerEditModel
  1. Если этот (монструозный, как написали выше) велик используется только на старте, когда нужно быстро нагенерировать кучу стабов для DTO, Model, ViewModel, то профита от него в долгой перспективе я не вижу. Если подразумевается через него обновлять весь сгенерированный зоопарк при изменении требований или схемы БД, то опять я профита не вижу, зато вижу знатный вред в виде перетирания кастомного кода, добавленного в VM, напр., после генерации.
  2. ...Model: ObservableObject — означает, что собираетесь биндиться к модели. Это означает, что модель будет наполняться кодом присущим VM (например, команды или нотификации зависимых свойств). А это означает, что ваши модели де-факто станут ViewModel'ями. Зачем нужна прослойка ...Model: ObservableObject непонятно. Да и проходил много раз, когда к таким вот нагенерированным мета-моделям приходилось присоединять PARTIAL файлы. Очень скверно в контексте WPF.
  3. В общем, считаю генерацию ViewModel допустимой только одноразово и выгоды от этого чуть более, чем никакой.
1. Я подошел несколько более формально к вопросу.
Суть — если мы генерируем болванки, то это автоматически делает процедуру разовой для объекта. Потому что болванка изменяется руками. Бессмысленно делать повторно — кучу времени уйдет на merge.
Если же генерация должна быть стабильной (при изменении перегенерировать весь стек слоев) — то тогда этот скрипт уже должен являться неотъемлемой частью проекта и ввреху сгенерированного кода большими буквами «this file contains autogenerated code. Don't change it!»). То же, что, к примеру, генерирует EF. Ибо обратное будет сильно портить жизнь всем участникам проекта.
2. Хорошо, что обратили мое внимание на это! Никогда не думал в таком разрезе. ObservableObject, имхо — просто объект, который может говорить об своих изменениях. Думаю, это видно и из его имени, но все же уточнил. А для ViewModel я всегда использовал ViewModelBase.
Почему он тут? В определенных сценариях, в нашем проекте, объект может сказать «я поменялся». Если, к примеру, с сервера пришла более свежая версия объекта. Но суть не в этом, скрипт переписывается за 5 минут, притачиваясь к задаче.
3. Ваше право. Пример использования здесь — это только способ пояснения.

Я вижу профит в экономии времени на описание слоев, но если вдруг время на модификацию до нужного состояния превышает время линейного написания — то конечно скрипт будет проигнорирован.
Ну и надо не забывать, такое разделение предоставит возможности T4 тем, кто не знает что такое T4. В случае, если задача заскриптована «старшим» братом.
1. На моей практике почти не было проектов, когда бы архитектура заданная на старте не претерпевала значительных изменений уже спустя месяц. Обычно требования настолько смутны, что уже через пару месяцев приходишь к выводу, что структура БД являяет собой полную противоположность бизнес-проблеме. В таком случае реализация и внедрение такого рода генераторов может быть «Преждевременной Оптимизацией».
Был один проект, когда созданная и принятая схема БД полностью соответствовала бизнесу, но там на старте представитель заказчика очень эффективно с архитектором сработался и четко понимал, какие фичи нужны. Но даже в этом случае такой генератор значительного профита не дал бы, т.к. основное время тратится не на создание Model и VM с базовым функционалом, а на постройку поверх них специфических сценариев пользования.
2. Опять же в упомянутом выше проекте так и было сделано за исключением генерации VM. И пошли по простому пути — биндинг к моделям (aka ObservableObject). Если бы сразу делались VM вместо такого наследования, то потом не было столько возни с такими мета-моделями. Пришлось много логики сделать в partial файлах и еще больше вынести во врапающие VM. Поддерживать такое УГ неприятно. Так что…
а) Если сущность является DataContext'ом строки в DataGrid — сразу создавайте под нее VM. Это позволит безболезненно добавлять некие команды для манипулирования внутренностями данной сущности (активация / деактивация, пометка аттрибутами данной сущности и изменение подчиненных и тп). Иначе придется реализовывать эти команды в родительской VM.
б) Если в ячейке требуются разные специфичные педальки (комментарий или флаги какие-то дополнительные), то опять же желательно создавать VM для ячейки.

Я ругался и продолжаю каждый раз на старте ругаться. По началу кажется, что создание VM для основных вещей излишне и нужно следовать принципу YAGNI, но с WPF и VM этот принцип не работает. Создать сразу VM на старте недорого. А вот сделать подмену моделей на VM уже в зрелом проекте невозможно из-за нехватки времени. Лид команды должен иметь стальные орехи с алмазным напылением, чтобы продавить заказчику оплату такого технического долга. Проценты будут очень велики.
Печальный, но по любому полезный опыт! Я же, скорее люблю SOLID + KISS. В фоне где то маячит DRY.
Получается просто: у каждой ступеньки( класса), есть своя область ответственности, и даже если это приводит к избыточности кода, выраженном в количестве классов, то у каждого из них будет достаточно малая ответственность и он будет читаться легко. Не скажу что очень строго держусь за это, но в разрезе слоев MVVM — да.
Я тоже за SOLID. Только вот его часто каждый по-разному интерпретирует. В данном случае я считаю наделение моделей элементами VM как раз нарушением принципа Single Responsibility.
Не все так плохо. ObservableObject внутри себя содержит только deafult реализацию механизмов оповещения об изменении, т.е. INotifyPropertyChanged, INotifyPropertyChanging.
Да, можно сузить их применение до VM, но они были нужны для оповещения о восходящих изменениях, к примеру когда у нас один объект и несколько визуализаций к нему, каждая из которых может изменится вслед за изменением объекта. В этом случае удобно сделать объект просто говорящим.
Но, по правде сказать, со временем tracking изменений полностью отделился от моделей и наследования от ObservableObject — и для меня это уже скорее архаизм. Я по прежнему не вижу ничего плохого в говорящем объекте, но не имею права защищать эту точку зрения — сам уже поступаю иначе.
В любом случае спасибо за мнение, это было очень полезно! Суть статьи от этого не страдает, но пример — да, становится менее ярким.
Вот видите… все равно отделить придется. Поэтому нужно сразу отказываться, чтобы не переделывать.

Если не допустить наследование от ObservableOnject, то запрет на биндинг к моделям будет более осязаемый. Припугнуть, так сказать, девелоперов утечками памяти. Это решение лид должен принять и не поощрять.

Если же лид принимает такое решение, то он сам себе и команде злой Буратино.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации