Теперь давайте какие реальные плюсы у т.н. декларативного? Букв меньше не стало. Совокупная сложность кода не понизилась — все равно в конвертере есть проверка if и выбор цвета. В XML-е писать не удобнее, но даже не в этом суть.
Только вера в то, что декларативно типа круче?
Ну ОК, вы скажите что ковертор можно будет задействовать в другом месте. Но! Что мешает мне вынести:
if (businessObject.Date.IsOdd)
DateTextBox.Background = Color.Red;
— в отдельный метод и просто его вызывать? Вам для конвертора придется целый класс содавать а мне — только метод.
Подозреваю что начнут приводить преимущества т.н. двустороннего связывания и обработки событий изменения данных. У меня есть что ответить на это, но подожду пока скажут.
Получается, что никакого реального преимущества, кроме хайпа, нет
Здравствуйте, Shmj, Вы писали:
S>Получается, что никакого реального преимущества, кроме хайпа, нет :xz:
Ни так, ни эдак делать не нужно. И декларативное vs. императивное тут ни при чём.
Конвертер не нужен. Потому что ViewModel — это и есть конвертер на стероидах. Должна быть привязка к свойству во вью-модели того же типа, что требуется для GUI. А уж внутри этого свойства мапь из низлежащих данных хоть императивно, хоть декларативно. На внешнем уровне всё останется декларативным.
Здравствуйте, Shmj, Вы писали:
S>Почему все верят, что декларативный подход рулит и на порядок упрощает работу?
Часто упрощает. Классический пример: соотношение размеров графических элементов, простые анимации и т.п.
В С++ и Qt есть оба подхода: QML и QWidgets. Многое на QML проще.
Re[2]: Связывание форм (GUI) с данными: императивно vs декларативно
S>>Почему все верят, что декларативный подход рулит и на порядок упрощает работу? S>В С++ и Qt есть оба подхода: QML и QWidgets. Многое на QML проще.
Действительно, некоторые простые примеры на QML выглядят проще. Но, не совсем понятно, как можно называть QML-подход декларативным. Как там насчет таблиц и деревьев? А деревьев в таблицах, сожержащих таблицы? Не нужно, да?
Re: Связывание форм (GUI) с данными: императивно vs декларативно
S>Почему все верят, что декларативный подход рулит и на порядок упрощает работу? S>Вот, давайте на примере.
Возьмите пример посложнее. ГУИ для списка, содержащего деревья разных типов, содержащие списки разных типов. Используйте темплейты для данных. Готово.
Что нужно сделать для создания ГУИ императивно? Даже подумать страшно. Определенные императивные технологии, и некоторые причисляющие себя к "декларативным", такого в принципе не поддерживают.
Вот это и есть порядок реального преимущества.
Re[3]: Связывание форм (GUI) с данными: императивно vs декларативно
Здравствуйте, Владимир35, Вы писали:
В>Действительно, некоторые простые примеры на QML выглядят проще. Но, не совсем понятно, как можно называть QML-подход декларативным. Как там насчет таблиц и деревьев? А деревьев в таблицах, сожержащих таблицы? Не нужно, да?
А никто и не говорил, что все задачи можно решить чисто декларативным подходом, в отличии от императивного. Очевидно, что кто-то должен реализовать эту подкапотную магию, для всех случаев это невозможно
Re: Связывание форм (GUI) с данными: императивно vs декларативно
S>Теперь давайте какие реальные плюсы у т.н. декларативного? Букв меньше не стало. Совокупная сложность кода не понизилась — все равно в конвертере есть проверка if и выбор цвета. В XML-е писать не удобнее, но даже не в этом суть.
Потому что ты не зе знаешь никаких других подходов, кроме XAML'а, и делаешь далеко идущие выводы. Например, SwiftUI тоже декларативный, сильно короче XAML'а и короче аналогичного декларативного бкода, и наглядно показывает удобство деклартивного кода и прозрачного связывания данных даже на простых примерах, например тут: https://developer.apple.com/tutorials/swiftui/creating-and-combining-views UI просто становится комбинацией вложенных структур, которые можно как угодно менять и вкладывать друг в друга.
Здравствуйте, Shmj, Вы писали:
S>Теперь давайте какие реальные плюсы у т.н. декларативного? Букв меньше не стало. Совокупная сложность кода не понизилась — все равно в конвертере есть проверка if и выбор цвета. В XML-е писать не удобнее, но даже не в этом суть.
ну например при декларативном биндинге, автоматом работает обновление отображаемого значения при изменении значения проперти в модели.
также например в декларативном биндинге потенциально можно использовать формулу, и подсистема биндинга может её проанализировать, выявить зависимости
от других полей модели и пересчитывать и обновлять отображаемое значение при их изменении.
Re[2]: Связывание форм (GUI) с данными: императивно vs декларативно
Здравствуйте, Владимир35, Вы писали:
В>Что нужно сделать для создания ГУИ императивно? Даже подумать страшно. Определенные императивные технологии, и некоторые причисляющие себя к "декларативным", такого в принципе не поддерживают.
В императивном стиле это будет выглядеть как вложенные друг в друга циклы или рекурсивные функции. Там все интуитивно понятно.
А вот в декларативном — действительно деревья с ветками разных типов со списками представить сложно.
Re[2]: Связывание форм (GUI) с данными: императивно vs декларативно
Здравствуйте, Mamut, Вы писали:
M>Потому что ты не зе знаешь никаких других подходов, кроме XAML'а, и делаешь далеко идущие выводы. Например, SwiftUI тоже декларативный, сильно короче XAML'а и короче аналогичного декларативного бкода, и наглядно показывает удобство деклартивного кода и прозрачного связывания данных даже на простых примерах, например тут: https://developer.apple.com/tutorials/swiftui/creating-and-combining-views UI просто становится комбинацией вложенных структур, которые можно как угодно менять и вкладывать друг в друга.
А как там будет выглядеть установка цвета даты в зависимости от четности, к примеру?
Re[2]: Связывание форм (GUI) с данными: императивно vs декларативно
Здравствуйте, MadHuman, Вы писали:
MH>ну например при декларативном биндинге, автоматом работает обновление отображаемого значения при изменении значения проперти в модели.
А оно не всегда нужно!!! Более того — иногда обновление нужно моментальное (т.е. пользователь еще не успел убрать фокус из элемента ввода) а иногда отложенное. Иногда обновление нужно связанное не с данными а с командой — как то нажатие на кнопку.
MH>также например в декларативном биндинге потенциально можно использовать формулу, и подсистема биндинга может её проанализировать, выявить зависимости MH>от других полей модели и пересчитывать и обновлять отображаемое значение при их изменении.
А ссылку на пример дадите?
Re[3]: Связывание форм (GUI) с данными: императивно vs декларативно
M>>Потому что ты не зе знаешь никаких других подходов, кроме XAML'а, и делаешь далеко идущие выводы. Например, SwiftUI тоже декларативный, сильно короче XAML'а и короче аналогичного декларативного бкода, и наглядно показывает удобство деклартивного кода и прозрачного связывания данных даже на простых примерах, например тут: https://developer.apple.com/tutorials/swiftui/creating-and-combining-views UI просто становится комбинацией вложенных структур, которые можно как угодно менять и вкладывать друг в друга.
S>А как там будет выглядеть установка цвета даты в зависимости от четности, к примеру?
Ты бы мог пройти по приведенной мной ссылке и увидеть сам. Но ты этого делать не собираешься, потмоу что твоя единственная задача — создать информационный шум и побольше тем с целью бессмысленных споров.
Здравствуйте, Shmj, Вы писали:
MH>>ну например при декларативном биндинге, автоматом работает обновление отображаемого значения при изменении значения проперти в модели.
S>А оно не всегда нужно!!! Более того — иногда обновление нужно моментальное (т.е. пользователь еще не успел убрать фокус из элемента ввода) а иногда отложенное. Иногда обновление нужно связанное не с данными а с командой — как то нажатие на кнопку.
если нужно в большинстве случаев, то исключения уже не играют рояль.
к тому же описанные вами варианты, могут быть потенциально реализованы как доп. настройка (проперть) режима декларативного биндинга.
MH>>также например в декларативном биндинге потенциально можно использовать формулу, и подсистема биндинга может её проанализировать, выявить зависимости MH>>от других полей модели и пересчитывать и обновлять отображаемое значение при их изменении.
S>А ссылку на пример дадите?
такое есть внутри нашего проекта, но используется внутренняя реализация.
в общедоступных сходу не припомню, но смутно припоминаю что в каких-то веб-фрэймворках такое видел.
Re[4]: Связывание форм (GUI) с данными: императивно vs декларативно
Здравствуйте, MadHuman, Вы писали:
MH>если нужно в большинстве случаев, то исключения уже не играют рояль.
А вот в этом и ошибка — кто сказал, что нужно в большинстве случаев?
В большинстве случаев ничего не нужно обновлять на форме для каждого элемента. Есть редкие элементы, для которых нужно обновлять форму — либо после того как убрал фокус либо до.
MH>к тому же описанные вами варианты, могут быть потенциально реализованы как доп. настройка (проперть) режима декларативного биндинга.
Проблема в том, что на практике кода меньше не становится
Вроде бы да, двойное связывание (но и оно не всегда нужно!) позволяет писать в 2 раза меньше кода. Однако из-за индивидуальных особенностей каждой конкретной формы, как правило, проигрываешь в другом.
Re: Связывание форм (GUI) с данными: императивно vs декларативно
Здравствуйте, Shmj, Вы писали:
S>Теперь давайте какие реальные плюсы у т.н. декларативного? Букв меньше не стало. Совокупная сложность кода не понизилась — все равно в конвертере есть проверка if и выбор цвета. В XML-е писать не удобнее, но даже не в этом суть.
S>Только вера в то, что декларативно типа круче?
Не вера, а знание. Это ты не веришь, а мы точно знаем
У тебя ошибка в том, что ты сравниваешь количество строк, простоту восприятия этого примитивного примера и относительную лёгкость создания такого кода. Так и есть. Всё верно. На простом примере такой код выглядит проще и писать его легче. Да и на более сложном примере будет примерно тоже самое. Вообще, я считаю, что любой нормальный программист должен без проблем сгенерировать строчек сто кода, которые должны даже работать. Почему все так любят всё переписывать? Потому что на чистом листе ещё нет никаких проблем, пиши себе, излагай мысль, одно удовольствие.
Все проблемы начинаются потом. Когда эти удовольствия и мысли нужно изогнуть в другую сторону, выправить под изменившиеся требования, расширить или наоборот урезать, но не всё, а только часть и сбоку ещё чего-нибудь пришпандорить.
Вот в этом случае императивный подход сосёт у декларативного как трофейный пылесос.
Ценность технологий, паттернов и подходов не в том, чтобы можно было быстро наклепать простой пример или демку (как в Code First). Не в том, что этот примитивный пример получился не в 10 строк, а в 9. Это всё не более чем приятный бонус. Ценность всего этого в том, насколько сопровождаемым и управляемым будет твой код на протяжении всего его жизненного цикла. Сможешь ли ты через год в своём или вообще в чужом коде быстро разобраться в хитросплетениях ифов и циклов? Не на твоём примере, а там где количество строк уже давно за тысячи и руку приложило несколько девелоперов. Я сомневаюсь. А в декларативном коде всё это сделать будет на порядок проще. Потому что его было тяжелее создавать, тяжелее проектировать, поначалу даже больше писать. Зато менять его как два пальца об асфальт.
Если нам не помогут, то мы тоже никого не пощадим.
Re[2]: Связывание форм (GUI) с данными: императивно vs декларативно
Здравствуйте, Mamut, Вы писали:
M>Потому что ты не зе знаешь никаких других подходов, кроме XAML'а
Да и зэмл, а точнее WPF он знает весьма поверхностно.
M>, и делаешь далеко идущие выводы. Например, SwiftUI тоже декларативный, сильно короче XAML'а и короче аналогичного декларативного бкода, и наглядно показывает удобство деклартивного кода и прозрачного связывания данных даже на простых примерах
Даже тут не к месту. Как раз на простыхьпримерах декларативность рулит. Проблемы наступают со сложными, так как императивный код гибче даже хорошего декларативного, и просто на две головы выше плохого декларативного, коего, увы, намного больше.
... << RSDN@Home 1.3.17 alpha 5 rev. 62>>
Re[3]: Связывание форм (GUI) с данными: императивно vs декларативно
НС>Даже тут не к месту. Как раз на простыхьпримерах декларативность рулит. Проблемы наступают со сложными, так как императивный код гибче даже хорошего декларативного, и просто на две головы выше плохого декларативного, коего, увы, намного больше.
Нужна прагматичность: декларативность, где надо, и императивность, где надо Но где ж найти идеал-то...
Здравствуйте, Mamut, Вы писали:
M>Нужна прагматичность: декларативность, где надо, и императивность, где надо Но где ж найти идеал-то...
Даже небольшая примесь императивности все сильно усложняет. Хороший пример — Blend и редактор WinForms. Последний намного более убог, но при этом очень глючен и мутен. Причина как раз наличие неизбежной императивности.
... << RSDN@Home 1.3.17 alpha 5 rev. 62>>
Re[5]: Связывание форм (GUI) с данными: императивно vs декларативно
M>>Нужна прагматичность: декларативность, где надо, и императивность, где надо Но где ж найти идеал-то...
НС>Даже небольшая примесь императивности все сильно усложняет. Хороший пример — Blend и редактор WinForms. Последний намного более убог, но при этом очень глючен и мутен. Причина как раз наличие неизбежной императивности.
Императивщина все равно бывает нужна. Потому что декларативность бывает многословна и/или неэффективна. Или надо работать с императивным кодом. И т.п. Но ее надо ограничивать. Типа «в условиях X мы можем использовать императивный код».
Например, в туториале, что я привел по ссылке, есть раздел «Use UIKit and SwiftUI Views Together»:
struct MapView: UIViewRepresentable {
func makeUIView(context: Context) -> MKMapView {
MKMapView(frame: .zero)
}
func updateUIView(_ view: MKMapView, context: Context) {
let coordinate = CLLocationCoordinate2D(
latitude: 34.011286, longitude: -116.166868)
let span = MKCoordinateSpan(latitudeDelta: 2.0, longitudeDelta: 2.0)
let region = MKCoordinateRegion(center: coordinate, span: span)
view.setRegion(region, animated: true)
}
}
struct MapView_Preview: PreviewProvider {
static var previews: some View {
MapView()
}
}
в update/make позволяется императивный код. Но для кода вокруг получившуюся струтуру все равно можно использовать дебкларативно
struct ContentView: View {
var body: some View {
VStack {
MapView()
VStack(alignment: .leading) {
Text("Turtle Rock")
HStack(alignment: .top) {
Text("Joshua Tree National Park")
Spacer()
Text("California")
}
}
}
}
}
struct ContentView_Preview: PreviewProvider {
static var previews: some View {
ContentView()
}
}
Вот что-то в таком стиле, имхо, — правильный подход.
Здравствуйте, Shmj, Вы писали:
S>Почему все верят, что декларативный подход рулит и на порядок упрощает работу?
Потому что суть не в противопоставлении себя "императивщине", а в том, что декларативный подход суть DSL. А это значит, что в твоём "языке ГУЁв" только самые нужные элементы и они заточены на свою задачу, позволяя наиболее мощно описывать решение.
S>Декларативный подход типа:
S>
Здравствуйте, Kolesiki, Вы писали:
K>Здесь {} — сокращение для Binding, [] — вызвать функцию из кода, "" — задать значение напрямую. K>Ну чем тебе не идеал?
Здравствуйте, Shmj, Вы писали:
S>Здравствуйте, Kolesiki, Вы писали:
K>>Здесь {} — сокращение для Binding, [] — вызвать функцию из кода, "" — задать значение напрямую. K>>Ну чем тебе не идеал?
S>Не XML-валидно.
А наплевать. XAML — это худшее, что есть в WPF. Тот же ammy, который ionoy сделал в 100 приятнее. К сожалению чтоб оно взлетело нужно, чтоб такую такую штуку MS делал.
Здравствуйте, Qbit86, Вы писали:
Q>Здравствуйте, Shmj, Вы писали:
S>>Получается, что никакого реального преимущества, кроме хайпа, нет
Q>Ни так, ни эдак делать не нужно. И декларативное vs. императивное тут ни при чём.
Q>Конвертер не нужен. Потому что ViewModel — это и есть конвертер на стероидах. Должна быть привязка к свойству во вью-модели того же типа, что требуется для GUI. А уж внутри этого свойства мапь из низлежащих данных хоть императивно, хоть декларативно. На внешнем уровне всё останется декларативным.
Q>Вместо этого: Q>
Если потребуется изменить цвет подсветки, то нам потребуется вносить изменения в ViewModel. Было бы лучше если бы нам для этого потребовалось изменить лишь style в разметке.
Q>Если потребуется изменить цвет подсветки, то нам потребуется вносить изменения в ViewModel.
В исходном примере тоже потребовалось бы вносить изменение в код — в конвертере.
Q>Было бы лучше если бы нам для этого потребовалось изменить лишь style в разметке.
Чем лучше? Кому лучше?
Глаза у меня добрые, но рубашка — смирительная!
Re: Связывание форм (GUI) с данными: императивно vs декларат
Здравствуйте, Shmj, Вы писали:
S>Почему все верят, что декларативный подход рулит и на порядок упрощает работу?
разработка софта в отличие от, например, строительства еще очень молода.
Люди ищут оптимальные подходы. Какое-то время казалось, что отделить разработку форм от обработки данных хорошая идея.
Скорее всего причина только в этом. Есть разные идеи и у каждой есть сторонники.
Но лично мое мнение, что победит "код как данные", посмотрите на успех elm, кложури и кложескрипта, https://github.com/fsprojects/Fabulous
websharper, fsbolero и т.п.
Любой UI это иерархия элементов(связанный список), если у нас в ЯП есть "list comprehension"(удобный для понимания человеком способ представления списков),
то проще и эффективней описать UI именно так. Отображение данных при этом на порядок упрощается, так же как и DRY и прочие вещи.
UPDATE. еще очевидный плюс — один яп вместо местного диалекта (XAML и т.п.) или привязка к дизайнеру(который еще и чувствителен к изменениям).
Здравствуйте, Shmj, Вы писали:
S>Почему все верят, что декларативный подход рулит и на порядок упрощает работу?
Потому что это решает не одну задачу, а множество. И чем больше задач ты решаешь, тем лучше декларативный подход.
S>Вот, давайте на примере.
Тут проблемы две.
1. В ВПФ декларативность убогая. Сам язык разметки — убогий. Программирование на ХМЛ, плюс динамическая типизация, плюс кране скудная и не удобная расширяемость. Вот если взять хотя бы АММИ, то расклад меняется.
2. Ты решаешь только одну задачу — отображение данных. И сравниваешь только объем кода. А в реальности задач бывает куда больше.
Вот смотри. У нас ГУЙ решает следующие задачи:
1. Переиспользование воью-моеделей.
2. Локализация.
3. Тестирование. Тестируется сам продукт, но через дерганье вью-моделей.
4. Отделение верстки от кода логики. Программист только рисует набросок формы и реализует ВМки с биндингом, а уже за реальное визуальное представление отвечают проффесионалы в верстке. Перередически производится рескининг (смена внешниего вида).
5. Реактивность и гибкость ГУя.
6. Автоматически снять скриншоты для всех переводов и для всех состояний, чтобы переводчики могли проверить правильность переводов и не были вынуждены протыкивать весь продукт годами (форм море).
S>Есть поле на форме, вам нужно установить дату и подсветить, если дата нечетная.
S>Императивный подход (примерно):
S>
И вот теперь нам нужно поменять цвет. Нам придется править код.
Далее нам нужно оттестировать все это. А присвоения хер знает где. Мы не можем тупо присвоить дату в ВМке и быть уверенным, что гуй ее отобразит как надо.
Следующая задача — локализация. Мы должны опять таки править код.
И так далее.
S>Декларативный подход типа:
S>
Ну, в ресурсы засовывать конвертер не обязательно. Решапрер или Райдер резолвят их по одному нажатию в нейспэйс.
Но согласен, что читабельность у этого птичьего языка не высока.
Правильно это бы выглядело как-то так:
using dateBacklightConverter=X.Y.X.dateBacklightConverter;
...
TextBox { Text=Date; Style=dateBacklightConverter(Date); }
Или даже:
using dateBacklightConverter=X.Y.X.dateBacklightConverter;
...
TextBox { Text=Date; Style=Date.IsOdd ? Normal : Highlighted; }
То есть это вопрос грамотной реализации языка попсания вьюх.
S>Теперь давайте какие реальные плюсы у т.н. декларативного? Букв меньше не стало.
У меня стало.
S>Совокупная сложность кода не понизилась
1. Код раделен на представление и ВМку. Теперь его можно тестировать.
2. Его внешний вид определяется стилями не связанными с кодом. Стало быть их можно легко менять.
3. Наш код реактивен, а значит его легче тестировать.
4. Мы можем переиспользовать ВМки в других вьюшках.
S> — все равно в конвертере есть проверка if и выбор цвета.
Да, логика представления никуда не девается. И если это однократное использование, то проще было бы описать его по месту.
Но если таких использований сони (что бывает часто в больших продуктах), то таки выгоднее вынести ее в отдельное место.
S>В XML-е писать не удобнее, но даже не в этом суть.
Полностью согласен. ХМЛ — плохой язык для программирования, а вьюхи все равно являются кодом, хоть и декларативным.
Еще минус — динамическая природа ВПФ. Но кое-ка ее обуздывает Решарпер и Райдер (в студии поддержка — говно).
S>Получается, что никакого реального преимущества, кроме хайпа, нет
Ты ее не там ищешь.
Смысл в разделении визуального представления и кода. Пока у тебя 2 строки, преимущества такого подхода не особо видны. Но если кода море, то смешивание логики представления и логики данных дает страшную кашу.
В большой компании версткой занимаются отдельные люди. Они обычно вообще не понимают в логике данных, но прекрасно справляются с визуальным представлением.
Плюс навороты бывают разными. Например, я тут выезивался недавно загоняя в заголовок ячейки грида чекбоксы и даже кнопки с меню. При этом в ВМ-ах оставались вполне понятные списки и булево свойство. Вся логика работы описывается в ВМке. Во вьюхе только биндиг к снадратным контролам, которые можно спокойно совать друг в друга. В итоге получается очень навороченный по функциональности гуй за вполне короткий срок. И это я этот ВФП второй раз в жизни видел.
В общем, сама идея раздения на представления и модели-представлений — здравая. ХМЛ — идиотизм! Динамка — астдай! То что ВМки нужно руками выписывать (все эти
INotifyPropertyChanged — тоже оверхэд).
Идеальное решение мне видится следующим образом:
1. Все вьюхи должны иметь статически заданный тип ВМки (контролируется ИДЕ и компилятором). При этом допускается сабтайпинг на интерфейсах.
2. Вьюхи должны поддерживать паттерн матчинг по типам сабатйпинга.
3. Во вьюхах должен использоваться специально разработанный для этого язык без всяких ХМЛ-ей или джейсонов.
4. Во вьюхах должны поддерживаться гибкие операторы как в нормальных императивных языках.
5. Для описания ВМок язык должен поддерживать зависимые вычисления (как ленивость в Хаскеле). Это позволит обойтись без костылей в виде
INotifyPropertyChanged. Просто пишешь:
Здравствуйте, Qbit86, Вы писали:
Q>Ни так, ни эдак делать не нужно. И декларативное vs. императивное тут ни при чём.
Q>Конвертер не нужен. Потому что ViewModel — это и есть конвертер на стероидах. Должна быть привязка к свойству во вью-модели того же типа, что требуется для GUI.
Нет, это нарушает идеологию MVVM. VM-а не должна думать о форматировании данных или их визуальном представлении. В идеале VM-ка должна только содержать сами данные.
Представь, что твой продукт должен быть локализован на десятки языков, а тебе нужно оттестировать ее. И вот ты возвращаешь из нее текст, а потом плюешься в тестах, так как он на разных языках разный.
Q>А уж внутри этого свойства мапь из низлежащих данных хоть императивно, хоть декларативно. На внешнем уровне всё останется декларативным.
Грош цена такой декларативности. Нет, возня с конвертерами это суровая действительность. И сделано это в ВПФ крайне убого и неудобно.
Я за последние 3 месяца насмотрелся хардкорного ВПФ-а с многометровыми простынями, которые не увидеть в дизайнере, и которые без пол литры не поймешь. Но соображения тестируемости, локализуемости и легкой смены визуального представления требуют иметь VM-ки с сырыми данными, а все визуальные навороты (включая перевод, форматирование и т.п.) производить только через конвертеры.
Можно конечно вводить иерархии ВМ-ок, где одна из них хранит сырые данные, а другая локализованные и приведенные к нужным типам. Но своего рода костыль вызванный убогостью ВПФ-а.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[2]: Связывание форм (GUI) с данными: императивно vs декларативно
Здравствуйте, Владимир35, Вы писали:
В>Что нужно сделать для создания ГУИ императивно? Даже подумать страшно. Определенные императивные технологии, и некоторые причисляющие себя к "декларативным", такого в принципе не поддерживают.
Это вопрос навороченности контролов. То что ВПФ позволяет делать иерархические верстки не заслуга MVVM, а заслуга архитектуры ВПФ. Та же херня в HTML, хотя там исходно MVVM-ом и не пахло, а ветки можно менять императивно.
Да и ВПФом можно спокойно возиться императивно.
Причем в ВПФ-е море подводных граблей (тм). Это и ретемлейтинг с необходимостью менять пол контрола. И данамика в связывании. И сложная отладка (почти никакая). И дебильная императивность стилей (это не стили, а какие-то императивные конструкции, в которых море присвоений свойств и откровенных шаблонов верстки). Короче один стеэоверфлоу-программинг.
В общем, хорошая идея с MVVM и гибкостью контролов, но хреновая реализация самоего языка.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
Q>>Конвертер не нужен. Потому что ViewModel — это и есть конвертер на стероидах. Должна быть привязка к свойству во вью-модели того же типа, что требуется для GUI.
VD>Нет, это нарушает идеологию MVVM. VM-а не должна думать о форматировании данных или их визуальном представлении. В идеале VM-ка должна только содержать сами данные.
VM переводится как модель представления. Не представление модели.
VD>В идеале VM-ка должна только содержать сами данные.
Тогда это и будут данные. Просто ещё один слой модели. То, что скрывается за буквой M в аббревиатуре MVVM.
VD>Представь, что твой продукт должен быть локализован на десятки языков, а тебе нужно оттестировать ее. И вот ты возвращаешь из нее текст, а потом плюешься в тестах, так как он на разных языках разный.
Это вообще ортогонально ViewModel'у. Тестирование — это сверка ожидаемого/желаемого значения и фактического/наблюдаемого значения. Если ты при сверке рассчитываешь ожидаемые значения, передавая одни параметры (язык), и рассчитываешь фактические значения, передавая другие параметры — то кто ж тебе виноват? Не ViewModel же.
Q>>А уж внутри этого свойства мапь из низлежащих данных хоть императивно, хоть декларативно. На внешнем уровне всё останется декларативным.
VD>Грош цена такой декларативности.
А тут не декларативность нужна как терминальная цель, а чтоб было просто и удобно. Задавать отображение в обычном C#-коде — просто и удобно. Пропихивать через нетипизированные аргументы контекст в отдельный бойлерплейт-конвертер и запариваться с его инстанцированием в XAML — это не просто и не удобно. Не делайте так.
VD>Нет, возня с конвертерами это суровая действительность.
Сам себе её навязал, сам мучаешься.
VD>И сделано это в ВПФ крайне убого и неудобно.
Поэтому «возни с конвертерами» стоит избегать. Терпеть это ради эфемерного хз чего, ещё и защищать — ментальная ловушка.
Здравствуйте, Qbit86, Вы писали:
Q>VM переводится как модель представления. Не представление модели.
И что? По факту это все равно модель, и связь ее с представлением должна ограничиваться биндингом. Никакой логики представления в ней быть не должно.
Q>Тогда это и будут данные. Просто ещё один слой модели. То, что скрывается за буквой M в аббревиатуре MVVM.
Так это и есть еще один слой модели адаптирующий ее к отображению. Например, в модели у нас тупо список файлов, а в ВМке ее картинка, короткое имя...
Q>Это вообще ортогонально ViewModel'у. Тестирование — это сверка ожидаемого/желаемого значения и фактического/наблюдаемого значения. Если ты при сверке рассчитываешь ожидаемые значения, передавая одни параметры (язык), и рассчитываешь фактические значения, передавая другие параметры — то кто ж тебе виноват? Не ViewModel же.
Нет, это все задачи решаемые данным подходом. Если у тебя ВМка начинает содержать логику представления ты теряешь эти возможности и усложняешь переиспользование ВМки в других представлениях.
Конвертеры и расширения решают данную проблему. Вся логика представления остаётся в представлении. Проблема только в том, что конвертеры громоздки и синтаксис КЗАМ-ла убог.
Q>А тут не декларативность нужна как терминальная цель, а чтоб было просто и удобно. Задавать отображение в обычном C#-коде — просто и удобно. Пропихивать через нетипизированные аргументы контекст в отдельный бойлерплейт-конвертер и запариваться с его инстанцированием в XAML — это не просто и не удобно. Не делайте так.
Дык это проблема языков, а не подхода. КЗАМЛ — действительно говноязык. Динамика — масдай. Но тогда надо уже думать об отказе от КЗАМЛа, а не аргументировать его кривизной нарушение модели.
Да, наверно проще зафигачить в ВМку свойство типа UIElement.Visibility. Но это нарушает модель. Да кода будет меньше. Да он даже будет гибче. Но в ВМке у тебя будет логика представления, а не адаптация модели. Ты будешь оперировать понятием видимости на экране, а не понятиями предметной области.
Например, свойство в ВМке должно называться SomeDataFound и иметь тип bool, а его биндинг с видимостью некоторых элементов должен быть через конвертер, а не LayoutForSomeDataVisibility с типом UIElement.Visibility. Последнее приводит к смешиванию логики представлены и логики модели, что неминуемо приведет каше и усложнению разработки.
Q>Сам себе её навязал, сам мучаешься.
Ее навязывает неудачная реализация. Нет проблем сделать язык верстки достаточно гибгим и удобным. То что МС этого не сделал не проблема модели (подхода), а проблема реализации.
Да, КЗАМЛ в реальном применении читается чудовищно плохо. Да все эти конвертеры и многословность их применения приводит к раздуванию кода представлений. Но все равно разделение дает неоспоримо большие преимущества.
Ну, и уж если выбирать твой подход, стоит подумать о модели MVVVM, т.е. еще одного промежуточного уровня содержащего только логику представления (локализацию, конвертацию и т.п.), а в предыдущей ВМке держать именно логику модели адаптированной к отображению, т.е. того что и должно называться ВМ.
Q>Поэтому «возни с конвертерами» стоит избегать. Терпеть это ради эфемерного хз чего, ещё и защищать — ментальная ловушка.
Нет. По этому приходится это говно терпеть. От части помогает Райдер. Там не плохая типизация сделана. Но по уму нужно прикрутить качественный фрэнтэд в котором не будет ХМЛ-я, будет полноценная типизация, и необходимые языковые средства спасающие от недостатков ВПФ.
Как вариант создание нормальной верстальной технологии, которая бы позволяла вообще не читать КЗАМЛ, а верстать все в визивидьж-виде (дизайнерами). Но этот подход тоже в ВПФ полностью провален, так как тот что есть дико тормозит, а конвертеры и расширения и вовсе убивают его и в реальном приложении дизайнер на фиг отключают и трахаются с прямым редактированием КЗАМЛа.
По факту МС просто забил на ВПФ. Технология потихоньку дохнет.
Возможно на смену ему придет Брэйзер. Но там точно такие же проблемы и еще свои.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
VD>По факту это все равно модель, и связь ее с представлением должна ограничиваться биндингом.
Всё так, у тебя из ViewModel'а нет прямых ссылок на вьюшкины _button1'ы. Но она не то что должна ограничиваться биндингом. Она должна обслуживать этот биндинг. Это единственное назначение VM в MVVM. Никакой другой самостоятельной ценности или философии у этого архитектурного паттерна нет. Если в GUI-платформе нет движка привязок, то там будут MVC, MVP, Model-View-Whatever; но не MVVM. Его нужно применять так, чтобы чтобы было удобно использовать привязки. А жертвовать удобством привязок в пользу каких-то притянутых за уши требований — это misuse.
VD>Никакой логики представления в ней быть не должно.
Это противоречит общепринятому пониманию паттерна:
The view model of MVVM is a value converter,[1] meaning the view model is responsible for exposing (converting) the data objects from the model in such a way that objects are easily managed and presented. In this respect, the view model is more model than view, and handles most if not all of the view's display logic...
The view model is an abstraction of the view exposing public properties and commands.
— https://en.wikipedia.org/wiki/Model–view–viewmodel
VD>Так это и есть еще один слой модели адаптирующий ее к отображению. Например, в модели у нас тупо список файлов, а в ВМке ее картинка, короткое имя...
Да, ViewModel — это модель, только не модель модели. Это модель представления.
VD>Если у тебя ВМка начинает содержать логику представления...
VD>...усложняешь переиспользование ВМки в других представлениях.
А можно какой-нибудь нетривиальный пример переиспользования VM'ки? Подойдёт какая-нибудь библиотека классов с nuget.org, где предлагаются осмысленные вью-модели для повторного использования.
VD>Конвертеры и расширения решают данную проблему.
Какую-то выдуманную проблему «переиспользования вью-моделов»?
VD>Вся логика представления остаётся в представлении.
Так ты ж всё равно пишешь конвертеры в C# коде? Где на две строчки логики приходится десять строчек бойлерплейта и кастов?
VD>Да, наверно проще зафигачить в ВМку свойство типа UIElement.Visibility. Но это нарушает модель. Да кода будет меньше. Да он даже будет гибче. Но в ВМке у тебя будет логика представления, а не адаптация модели.
Именно логика представления и должна быть в VM'ке. Если использовать каноничный MVVM, а не чей-то вымышленный одноимённый паттерн.
VD>Ты будешь оперировать понятием видимости на экране, а не понятиями предметной области.
Кто-то же должен оперировать понятием видимости на экране?
VD>Например, свойство в ВМке должно называться SomeDataFound и иметь тип bool, а его биндинг с видимостью некоторых элементов должен быть через конвертер, а не LayoutForSomeDataVisibility с типом UIElement.Visibility. Последнее приводит к смешиванию логики представлены и логики модели, что неминуемо приведет каше и усложнению разработки.
Логика представления — в модели представления (ViewModel). Логика модели — в модели модели (Model). Вот и всё.
В применении к этому примеру. В VM'ке может быть «ссылка на модель», в данном случае backing field _someDataFound: bool (или не быть, если достаточно целевого типа). А для привязки публиковаться свойства целевого типа: SomeDataFoundVisibility: Visibility, SomeDataFoundColor: Color (серый, если не найден), etc. Геттеры этих свойств и будут конвертерами из модели в представление. Всё просто и плоско, и минимизирует количество синтаксического мусора в разметке.
VD>Но все равно разделение дает неоспоримо большие преимущества.
Пока насчитывается ровно ноль «неоспоримо больших преимуществ». Наоборот, вместо решения поставленных задач разработчик занят генерёжкой BooleanToVisibilityConverter'ов ради удовлетворения фантазий о воображаемом переиспользовании ViewModel'ов. А можно просто использовать ViewModel по его прямому назначению.
Глаза у меня добрые, но рубашка — смирительная!
Re: Связывание форм (GUI) с данными: императивно vs декларативно
Здравствуйте, Shmj, Вы писали:
S>Почему все верят, что декларативный подход рулит и на порядок упрощает работу?
Вера и религия не свойственна программистам!
Что то проще сделать декларативно, а что то программно.
В том же WPF Xaml можно применять как декларативный так и программный подход. https://metanit.com/sharp/wpf/11.php
В тех же Win Forms можно работать и через дизайнер и программно.
Все зависит от условий. И можно сочетать эти два подхода вместе
и солнце б утром не вставало, когда бы не было меня