Управление логикой помощника (wizard-а)
От: es3000  
Дата: 17.05.19 15:16
Оценка:
Часто в программах используют "Помощники" (wizard-ы).
Это несколько последовательно отображаемых пользователю окон, в которых он что-то вводит.
Последовательность окон может быть разная в зависимости от того, что вводит пользователь.
И управляется эта последовательность программой.

Хочется сделать "правильную" архитектуру для реализации такого Помощника.
С выделением классов: Представление, Контроллер, Модель, Презентатор в соответствии с "хорошими" принципами разработки ПО: типа CleanArchitecture, Domain-driven design и др.

Реализовывать планируется на WinForms C#.

С первого взгляда кажется, что для управления логикой и последовательностью отображения окон для пользователя, надо сделать какой-то отдельный объект-Контроллер.
Правильно?

Что думаете?
Подскажите пожалуйста?
Re: Управление логикой помощника (wizard-а)
От: es3000  
Дата: 17.05.19 15:27
Оценка:
E>С первого взгляда кажется, что для управления логикой и последовательностью отображения окон для пользователя, надо сделать какой-то отдельный объект-Контроллер.

Получается, что эта логика — она должна быть независима от конкретной реализации отображаемых окон.
И ее можно выделить даже в отдельный слой.

В книгах по архитектурам иногда кроме слоев Business-Layer и UI-Layer, также указывают Application-Layer.
Может быть эта логика, управляющая отображением окон Помощника, и есть часть Application Layer?
Re: Управление логикой помощника (wizard-а)
От: qaz77  
Дата: 17.05.19 15:27
Оценка:
Здравствуйте, es3000, Вы писали:

E>Часто в программах используют "Помощники" (wizard-ы).

E>Это несколько последовательно отображаемых пользователю окон, в которых он что-то вводит.
E>Последовательность окон может быть разная в зависимости от того, что вводит пользователь.
E>И управляется эта последовательность программой.

E>Хочется сделать "правильную" архитектуру для реализации такого Помощника.

E>С выделением классов: Представление, Контроллер, Модель, Презентатор в соответствии с "хорошими" принципами разработки ПО: типа CleanArchitecture, Domain-driven design и др.

Пользователь такой системы кто?
Кто-то будет делать по 10 новых проектов на дню с "чистой" архитектурой?
Меня даже относительно неплохой wizard в Visual Studio выбешивает.
Re[2]: Управление логикой помощника (wizard-а)
От: es3000  
Дата: 17.05.19 15:44
Оценка:
Q>Пользователь такой системы кто?

В смысле кто? Обычный человек.

Q>Кто-то будет делать по 10 новых проектов на дню с "чистой" архитектурой?


Зачем по 10 проектов?
В одном проекте можно же по разному реализовать какую-то функциональность.
В данном случае одну из функций приложения можно реализовать в виде Помощника.

Q>Меня даже относительно неплохой wizard в Visual Studio выбешивает.


Это да, "продвинутые" пользователи не очень любят wizard-ы.
Но насколько я знаю, те кто мало дружат с ПК — им Помощники нравятся.
Re[3]: Управление логикой помощника (wizard-а)
От: qaz77  
Дата: 17.05.19 16:51
Оценка:
Здравствуйте, es3000, Вы писали:


Q>>Пользователь такой системы кто?


E>В смысле кто? Обычный человек.


Q>>Кто-то будет делать по 10 новых проектов на дню с "чистой" архитектурой?


E>Зачем по 10 проектов?

E>В одном проекте можно же по разному реализовать какую-то функциональность.
E>В данном случае одну из функций приложения можно реализовать в виде Помощника.

А, я понял, что затевается.
Вроде мастера каких-то там отчетов, определяемых пользователем программного продукта.
Тут определение отчета — это модель. А что тут контроллер и представдение — хз.
Если мастер — это цепочка модальных диалогов в классике жанра,то имхо не надо заморачиваться с MVC.

Недавно делал визард подключения к бд со всякими извращениями вроде upgrade версии бд и т.п.
Имхо тут лучше подходит конечный автомат (ака FSM), а не MVC.

В подобной задаче могу себе представить MVC только как "конструктор запросов" для построения отчета с квадратиками условий, как в MS Access.
Конечному пользователю все равно это очень больно будет...
Re: Управление логикой помощника (wizard-а)
От: Kolesiki  
Дата: 17.05.19 20:43
Оценка:
Здравствуйте, es3000, Вы писали:

E>Хочется сделать "правильную" архитектуру для реализации такого Помощника.

E>Что думаете?

Думаю, что с таким подходом, где у тебя "всё правильно", ты никогда ничего не напишешь. Упираться лбом в теорию можно бесконечно, но финальный код всё равно будет на костылях и изоленте вперемешку с хардкодом. Особенно, если отталкиваешься от "теории", ни черта не имея в "практике". Поучись писать хотя бы "плохие" программы — там увидишь, где можно писать "красиво", а где теория только мешает.
Re: Управление логикой помощника (wizard-а)
От: MozgC США http://nightcoder.livejournal.com
Дата: 17.05.19 20:51
Оценка: +1
На мой взгляд использование MV* в WinForms — это натягивание совы на глобус. Если хотите попробовать современные паттерны разработки desktop GUI — попробуйте WPF & MVVM.
Ну и вообще, не слишком увлекайтесь "правильными" паттернами разработки. Очень много из того что нам "продают" на практике не особо используется или не особо удобно. Имхо, главным критерием должна быть понятность и легкость работы с кодом для других разработчиков. Покажите свой код другому разработчику — и если он скажет что все понятно и работать с таким дизайном (кода) удобно — это самое главное, и не надо париться, что вы не используете MV* или ещё что-то "модное".
Re[2]: Управление логикой помощника (wizard-а)
От: es3000  
Дата: 18.05.19 11:18
Оценка:
MC>На мой взгляд использование MV* в WinForms — это натягивание совы на глобус. Если хотите попробовать современные паттерны разработки desktop GUI — попробуйте WPF & MVVM.

Я нигде не писал, что собираюсь использовать MVC.
Можно использовать и MVVM.

MC>Имхо, главным критерием должна быть понятность и легкость работы с кодом для других разработчиков. Покажите свой код другому разработчику — и если он скажет что все понятно и работать с таким дизайном (кода) удобно — это самое главное, и не надо париться, что вы не используете MV* или ещё что-то "модное".


А разве эти архитектуры не учат писать понятный и легкий код?
Re: Управление логикой помощника (wizard-а)
От: Буравчик Россия  
Дата: 19.05.19 17:14
Оценка: +1
Здравствуйте, es3000, Вы писали:

E>Часто в программах используют "Помощники" (wizard-ы).

E>Это несколько последовательно отображаемых пользователю окон, в которых он что-то вводит.

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

E>Последовательность окон может быть разная в зависимости от того, что вводит пользователь.


Т.к. последовательность сложная вынеси управление в отдельный класс WizardFlow.
Этот класс WizardFlow должен сообщать, какую страницу вывести при нажатии "вперед" и "назад".
При нажатии кнопки, обращайся к WizardFlow, и выводи соответствующую страницу (которую он укажет)

Логику для определения следующей/предыдущей страницы напишешь любую.
Но класс WizardFlow должен знать о некоторых "важных событиях", например, "пользователь выбрал такой-то ответ на такой странице".
Нужно классу WizardFlow сообщать о таких событиях.
Best regards, Буравчик
Re[3]: Управление логикой помощника (wizard-а)
От: qaz77  
Дата: 20.05.19 07:28
Оценка:
Здравствуйте, es3000, Вы писали:
E>А разве эти архитектуры не учат писать понятный и легкий код?

Нет архитектура — это не про написание кода.
Различные паттерны типа MVC — это способ разделить обязанности между классами.
Декомпозиция задачи на подзадачи на верхнем уровне абстакции.
Написание красивого и понятного кода также имеет отношение к декомпозиции, но на самом нижнем уровне.
Например, выделить похожий код в функцию-помощник, дать понятные имена переменным, не писать функции на сотни строки и т.п.
Re: Управление логикой помощника (wizard-а)
От: ylem  
Дата: 20.05.19 07:39
Оценка:
Если нужен mvvm с байндингами, типа как в WPF, но нужно в WinForms, есть вот такая штука.
https://archive.codeplex.com/?p=truss
В простых случаях работает. В сложных не пробовал, но вроде как лаконично пишутся 'свои' байндинги.
Re[2]: Управление логикой помощника (wizard-а)
От: es3000  
Дата: 20.05.19 07:39
Оценка:
Б>Т.к. последовательность сложная вынеси управление в отдельный класс WizardFlow.

Я тоже об этом думал.

Б>Этот класс WizardFlow должен сообщать, какую страницу вывести при нажатии "вперед" и "назад".

Б>При нажатии кнопки, обращайся к WizardFlow, и выводи соответствующую страницу (которую он укажет)

Б>Логику для определения следующей/предыдущей страницы напишешь любую.

Б>Но класс WizardFlow должен знать о некоторых "важных событиях", например, "пользователь выбрал такой-то ответ на такой странице".
Б>Нужно классу WizardFlow сообщать о таких событиях.

Каким "компонентом" можно считать этот класс WizardFlow?
Это получается Презентатор?
Re[2]: Управление логикой помощника (wizard-а)
От: es3000  
Дата: 20.05.19 07:42
Оценка:
Y>Если нужен mvvm с байндингами, типа как в WPF, но нужно в WinForms, есть вот такая штука.
Y>https://archive.codeplex.com/?p=truss
Y>В простых случаях работает. В сложных не пробовал, но вроде как лаконично пишутся 'свои' байндинги.

Спасибо! Посмотрю.

Но вопрос у меня был немного в другом.
Меня больше интересует архитектурное решение.
Re[2]: Управление логикой помощника (wizard-а)
От: qaz77  
Дата: 20.05.19 07:48
Оценка: 3 (1)
Здравствуйте, Буравчик, Вы писали:
Б>Т.к. последовательность сложная вынеси управление в отдельный класс WizardFlow.
Б>Этот класс WizardFlow должен сообщать, какую страницу вывести при нажатии "вперед" и "назад".
Б>При нажатии кнопки, обращайся к WizardFlow, и выводи соответствующую страницу (которую он укажет)

Б>Логику для определения следующей/предыдущей страницы напишешь любую.

Б>Но класс WizardFlow должен знать о некоторых "важных событиях", например, "пользователь выбрал такой-то ответ на такой странице".
Б>Нужно классу WizardFlow сообщать о таких событиях.

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

При большом количестве страниц и ветвлений трудности будут с реализацией класса WizardFlow.
Запрограммировать его правильно в процедурном стиле на if-ах и switch-ах вызовет сложности.

Например, вот такая схема работы визарда у меня была в недавней задаче:


Каждому состоянию визарда я сопоставил класс WizardState, содержащий логику переходов в следующее и предыдущее состояние.
Объекты класса WizardState константные и существуют в единственном экземпляре (singleton).

Класс WizardFlow получился простым, менее 100 строк кода.
Он работает по принципу конечного автомата, каждый момент имея один текущий WizardState.
У него всего три операции:
Re[3]: Управление логикой помощника (wizard-а)
От: es3000  
Дата: 20.05.19 08:22
Оценка:
Q>Класс WizardFlow получился простым, менее 100 строк кода.
Q>...

А если перевести это в терминологию "чистой архитектуры", то что в это реализации будет являться Представлением, Презентатором, контроллером, Интерактором?
Re[3]: Управление логикой помощника (wizard-а)
От: Буравчик Россия  
Дата: 20.05.19 08:37
Оценка:
Здравствуйте, es3000, Вы писали:

E>Каким "компонентом" можно считать этот класс WizardFlow?

E>Это получается Презентатор?

Да, это часть презентера.
Best regards, Буравчик
Re[4]: Управление логикой помощника (wizard-а)
От: qaz77  
Дата: 20.05.19 08:50
Оценка: +1
Здравствуйте, es3000, Вы писали:

E>А если перевести это в терминологию "чистой архитектуры", то что в это реализации будет являться Представлением, Презентатором, контроллером, Интерактором?


Все это очень смахивает на натягивание совы на глобус...

Если очень грубо, то WizardFlow более похож на контроллер или презентатор.
Представление тут диалоговое окно мастера со всеми его страницами и контролами.
В моем случае использовался объект WizardData, который определенно можно рассматривать как модель.

С другой стороны, у меня не использовались архитектурные ограничения, характерные для MVC или MVP.
Так код страниц визарда (т.е. Представления) напрямую писал изменения в WizаrdData (т.е. модель).
Объект WizardFlow контролировал только один аспект поведения — переходы между страницами, но никак не использовался для внутренней логики работы каждой конкретной страницы.
Наверное, я просто не делал слишком сложные страницы, чтобы их логику мне захотелось выделить в какой-то отдельный класс.
Re[5]: Управление логикой помощника (wizard-а)
От: Буравчик Россия  
Дата: 20.05.19 10:04
Оценка:
Здравствуйте, qaz77, Вы писали:

Q>Все это очень смахивает на натягивание совы на глобус...


Да нет. Это и есть MVP, которое так сильно ищет es3000

Q>Если очень грубо, то WizardFlow более похож на контроллер или презентатор.

Q>Представление тут диалоговое окно мастера со всеми его страницами и контролами.
Q>В моем случае использовался объект WizardData, который определенно можно рассматривать как модель.

model — WizardData
presenter — код формы визарда, часть этого кода вынесена в отдельный класс WizardFlow
view — дочерние страницы визарда

Q>С другой стороны, у меня не использовались архитектурные ограничения, характерные для MVC или MVP.

Q>Так код страниц визарда (т.е. Представления) напрямую писал изменения в WizаrdData (т.е. модель).

Да, по-хорошему отдельные страницы визарда должны отправить нужные сообщения, а код диалогового окна должен изменить WizаrdData.
Но это как раз пример частого упрощения применения теории для удобства работы.
Такое упрощение может аукнуться, а может и нет (зависит от объема кода)
Best regards, Буравчик
Re[6]: Управление логикой помощника (wizard-а)
От: es3000  
Дата: 20.05.19 10:29
Оценка:
Б>Да нет. Это и есть MVP, которое так сильно ищет es3000

Да нет, я не ищу именно MVP.

Я ищу способ написать "хороший", поддерживаемый, расширяемый код.
Чтобы в нем разные зоны "ответственности" были разделены.
В этом есть здравая идея.

Но на практике сталкиваешься с тем, что разделить-то толком и не получается.
Все равно получается (хоть "чистая архитектура", хоть MVP, хоть MVVP), что все друг на друга "завязано".

Смысл разделения в чем?
В том, чтобы при изменении одной части кода, не приходилось менять другую часть кода.
Например, представьте тот же Wizard.
Мы хотим отвязать логику отображения последовательности форм от конкретных форм-представлений.
Например, чтобы иметь возможность позже сделать формы красивее.
И получается, что мы не можем этого сделать!
Так как логика отображения форм заложена в Презентере, а Презентер жестко завязан на формы.
Как их отвязать?
Отредактировано 20.05.2019 10:31 es3000 . Предыдущая версия .
Re[7]: Управление логикой помощника (wizard-а)
От: qaz77  
Дата: 20.05.19 11:06
Оценка: +1
Здравствуйте, es3000, Вы писали:
E>Да нет, я не ищу именно MVP.

E>Я ищу способ написать "хороший", поддерживаемый, расширяемый код.

E>Чтобы в нем разные зоны "ответственности" были разделены.
E>В этом есть здравая идея.

Все правильно. И изучать имеющиеся подходы также надо.
Но умение правильно расставлять приоритеты и искать компромиссы приходит с опытом...

E>Но на практике сталкиваешься с тем, что разделить-то толком и не получается.

E>Все равно получается (хоть "чистая архитектура", хоть MVP, хоть MVVP), что все друг на друга "завязано".

Чтобы что-то работало совместно, оно должно быть внутри как-то завязано.
Обычно, когда говорят про отсутствие зависимости или слабую зависимость, то имеют в виду зависимость от конкретной реализации объекта-контрагента.
Т.е. для нас объект выполняет какую-то роль, на которую мы можем полагаться.
Обычно такая роль оформляется в виде абстрактного интерфейса, операции которого наделены определенными ожиданиями (семантикой).

Допустим, я прихожу в супермаркет, беру бутылку молока и иду с ней на кассу.
Мне не важно, кто сидит за кассой, тетя Маша или тетя Люба.
Я протягиваю бутылку молока, вызывая операцию "пробить товар" у абстрактного интерфейса "кассир" и ожидаю продолжения протокола взаимодействия (прием оплаты и т.д.).
Нарушением семантики операции в данном случае, например, будет, если кассирша вместо положенного, откупорит бутылку и выпьет молоко.
Все объекты тут те же (содержание диаграммы классов тождественное), а разница поведения очевидна.
Когда говорят о минимизации зависимостей, то подразумевают, что нам не важно какой именно человек сидит за кассой, лишь бы он делал то, что положено интерфейсу "кассир".
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.