Как я могу применить шаблон MVC к приложению C # WinForms?

11

Я разработчик C ++, который с тех пор использует шаблон MVC для разработки GUI.

Недавно я хотел вернуться в C # и настроить приложение Windows Forms, но теперь я немного растерялся, как перенести его в MVC-совместимую структуру.

В настоящее время я пытаюсь «объявить» класс, который мне дан для WinForms в качестве представления, и добавить класс для модели и контроллера в фоновом режиме. Тем не менее, я не совсем уверен, как взаимодействовать с событиями, такими как нажатие кнопки. Обычно я перенаправляю эти события на контроллер и выполняю действия в представлении после завершения.

Это кажется довольно неудовлетворительным в этом созвездии. Например, если бы я хотел реализовать кнопку «Выход», мне пришлось бы перенаправить событие из представления в контроллер, а также реализовать дополнительный открытый метод в моем представлении, который затем можно вызывать из контроллера, пока я может просто вызвать Close () из View в первом случае.

У вас есть какой-нибудь совет для меня? Мое понимание Windows Forms в C # просто недостаточно хорошо, чтобы попробовать реализацию MVC? Я даю классу форм неправильную роль? Является ли MVC просто неподходящей архитектурой для этого варианта использования?

Sossenbinder
источник
1
ОТ вопрос. Но почему WInforms? WPF предназначался для замены Winforms и поддерживает MVC (ну технически MVVM). Хотя я скажу, что кривая обучения WPF может быть крутой. (но если вы сделаете это плохо, вы можете сделать код WPF похожим на Winforms)
Peter M
1
@PeterM: потому что даже после 10 лет WPF отстой и все еще медленный.
whatsisname
3
Перефразируя комментарий @ whatsisname, WPF ориентирован на более крупные приложения. Меньшие приложения могут лучше обслуживаться с Winforms, потому что Winforms возможно проще. Однако, если вы хотите сделать этот аргумент, вы также можете сделать аргумент, что ваше приложение Winforms достаточно мало, где оно, вероятно, в любом случае не нуждается в MVP. MVVM запекается в WPF. WPF имеет векторную графику, поэтому он не испытывает тех же проблем с размерами, что и Winforms. WPF очень удобен для компоновки (вы можете легко помещать элементы управления в другие элементы управления), и он имеет более жесткую привязку данных. Что не нравится?
Роберт Харви
3
@whatsisname WPF может быть отстой, но он отстой намного меньше, чем Winforms для чего-либо, кроме игрушечной программы
Питер М
2
Для внутренних настольных программ я бы так сказал. Но многие компании предпочитают браузерные приложения для своих бизнес-операций просто потому, что установка не требуется.
Роберт Харви

Ответы:

3

По совпадению, я работаю над проектом WinForms, который создан по образцу MVC. Я бы не назвал это идеальным ответом, но я объясню мой общий дизайн, и, надеюсь, это поможет вам придумать свой собственный.

Судя по чтению, которое я сделал перед началом этого проекта, кажется, что нет «правильного» способа реализовать это. Я следовал простым принципам разработки ООП и MVC, а остальное было методом проб и ошибок при разработке рабочего процесса.

Является ли MVC просто неподходящей архитектурой для этого варианта использования?

Нет ..? В вашем вопросе недостаточно контекста, чтобы дать прямой ответ на этот вопрос. Почему вы используете MVC в первую очередь? Каковы нефункциональные требования вашего проекта? Ваш проект будет очень тяжелым для пользовательского интерфейса? Вы больше заботитесь о безопасности и предпочитаете многоуровневую архитектуру? Каковы основные компоненты вашего проекта? Возможно, каждому компоненту нужен свой шаблон проектирования. Узнайте, почему вы хотите использовать этот шаблон проектирования в первую очередь, и вы можете ответить на свой вопрос;)

Моя причина использования MVC: по моему мнению, это довольно простой шаблон проектирования, и мой дизайн в значительной степени основан на взаимодействии с пользователем. Способ, которым MVC позволяет разработчику разделять проблемы, достаточен и для моего приложения. Это делает мой код много более ремонтопригодны и проверяемым.

Я также предполагаю, что я использую больше гибридного дизайна. Как правило, идеальная концепция, представленная в программной инженерии, фактически не реализуется на практике. Вы можете изменить дизайн в соответствии с потребностями вашего проекта. Не нужно увлекаться тем, что правильно или неправильно. Существуют общие практики, но правила всегда можно согнуть или нарушить, если вы не стреляете себе в ногу.

Моя реализация началась с разработки высокого уровня, которая дала мне представление о том, какие компоненты мне понадобятся. Лучше всего начать с этого и продолжить свой путь в архитектуре. Вот схема пакета для проекта (созданного в StarUML): введите описание изображения здесь

Обратите внимание, что каждый отдельный уровень, кроме уровня представления, зависит от системы обмена сообщениями. Это общий «язык», который нижние уровни и подсистемы этих уровней используют для общения друг с другом. В моем случае это было простое перечисление, основанное на операциях, которые можно выполнить. Что подводит меня к следующему пункту ...

Думайте об операциях или командах как об основании вашей реализации. Что вы хотите, чтобы ваше приложение делало? Разбейте его на самые основные операции. Например: CreateProject, WriteNotes, SaveProject, LoadProject и т. Д. В GUI (или классах форм) произойдет какое-то событие (например, нажатие кнопки). С каждой операцией связан метод контроллера. В этом случае что-то вроде выхода слишком просто. Приложение может быть просто закрыто из класса Form. Но предположим, что я сначала хотел сохранить некоторые данные приложения в файле? Я вызову метод «Сохранить» из соответствующего класса контроллера в моем методе нажатия кнопки.

Оттуда контроллер будет вызывать правильный набор операций из классов Service. Классы обслуживания в моем приложении действуют как интерфейс для уровня домена. Они будут проверять ввод, полученный от вызова метода контроллера (и, следовательно, от GUI), и манипулировать моделью данных.

После завершения проверки и манипулирования соответствующим объектом метод службы вернет код сообщения контроллеру. Например, MessageCodes.SaveSuccess. И контроллер, и классы обслуживания были основаны на объектах домена и / или общем наборе операций, которые могут быть сгруппированы вместе.

Например: FileMenuController(операции: NewProject, SaveProject, LoadProject) -> ProjectServices(CreateProject, PersistProjectToFile, LoadProjectFromFile). Где Projectбудет класс домена в вашей модели данных. Классы Controller и Service в моем случае были неинстанцируемыми классами со статическими методами.

Затем контроллер распознает операцию как завершение un / успешно. Теперь у контроллера есть своя собственная система обмена сообщениями, которую он использует для взаимодействия с уровнем представления, следовательно, существует двойная зависимость между уровнями обслуживания и представления. В этом случае класс, вызываемый ViewStateв ViewModelsпакете, всегда возвращается в GUI контроллером. Это состояние содержит такую ​​информацию, как: « является ли состояние, которое вы пытались сделать приложением действительным? », « Удобочитаемое сообщение об операции, которую вы пытались выполнить, и почему она была или не удалась (сообщения об ошибках) » и ViewModelкласс.

ViewModelКласс содержит соответствующие данные из области слоя , что графический интерфейс будет использовать для обновления вида. Эти модели представлений выглядят как доменные классы, но в моем случае я использовал очень узкие объекты. По сути, они практически не работают, просто передают информацию о низкоуровневом состоянии приложения. Другими словами, я НИКОГДА не собираюсь отдавать свои доменные классы на уровень представления. Это также объясняет , почему Controllersи Servicesпакеты разделить слой услуг на две части. Контроллеры никогда не будут обрабатывать классы домена или проверять их состояние. Они просто действуют как граница, преобразующая данные, относящиеся к графическому интерфейсу, в данные, относящиеся к области, которые могут использовать службы, и наоборот. Включение служебной логики в контроллер приведет к очень жирной контроллеры, которые сложнее обслуживать.

Я надеюсь, что это дает вам отправную точку.

Соблазнительный топаз
источник