Рефакторинг К шаблону MVC - Сомнения на разделении представления от контроллера

Я пытаюсь осуществить рефакторинг свое приложение (с 1 000 + строки кода GUI) к шаблону стиля MVC. Логический код является уже отдельным от GUI так, чтобы не была проблема. Мое беспокойство является разделением представления от контроллера. Я понимаю основной принципал MVC, и это учебное руководство в wxpython Wiki было очень полезно, но пример кода немного упрощен и оставляет меня с сомнениями, когда я пытаюсь применить принципал к своему собственному проекту, который вполне немного более сложен.

Отрывок структуры..

У меня есть a MainWindow со многими виджетами включая a noteBook (раздел с вкладками), ноутбук имеет много вкладок одна из вкладок (который я называю FilterTab) содержит два экземпляра класса (что я называю a FilterPanel) это - панель с полем списка, тремя кнопками, один для очистки, один для удаления и один для добавления объектов к списку. В зависимости от флагов, переданных классу на инстанцировании, добавить событие кнопок может создать различные типы диалоговых окон, например, диалогового окна ввода текста или directoryPicker и т.д.

Это - всего одна часть GUI, который вполне разделен на уровни - с обработчиками событий, проложенными под землей в классе FilterPanel.

Если бы я должен был преобразовать ту часть в MVC, то я должен был бы связать события кнопки для каждого экземпляра FilterPanel в моем контроллере (вместо в filterPanel классе) - в этом случае существует два (filterPanel экземпляры)

Таким образом, у меня было бы что-то вроде этого для каждой кнопки, (3 кнопки на filterPanel * количество экземпляров панели) плюс обработчики..

 self.mainWindow.filterTab.dirFilterPnl.Bind(wx.EVT_BUTTON,
                                    self.onAdd_dirFilterPnl, 
                            self.mainWindow.filterTab.dirFilterPnl.addBtn,
                            self.mainWindow.filterTab.dirFilterPnl.addBtn.GetId()
                                    )

Который добавляет много дополнительного кода, (удвойте сумму обработчиков событий, если у меня есть только два filterPanel экземпляра),

Таким образом, я хотел бы знать, что я проявляю правильный подход?

6
задан volting 4 October 2014 в 16:07
поделиться

2 ответа

Если бы я преобразовал эту часть в MVC Мне бы пришлось привязать события кнопки для каждого экземпляра FilterPanel в моем контроллере (вместо filterPanel class)

Не обязательно! Философия и практика MVC не подразумевают, что «представления» являются элементарными виджетами; вашу FilterPanel можно было бы представить / реализовать как «расширенный / составной» виджет, который генерирует свои собственные высокоуровневые «события» (направленные на контроллер) и обновляется соответствующим образом. Таким образом, этот составной виджет может иметь обработчики для «событий» более низкого уровня и синтезировать из них события более высокого уровня, отправляя их контроллеру; контроллеру не нужно знать или заботиться о каждой кнопке и т. д., только о событиях более высокой абстракции, которые он получает, например, «пользователь хочет выбрать каталог для цели X» или «пользователь хочет ввести текст для цели Y» - и ответьте им, сказав представлению, что делать.

Ключевым моментом является то, что представление не принимает «семантических» решений, основанных на событиях, которые оно обрабатывает, и никогда не отправляет никаких команд модели - контроллер является незаменимым «посредником» для всех таких взаимодействий.

Для аналогии рассмотрим, что на самом нижнем уровне графического интерфейса есть события очень низкого уровня, такие как «левая кнопка мыши вниз» и «левая кнопка мыши вверху» - «виджет кнопки» реагирует непосредственно на них, изменяя параметры кнопки. внешний вид («визуальное» решение, а не «стратегическое») и, в конечном итоге, если и когда это необходимо, синтез события более высокой абстракции, такого как «нажата кнопка» (когда за нажатой кнопкой мыши следует кнопка мыши вверх без промежуточные движения мыши, опровергающие гипотезу "щелчка", например). Последний затем направляется на любой более высокий уровень, который должен «реагировать» на нажатия кнопок.

Точно так же ваши многофункциональные / составные виджеты могут принимать такие события и синтезировать те, которые имеют более высокую абстракцию, для реакции контроллера. (То же самое абстрактное событие может быть сгенерировано нажатием кнопки, выбором меню, определенными нажатиями клавиш ... контроллер не заботится об этих «визуальных» соображениях нижнего уровня, а именно о задании представления / виджета и представления / виджета не жестко кодирует «стратегические» решения и действия для такого взаимодействия с пользователем, это работа контроллера).

Разделение задач помогает решить такие вопросы, как тестирование и гибкость приложений; Ничего удивительного, что такие преимущества можно купить по цене наличия большего количества кода по сравнению с альтернативой, в которой все жестко запрограммировано ... но если вы выбираете MVC, вы подразумеваете, что цена для вас стоит того.

wx может быть не идеальной структурой для реализации этого, но вы можете создать подкласс wx.Событие - или вы можете использовать отдельную систему событий, такую ​​как pydispatcher , для событий более высокой абстракции, которые проходят между отдельными подсистемами, чтобы отделить контроллер от конкретного выбора среды графического интерфейса пользователя. Обычно я использую Qt, чья модель сигналов / слотов, IMNSHO, расширяет / масштабируется лучше, чем системы событий типичных графических интерфейсов. Но это другой выбор и другой вопрос.

9
ответ дан 10 December 2019 в 00:31
поделиться

wxPython включает pubsub, который следует методологии публикации / подписки. Он похож на pydispatcher, хотя их реализации различаются. В вики wxPython есть несколько примеров использования pubsub в вашей программе, а также это простое руководство по этой теме:

http://www.blog.pythonlibrary.org/2010/06/27/wxpython-and- pubsub-a-simple-tutorial /

MVC в графическом интерфейсе пользователя не совсем такой же, как в Django или TurboGears. Я обнаружил, что могу поместить большую часть своей логики в контроллеры, а в моем «представлении» я просто привязываюсь к контроллеру. Примерно так:

view.py

btn.Bind (wx.EVT_BUTTON, self.onButton)

def onButton (self, event): controller.someMethod (* args, ** kwargs)

В зависимости от вычислений я могу запустить поток с моего контроллера и опубликовать результат позже, используя wx.CallAfter + pubsub.

1
ответ дан 10 December 2019 в 00:31
поделиться
Другие вопросы по тегам:

Похожие вопросы: