, мы создали приложение:
Presenter отбражает результаты работы счётного части (Model) на несколько форм(Views).
Скажем, три формы (View1,View2,View3) с разными графиками, один Presenter, одна Model.
Вопрос: чем должны являться модальные диалоги (10 штук), задающие параметры алгоритма ?
Делать их все View вроде не стоит логически, и накладно физически, т.к. для каждый View
реализует своё интерфейс IView.
С другой стороны, результат их ввода нужен Presenter'у: он забирает результат и сохраняет его в модели.
Можно, конечно, интерфейс диалогов реализовать в интерфейсах одного или нескольких View, с тем, чтобы они просто переадресовали запросы нужным диалогам. Т.е. для Presenter'a этих диалогов не существует — он видит только интерфейсы View1,2,3.
В сомнениях. Поделитесь опытом.
, мы создали приложение: А>Presenter отбражает результаты работы счётного части (Model) на несколько форм(Views). А>Скажем, три формы (View1,View2,View3) с разными графиками, один Presenter, одна Model. А>Вопрос: чем должны являться модальные диалоги (10 штук), задающие параметры алгоритма ?
модальные диалоги — вроде плохой тон в юзабилити...
А>Делать их все View вроде не стоит логически, и накладно физически, т.к. для каждый View А>реализует своё интерфейс IView.
а нельзя для всех диалогов один интерфейс, он ведь единообразно с данными работает, а для данных — базовый объект модели с наследниками для разных наборов параметров
А>С другой стороны, результат их ввода нужен Presenter'у: он забирает результат и сохраняет его в модели.
А>Можно, конечно, интерфейс диалогов реализовать в интерфейсах одного или нескольких View, с тем, чтобы они просто переадресовали запросы нужным диалогам. Т.е. для Presenter'a этих диалогов не существует — он видит только интерфейсы View1,2,3.
, мы создали приложение: А>Presenter отбражает результаты работы счётного части (Model) на несколько форм(Views). А>Скажем, три формы (View1,View2,View3) с разными графиками, один Presenter, одна Model. А>Вопрос: чем должны являться модальные диалоги (10 штук), задающие параметры алгоритма ?
А>Делать их все View вроде не стоит логически, и накладно физически, т.к. для каждый View А>реализует своё интерфейс IView.
А>С другой стороны, результат их ввода нужен Presenter'у: он забирает результат и сохраняет его в модели.
А>Можно, конечно, интерфейс диалогов реализовать в интерфейсах одного или нескольких View, с тем, чтобы они просто переадресовали запросы нужным диалогам. Т.е. для Presenter'a этих диалогов не существует — он видит только интерфейсы View1,2,3. А>В сомнениях. Поделитесь опытом.
Диалог останется диалогом, но на нем должен выводиться соответствующий контент т.е. реализация View, а Presenter отвечает только за формирование данных для отображения и не нужно его путать с контроллером ...
Здравствуйте, kejroot, Вы писали: K>модальные диалоги — вроде плохой тон в юзабилити...
Меня интересует архитектура ModelViewPresenter и ModelViewController применительно к повсеместно используемым модальным и немодальным диалогам, а не хорошие манеры в юзабилити.
K>а нельзя для всех диалогов один интерфейс, он ведь единообразно с данными работает, K>а для данных — базовый объект модели с наследниками для разных наборов параметров
Не понял. Из одного диалога забираем список выделенных каналов, из другого — расчитанный вектор времени, из третьего — праметры хитровы@@аного интегрального преобразования, на четвёртом прогрессбар развлекает пользователя и т.д. — разброд, шатание и никаких общих интерфесов
Как это подать в Presenter, чтобы быстро и по науке ?
Здравствуйте, shvonder, Вы писали:
S>Здравствуйте, kejroot, Вы писали: K>>модальные диалоги — вроде плохой тон в юзабилити... S>Меня интересует архитектура ModelViewPresenter и ModelViewController применительно к повсеместно используемым модальным и немодальным диалогам, а не хорошие манеры в юзабилити.
ка хотице..
K>>а нельзя для всех диалогов один интерфейс, он ведь единообразно с данными работает, K>>а для данных — базовый объект модели с наследниками для разных наборов параметров
S> Не понял. Из одного диалога забираем список выделенных каналов, из другого — расчитанный вектор времени, из третьего — праметры хитровы@@аного интегрального преобразования, на четвёртом прогрессбар развлекает пользователя и т.д. — разброд, шатание и никаких общих интерфесов
ну значт пустой интерфейс общий он же базовый! главное, что он используется в общем интерфейсе диалога!
S>Как это подать в Presenter, чтобы быстро и по науке ?
я не знаю.
Основательно..
S>Диалог останется диалогом, но на нем должен выводиться соответствующий контент т.е. реализация S>View, а Presenter отвечает только за формирование данных для отображения и не нужно его путать с S>контроллером ...
Я и стараюсь не путать.
По моим представлениям (далее цитата ) контроллер в ModelViewController
отвечал за события, пришедшие не с гуя, в отличие от современных библиотек, где View есть источник событий — всякие клики на форме и проч. Отсюда преврашение ModelViewController в DocunentView, где
Document = View + Controller.
А в ModelViewPresenter из гуя вынесли по-возможности всю логику, и перенесли в Presenter. Т.е. Presenter, реагируя на событие гуя(View), забирает данные из него, передаёт в счётное ядро(Model),
забирает результат, обрабатывает его нужным образом, и передаёт в примитивный интерфейс гуя для прорисовки. Т.е. именно Presenter и является контроллером, а гуй(View) — придаток с простым интерфейсом, и по этой причине его легче заменять.
Что касается диалогов: согласитесь, ставить рядом, например, сложную рисовалку карт и диалог
с одной кнопкой выбора цвета — странно. Тем более, если диалогов много, они часто меняются, но
взаимодействуют с Presenter'ом через абстрактный интерфейс, который нужно подерживать.
А ссылки щас начну листать.
Здравствуйте, Stormblast, Вы писали:
S>Диалог останется диалогом, но на нем должен выводиться соответствующий контент т.е. реализация S>View, а Presenter отвечает только за формирование данных для отображения и не нужно его путать с S>контроллером ...
С этим, кстати, абсолютно согласен — диалог отображает состояние модели. Но как же не хочется его
делать отдельным View: интерфейс писать, реализацию интерфейса, создавать его где-то, регистрировать View<-->Presenter в друг друге, а потом ещё и управлять из Presenter'a: аля
IMyFamouseDlg10->ShowModal(). И всё через абстрактный интерфейс протаскивать. И ни боже мой не удалять из проекта — иначе убивать всё обратно..
Здравствуйте, shvonder, Вы писали:
S> Что касается диалогов: согласитесь, ставить рядом, например, сложную рисовалку карт и диалог S>с одной кнопкой выбора цвета — странно. Тем более, если диалогов много, они часто меняются, но S>взаимодействуют с Presenter'ом через абстрактный интерфейс, который нужно подерживать. S> А ссылки щас начну листать.
Если можна с этого места подробней, какая разница Presenter'у: это сложный диалог рисовалки или простенький диалог выбора цвета ?
Вообщем предлагаю тебе следующую схему:
есть Model которую слушает View в случае изменения модели View запрашивает новый Presenter который служит input-ом для данной View ...
S>Вообщем предлагаю тебе следующую схему: S>есть Model которую слушает View в случае изменения модели View запрашивает новый Presenter который служит input-ом для данной View ...
S>упрощенно: S>changeModel(...) S>{ S> if(...){ view->>setInput(...->getPresenter()); S> } S>}
да забыл добавить:
после того как во View были внесены какие то данные то после сохранения они попадают сразу в модель естественно в данной схеме минуя Presenter, что вызовет событие обновление модели и т.д. ...
Здравствуйте, Stormblast, Вы писали:
S>Здравствуйте, Stormblast, Вы писали:
S>>Вообщем предлагаю тебе следующую схему: S>>есть Model которую слушает View в случае изменения модели View запрашивает новый Presenter который служит input-ом для данной View ... S>.. S>да забыл добавить: S>после того как во View были внесены какие то данные то после сохранения они попадают сразу в модель естественно в данной схеме минуя Presenter, что вызовет событие обновление модели и т.д. ...
Я имею ввиду другой подход: когда логика полностью вынесена из View.
У тебя View сам запрашивает данные по событию от модели, сам отрисовывается по своей логике. Решили заменить View — нужно заново переписать всю логику рисования в новом View ( зато уж отрисовка будет оптимальной — View прекрасно знает, как себя лучше рисовать).
Я говорю о другом подходе: View реализует абстрактный интерфейс IView. Операции этого интерфейса
вызываются в Presenter'e. Хорошо то, что замена View никак не сказывается на логике рисования. Как вызывал Presenter абстрактные операции, скажем ICurveView,так и будет вызывать:
То что реализация ICurveView* поменялась, он не в курсе. Смущает трудоёмкость:
все операции нужно протаскивать через интерфейс ICurveView. Если и диалоги тем же манером — просто вешалка . И никакой, понимаешь, личной жизни
Здравствуйте, Stormblast, Вы писали:
S>что бы получить новый(измененный) Presenter.
А бывает такое, что вы более многословны?
Насколько понял по написанному выше, модель у вас оповещает представление об изменении, по данному событию представление вытаскивает данные из предъявителя, пока правильно или нет?
Здравствуйте, rsn81, Вы писали:
R>Здравствуйте, Stormblast, Вы писали:
S>>что бы получить новый(измененный) Presenter. R>А бывает такое, что вы более многословны? R>Насколько понял по написанному выше, модель у вас оповещает представление об изменении, по данному событию представление вытаскивает данные из предъявителя, пока правильно или нет?
да ... есть некий Builder который отдает Presenter ...
Здравствуйте, Stormblast, Вы писали:
S>Здравствуйте, rsn81, Вы писали:
R>>Здравствуйте, Stormblast, Вы писали:
S>>>что бы получить новый(измененный) Presenter. R>>А бывает такое, что вы более многословны? R>>Насколько понял по написанному выше, модель у вас оповещает представление об изменении, по данному событию представление вытаскивает данные из предъявителя, пока правильно или нет?
S>да ... есть некий Builder который отдает Presenter ...
Господа, ну не уклоняйтесь в сторону. Имеем модель неактивного Presenter'а, который ничего сам не делает, а только реализует интерфейс. Стоит ли для каждого диалога делать интерфейс, чтобы постредством него Presenter манипулировал ими наравне с остальными Presenter'ами ?
S>постредством него Presenter манипулировал ими наравне с остальными Presenter'ами ?
ошибся, читать так:
"постредством него Presenter манипулировал ими наравне с остальными View'ами ?"
Здравствуйте, Stormblast, Вы писали:
R>>Насколько понял по написанному выше, модель у вас оповещает представление об изменении, по данному событию представление вытаскивает данные из предъявителя, пока правильно или нет? S>да ... есть некий Builder который отдает Presenter ...
Идем дальше. Представление определенным образом инициирует действия над моделью, которые отрабатывает предъявитель. Так зачем активная модель, если всеми манипуляциями над моделью занимается предъявитель, ведь после завершения своих действий он сам может оповестить представление?
Потому и говорю, что у вас явный MVC. В MVP модель и представление никоим образом не связаны, даже по Observer — попросту незачем. См., к примеру, здесь: Отличия от MVC
— на приведенном там рисунке в вашем случае нужно нарисовать еще одну связь между представлением и моделью. См. там же рассмотрение гибридов MVC, возможно, у вас что-то вроде Supervising Controller, но вовсе не MVP.
Здравствуйте, rsn81, Вы писали:
Боясь быть назойливым, переспрашиваю:
Имеем модель неактивного Presenter'а, который ничего сам не делает, а только реализует интерфейс. Стоит ли для каждого диалога делать интерфейс, чтобы постредством него Presenter манипулировал ими наравне с остальными View'ами ?
Спасибо.
? Если так, то ничего не посоветую: не разделяю взгляд автора на MVP, точнее просто придерживаюсь другого, который мне кажется несколько проще. У меня предъявитель и представления связаны прямо по Command, а в обратную сторону по Observer, то есть представление реализует интерфейс оповещения, в принципе, некоторая аналогия с вашим вариантом есть, но не берусь судить.
S>модель неактивного Presenter'а
Это пять!
Что за чудо-юдо-то такое?
S>Стоит ли для каждого диалога делать интерфейс, чтобы постредством него Presenter манипулировал ими наравне с остальными View'ами ?
Да, стоит. Чем диалог не представление-то? Ответьте сами себе на такой простой вопрос: если данные модели изменяться уже после открытия диалога, то есть представления, которое ее отображает, должен ли на это как-то среагировать диалог, к примеру, обновиться, показав актуальные данные или продолжать казать дела минувших дней? Или такой: пользователь через диалог изменяет данные, должны ли оно (это изменение) мгновенно (или даже вообще просто после закрытия диалога) отобразиться где-то в экранной форме? В зависимости от ответа на этот вопрос и решайте.
Здравствуйте, rsn81, Вы писали:
R>Здравствуйте, shvonder, Вы писали: S>>модель неактивного Presenter'а R>Это пять! R>Что за чудо-юдо-то такое?
Очепятка. Читать — пассивный Viewer. Пассивный, активный, так и просится на язык нетехнический термин
R>Или такой: пользователь через диалог изменяет данные, должны ли оно (это изменение) мгновенно (или даже вообще просто после закрытия диалога) отобразиться где-то в экранной форме?
Должно. В общем пока такое сложилось мнение: MVP Бодягина
Здравствуйте, shvonder, Вы писали:
S>Очепятка. Читать — пассивный Viewer. Пассивный, активный, так и просится на язык нетехнический термин
Честно говоря, такого термина тоже не встречал, хотя понял, что вы подразумеваете. В отношении MVC термины активность/пассивность употребляют по отношению к модели (после описания оригинальной реализации в Smalltalk аж лет 30 назад).
S>Должно. В общем пока такое сложилось мнение: MVP Бодягина
реализовывать мучительно.
Сколько программистов, столько и видений MVC/MVP. По-моему, в этом нет ничего плохого: каждый видит мир по-разному, соответственно на объектах каждому, возможно, бывает удобнее несколько по-своему построить взаимодействия сущностей. Кстати, оригинальное описание MVC в Smalltalk спокойно допускает такие всевозможные трактования (задаются только основные правила игры, а нюансы каждый может выбрать по вкусу). Возможно, вам чисто психологически удобнее видеть сущности MVC-триады несколько иначе, нежели предлагает IB. У меня и вовсе иное видение: если интересно, см. другую статью про MVC на сайте.
Здравствуйте, rsn81, Вы писали:
R>Возможно, вам чисто психологически удобнее видеть сущности MVC-триады несколько иначе, нежели предлагает IB. У меня и вовсе иное видение: если интересно, см. другую статью про MVC на сайте.
На самомо деле я стрепетом жду момента, когда соберу наконец хелло ворд на VC с wxWindows, и буду переходить на студию. Новый проект решил сделать максимально переносимым в том плане, чтобы менять гуй малой кровью. А тут Бодягин и говорит: "хлопцы, ща покажу", и даже спорит с неверующими и даже убедительно. Ладно, поживём увидим.
Здравствуйте, shvonder, Вы писали:
S>На самомо деле я стрепетом жду момента, когда соберу наконец хелло ворд на VC с wxWindows, и буду переходить на студию. Новый проект решил сделать максимально переносимым в том плане, чтобы менять гуй малой кровью. А тут Бодягин и говорит: "хлопцы, ща покажу", и даже спорит с неверующими и даже убедительно. Ладно, поживём увидим.
Вообще говоря, стоит прислушаться к словам IB. То, что вы не смогли разобраться с его видением MVP, говорит только об одном и это "одно" — вовсе не то, что вы написали выше.
Здравствуйте, rsn81, Вы писали:
R>Вообще говоря, стоит прислушаться к словам IB. То, что вы не смогли разобраться с его видением MVP, говорит только об одном и это "одно" — вовсе не то, что вы написали выше.
Никто не говорит, что IB неправ. Просто моя попытка реализовать IB-MVP мне самому не нравиться, ну я и спросил. Вопросов то много. Как так лихо Виду удаётся вызывать нужные процедуры Презентера, при том, что вид о нём даже не знает
public class Presenter
{
private Model _model = new Model();
private IView _view;
public Presenter(IView view)
{
_view = view;
_view.SetCelsius += new EventHandler<EventArgs>(OnSetCelsius);//<---- !!!
_view.SetFarenheit += new EventHandler<EventArgs>(OnSetFarenheit);
RefreshView();
}
Сдаётся, что на C++ такого не сделать. Лучше чем слать сообщения интерфейсу этого класса, я пока не придумал.
Прошу прощения за многословность, но тема интересная, а попытки поспрошать в форуме обычно заканчиваются какой то ерундой.
S>Сдаётся, что на C++ такого не сделать. Лучше чем слать сообщения интерфейсу этого класса, я пока не придумал.
На С++ это делается практически так же, как и в NET, если использовать boost::function или аналоги.
Здравствуйте, shvonder, Вы писали:
S>Лучше чем слать сообщения интерфейсу этого класса, я пока не придумал.
Статью IB читал уже давно, но разве он не имеено так и предлагал?
S>Прошу прощения за многословность, но тема интересная, а попытки поспрошать в форуме обычно заканчиваются какой то ерундой.
Взаимодействие представления и предъявителя мы обсуждали в теме обсуждения его статьи, посмотрите ее: я предлагал в ней альтернативные варианты — конкретно, помню, мне не очень нравилось, что при таком построении связи нет возможности прицепить к одному предъявителю множество представлений.
Здравствуйте, rsn81, Вы писали:
R>помню, мне не очень нравилось, что при таком построении связи нет возможности прицепить к одному предъявителю множество представлений.
Ну почему же, мы ведь можем реализовать в предьявителе специальный интерфейс для поддержки этой возможности, примерно так:
class IView {
public:
boost::function<void (IView*, int)> SetCelsius;
};
class Presenter {
public:
Presenter();
void AddView(IView* view) {
view->SetCelsius = boost::bind(&Presenter::OnSetCelsius, this, _1, _2);
_views.push_back(view);
}
private:
void OnSetCelsius(IView* view, int n) {
// обновляем все view из массива _views;
}
std::vector<View*> _views;
};
Здесь я добавил параметр IView* к коллбэку, чтобы предъявитель знал, какое представление его вызвало, если это знание не нужно, его можно убрать.
По большому счёту получился тот же обсервер, но немного более гибкий. Отличие заключается в том, что по обсерверу для подписки на сообщения представление должно получить указатель/ссылку на объект класса, реализующего некий интерфейс IPublisher (у которого есть метод void Subscribe(IObserver*) ). В приведённом же варианте абсолютно любой класс может настроить коллбэки под себя и получать сообщения от представления. Но в остальном, не спорю, решения почти эквивалентны.
Что же касается главного вопроса топика про модальные диалоги, то на мой дилетанский взгляд не нужно для каждого из них лепить новый интерфейс IView. Способ ввода параметров — это внутреннее дело каждого представления, т.е. этот модальный диалог как бы часть представления, такая же, как и контролы, которые на нём лежат.
Здравствуйте, Экселенц, Вы писали:
Э>Ну почему же, мы ведь можем реализовать в предьявителе специальный интерфейс для поддержки этой возможности, примерно так:
[skipped]
Именно так и делаю. Просто в этом случае потребность в том виде IView, который предлагает IB, нивелируется, нет, оно возможно, но мне кажется более удобным здесь становится озвученное выше т.н. "активное" представление. Да, оно реализует простой контракт подписки ISubscriber, по которому получает оповещения от предъявителя (при этом или получая информацию об изменении модели в самом оповещении, или самостоятельно вытягивая эту информацию из предъявителя). То есть, если ничего не путаю, конечно, у вас немного сложнее: IView + Callback — а здесь только ISubscriber.
Здесь еще дополнительная фишка выстреливает. Так как представление является всего лишь подписчиком, то оно может отписаться от одного предъявителя и подписаться на события другого. Чувствуете применимость? К примеру, проводник Windows: при выборе в дереве иерархии папок конкретной, боковое представление содержимого папки переключается на отображение выбранной папки (отписывается от одного предъявителя, подключается к другому). Возможен случай, когда представление вообще ничего не отображает: не подключено ни к одному предъявителю.
Здравствуйте, rsn81, Вы писали:
R>Именно так и делаю. Просто в этом случае потребность в том виде IView, который предлагает IB, нивелируется, нет, оно возможно, но мне кажется более удобным здесь становится озвученное выше т.н. "активное" представление. Да, оно реализует простой контракт подписки ISubscriber, по которому получает оповещения от предъявителя (при этом или получая информацию об изменении модели в самом оповещении, или самостоятельно вытягивая эту информацию из предъявителя). То есть, если ничего не путаю, конечно, у вас немного сложнее: IView + Callback — а здесь только ISubscriber.
Всё таки мне кажется, что количество связей в обоих случаях одинаково. У вас же представление должно как-то общаться с предъявителем или моделью, например, сообщить, что пользователь выбрал новую папку в дереве папок проводника. Значит, где-то будет метод SetSelectedDir(String dir). Это метод можно вызвать либо явно, если представление имеет ссылку на предъявителя/модель, как, наверное, у вас, либо через callback. Т.е. я хочу сказать, что только интерфейса ISubscriber мало.
R>Здесь еще дополнительная фишка выстреливает. Так как представление является всего лишь подписчиком, то оно может отписаться от одного предъявителя и подписаться на события другого. Чувствуете применимость? К примеру, проводник Windows: при выборе в дереве иерархии папок конкретной, боковое представление содержимого папки переключается на отображение выбранной папки (отписывается от одного предъявителя, подключается к другому). Возможен случай, когда представление вообще ничего не отображает: не подключено ни к одному предъявителю.
Мне видится, что это классический подход MVC, в котором нет ничего плохого В MVP же я вижу решение этой задачи следующим образом. У правого IView в интерфейсе есть метод ShowItems(Vector<Item>). В ответ на изменение текущей папки в левом представлении (дереве папок) предъявитель получает у модели содержимое этой новой папки и вызывает у правого представления метод ShowItems, передавая новое содержимое (здесь Item описывает элемент файловой системы (папку, файл...)). Т.е. представлению просто не нужно подписываться и отписываться на события, всем управляет предъявитель.
Но я не противопоставляю ваш подход своему, скажу банальность, но в разных ситуациях проще и лучше могут оказаться разные подходы. Я просто подсказал автору топика, как на С++ сделать то же самое, что и на NET в статье, если он захочет Хотя не скрою, в целом пассивная модель мне нравится больше и сам я стараюсь оставаться в её рамках, если другой подход не сулит больших преимуществ.
Здравствуйте, Экселенц, Вы писали:
Э>Всё таки мне кажется, что количество связей в обоих случаях одинаково. У вас же представление должно как-то общаться с предъявителем или моделью, например, сообщить, что пользователь выбрал новую папку в дереве папок проводника. Значит, где-то будет метод SetSelectedDir(String dir). Это метод можно вызвать либо явно, если представление имеет ссылку на предъявителя/модель, как, наверное, у вас, либо через callback. Т.е. я хочу сказать, что только интерфейса ISubscriber мало.
Представление выбирает нужный ему предъявитель из локатора предъявителей (см. шаблон проектирования Service Locator), это чтобы избежать неприятностей с Singleton. Разумеется, общение представления и предъявителя в части изменения данных подразумевает интерфейс со стороны предъявителя — использую шаблон проектирования Command. Говорил выше немного о другом: о том, что на представление налагается всего один контракт — подписки; а предъявителю не так важно, кто получает его уведомления — все, кто подписался (в принципе, это может быть любой заинтересованный класс, то есть представление не обязательно подразумевает какое-либо графическое отображение).
Э>Мне видится, что это классический подход MVC, в котором нет ничего плохого В MVP же я вижу решение этой задачи следующим образом. У правого IView в интерфейсе есть метод ShowItems(Vector<Item>). В ответ на изменение текущей папки в левом представлении (дереве папок) предъявитель получает у модели содержимое этой новой папки и вызывает у правого представления метод ShowItems, передавая новое содержимое (здесь Item описывает элемент файловой системы (папку, файл...)). Т.е. представлению просто не нужно подписываться и отписываться на события, всем управляет предъявитель.
Угу, так и описывал IB. Просто в статье не был затронут аспект работы с одними данными (моделью) нескольких представлений.
Э>Но я не противопоставляю ваш подход своему, скажу банальность, но в разных ситуациях проще и лучше могут оказаться разные подходы. Я просто подсказал автору топика, как на С++ сделать то же самое, что и на NET в статье, если он захочет Хотя не скрою, в целом пассивная модель мне нравится больше и сам я стараюсь оставаться в её рамках, если другой подход не сулит больших преимуществ.
Да, последнее время склоняюсь к тому же: с пассивной моделью меньше хлопот.