Pull to refresh

Comments 7

Спасибо за статью, как раз вынужден оперативно разбираться с авалонией и мввм, очень доступно разложили. Было бы здорово, если пример о навигации был бы более развернутый

Поставил бы лайк, да карма не позволяет :(

Будет серия статей про mvvm. И про навигацию тоже будет подробная статья. Постараюсь за следующую неделю все опубликовать. Следите. Спасибо за отзыв.

Карму немного исправил :)

enum State {        
    case idle        
    case loading        
    case loaded([Product])        
    case error(String)    
  }

Вместо россыпи разрозненных свойств я предпочитаю использовать единый State. Идеальный инструмент для этого - enum.

вы видимо не сталкивались с более сложными view model, где нужно данные из одного State case перегонять в другой.

Leaky Views: Передача UI объектов во ViewModel. Никогда не передавайте UIImage или NSAttributedString. Передавайте Data или просто String. ViewModel должна жить в мире чистой логики.

не совсем понял. Вы предлагаете запретить передавать UI в модель или чтобы модель не использовала swiftui и uikit в целом?
А еще что вы предлагаете делать, когда у вас NSAttributedString состоит из нескольких частей с разным форматированием, которые нужно еще собрать в одну строку перед тем, как показать?

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

А про запрет UI во ViewModel - да, если у вас есть необходимость импортить UIKit во viewModel, то это порочная практика. Именно об этом и пишу. Этого всегда можно избежать. В случае с атрибутированной строкой можно написать отдельный helper, который помогал бы решить эту проблему и дергать его из ViewModel. Кмк это бы решило проблему чистого ViewModel.

Соглашусь с первым комментарием по поводу состояния.

"Состояние"("State") – это прям отдельный шаблон из книжки Банды Четырех, чтобы с ним работа была комфортна, он должен реализовываться через набор классов с одним и тем же интерфейсом. Иначе, рано или поздно столкнетесь с проблемами. Например, enum'ы не расширяемые. Добавить состояние без нарушения OCP у вас не выйдет. В мелких проектах это и не важно, но в крупных...

Ну, и Вы тут много говорите о том, что не нужно смешивать ответственности, а "Состояние" (с переходами между ними, которые довольно часто не тривиальные! и не все вообще разрешены!) – вполне себе цельная отдельная ответственность...

Попробуйте её инкапсулировать по шаблону Банды Четырех. Не с первого раза, но получится всю прелесть прочувствовать...

Сам тоже сейчас редактирую статью про "правильную готовку" MVVM. Думал уже не публиковать, но, видимо, теперь придется :)

В статье Вики про MVVM указано, что вьюмодель содержит всего 3 ответственности:

  1. абстракцию для разделения вьюхи и модели (слабая связность).

  2. преобразование данных из вида модели к виду отображения (и возможно, но необязательно, обратно).

  3. биндинг - вариация абстрагирования и/или преобразования данных.

Вот, в принципе и все, что имеет право быть во вьюомдели. Все остальное, что вы перечислили, это уже либо модель, либо представление. Без вариантов! Например, навигация – ответственность представления. Если Вы меняете систему представления (например, с iOS переезжаете на мак, часы или телевизор), то в Вашем приложении не нужно бы менять ни вьюмодель, ни модель... а если Ваша модель зависит от роутера или координатора, то вам этого не избежать... а вот если роутер или координатор дергаются напрямую из вью, то остальные два слоя вашего приложения изменений не требуют – достаточно поменять только представление...

Unidirectional Data Flow – это пункт 2 из обязательных ответственностей. Преобразование данных. В одну и в другую сторону. Они в 142% случаев всегда независимы друг от друга, да. Поэтому реализовать их в двух разных классах не представляет сложности никогда. Но при этом оба класса все же остаются внутри слоя вьюмодели. Это слой. Он не обязан состоять из одного класса... В вашем примере Вы просто лишь одну часть этой ответственности осуществляете через биндинг. Но можно и обе, проблем не будет, это все еще будет UDF, если вью будет писать в одно свойство, а модель в другое (в одном или разных объектах – уже неважно)...

Но в принципе биндинг для преобразования данных не обязателен, как и для абстракции. Но с его помощью можно реализовать и то, и другое. А можно и не реализовывать. Биндинг для MVVM не обязателен, но тогда оно выродится в MVP или MVC с пассивной моделью.

В остальном, Вы молодец. Копайте глубже и проблем у Вас не будет ни с какой архитектурой. Еще и на лету их сможете менять, если ответственности представления (типа навигации) не будете опускать ниже.

ПС: неплохо Вы статьи генерите – по одной в день – ИИ помогает?

Sign up to leave a comment.

Articles