Форум: "Прочее";
Текущий архив: 2007.08.26;
Скачать: [xml.tar.bz2];
ВнизСтруктурность vs Простота Найти похожие ветки
← →
Piter © (2007-07-25 21:59) [0]Интересно ваше мнение по поводу сабжа. Объясню на примере:
Допустим, на некоей главной форме есть галочка (TCheckBox). Галочка включается - появляется дочерняя форма дополнительная. Галочка выключается - дочерняя форма скрывается.
Но "проблема" в том, что дочернюю форму можно закрыть не только убрав галочку на главной форме, но и просто нажав на крестик или допустим ALT+F4. И как вы думаете, что правильнее в этой ситуации - чтобы дочерняя форма напрямую обращалась к главной и снимала там галочку у чекбокса, или чтобы у дочеренй было некое событие, присвоив которое она просто будет уведомлять о своем закрытии, ну навроде:if Assigned(FMyClose) then
FMyClose(Self);
С одной стороны первый способ нагляднее и проще, всем доступен. С другой стороны, это получатся перекрестные ссылки одного модуля на другой. Я может не прав, но всегда стараюсь делать иерархию от большего к меньшему. Если некий юнит обращается к другому юниту, значит последний на более низком уровне и сам он к модулю более верхнего уровня обращаться не должен.
Это вроде как ближе к ООП подходу.
Но кто-то скажет, что это городить огород.
Как вы поступаете?
P.S. Я обычно если проект тяп ляп на скорую руку - не парюсь и выбираю первый подход, а если более серьезное приложение - второй.
← →
Virgo_Style © (2007-07-25 22:16) [1]Piter © (25.07.07 21:59)
или чтобы у дочеренй было некое событие, присвоив которое она просто будет уведомлять о своем закрытии
Не совсем понял, это вроде callback"а?
Если делать тяп-ляп, то я бы поставил проверку по таймеру, но это, конечно, совсем страшненько.
Более серьезно, imho, сделать callback, причем можно это сделать не только как вызов процедуры, но и как посылку сообщения.
← →
Shalom (2007-07-25 22:20) [2]Подход с галочкой в данном случае изначально не верный, так как без индикации состояния дочернего окна вполне можно обойтись.
Это можно делать кнопкой без состояния, которая покажет или скроет форму в зависимости от того, отображается она или нет.
Логика пользовательского интерфейса должна быть максимально простой.
Конечно, должен быть определенный уровень абстракции для достаточно независимых объектов, обменивающихся сообщениями.
Можно использовать, например, паттерн "Наблюдатель".
← →
Zeqfreed © (2007-07-25 22:21) [3]Лучше, чтобы при нажатии Alt + F6 и одновременном движении курсора по кругу радиусом от 50 до 52 пикселей открывалась форма. А закрывалась сама, через случайный промежуток времени. Пользователь будет доволен.
← →
antonn © (2007-07-25 22:22) [4]
> Это можно делать кнопкой без состояния
есть понятие об том интерфейсе, что делает Piter?
← →
ferr © (2007-07-25 22:24) [5]В отдельном классе, видимом как форме с чебоксом так и допформе, хранится свойство - флажок, в этом же классе есть событие о изменении этого флажка.. и всё в таком духе..
← →
Shalom (2007-07-25 22:25) [6]antonn © (25.07.07 22:22) [4]
Так расскажите если есть.
Piter предоставил ровно столько информации, сколько счел нужным, никак не обосновав использование галочки.
← →
Sergey Masloff (2007-07-25 22:35) [7]Можно еще мессадж посылать родительскому окну. Для этого дочке о нем практически ничего не надо знать
Но открытие окна по чекбоксу ни фига не интуитивно
← →
jack128_ (2007-07-25 22:37) [8]Вариант номер 2. Без вариантов.
← →
Джо © (2007-07-25 22:56) [9]Я за событие или мессадж.
Вариант с кнопкой/элементом меню без состояния тоже рассмотрел бы.
← →
DrPass © (2007-07-25 23:01) [10]
> Это вроде как ближе к ООП подходу.
>
> Но кто-то скажет, что это городить огород.
Считаю, что это - городить огород. Правила ООП не самоцель, а всего лишь средство упрощения структуры программ. И, спрашивается, зачем им следовать в тех случаях, если упрощение не достигается.
← →
Kolan © (2007-07-25 23:01) [11]> как вы думаете, что правильнее в этой ситуации
Прочти про паттерн медиатор — оба твои варианта не очень.
← →
Юрий Зотов © (2007-07-26 00:26) [12]Мастер-форма показывает дочернюю (кнопкой, или иным щелчком, главное, чтобы без всякого запоминания - в том числе, без всяких без всяких галочек). Остально ее не волнует.
Юзер закрывает дочернюю форму. ОК, на здоровье. Она закрывается и больше ничего не происходит
← →
Юрий Зотов © (2007-07-26 00:28) [13]То есть, имелось в виду не " cтруктурность vs простота", а " структурность И прстота ".
← →
Piter © (2007-07-26 01:50) [14]Понимаю ваши затруднения без примера. Приведу пример:
у качалок есть такая опция - "корзина". Это маленькое полупрозрачное окошко, которое висит поверх всех окон, и чтобы качать можно просто перенести ссылку с браузера в корзину. Например, это можно наблюдать в качалке FlashGet. Удобная вещь.
Как эта корзина управляется? В меню качалки есть пункт меню "Корзина". Можно сделать так, чтобы она просто скрывала, если корзина отображается и отображала, если она скрытая. Но нагляднее когда корзина открыта - чтобы в главном пункте меню на ее месте стояла галочка (активно). С включение понятно - нажал пункт меню, взвелась галочка, ты сделал форме-корзине Show. А если закрыть? Ее можно закрыть как и через пункт меню, так и через опции корзины, например, всплывающем меню формы корзины. Оно обрабатывается формой корзины, как она уведомит, что она закрывается главной форме?
Или напрямую убирает из главной формы, из меню галочку. Или как-то сообщает.
Вот и что правильно? Мне кажется структурнее, когда через событие (ну это и есть callback), но можно и напрямую. Через таймер, имхо, совсем не правильно.
← →
Юрий Зотов © (2007-07-26 02:08) [15]> Piter © (26.07.07 01:50) [14]
Callback или сообщение.
1. Таймер оставим юным читателям Фленова и не обсуждаем вообще.
2. Управление одного объекта другим объектом напрямую - плохо. Объект отвечает сам за себя, сам знает все свои фичи и сам должен принимать решение. Другой же объект только должен его уведомить, что что-то произошло.
← →
Псалтырь (2007-07-26 02:10) [16]TAction?
← →
Юрий Зотов © (2007-07-26 02:16) [17]> Piter © (26.07.07 01:50) [14]
Но самое правильное и простое - вообще не иметь никаких галочек. Пункт меню главной формы просто говорит дочерней "покажись" и ничего не запоминает - а дальше уже дочерняя рулит сама. Если она и так видимая, то ничего не делает, иначе показывается. А закрывает ее юзер, когда ему надо.
← →
Kolan © (2007-07-26 11:23) [18]> Допустим, на некоей главной форме есть галочка (TCheckBox)
> . Галочка включается — появляется дочерняя форма дополнительная.
Как я бы сделал:
1. Форма и галочка вообще ниче о друг друге не знаю.
2. Есть медиатор такого вида, который знает о всех:
TMediator = clas
procedure Show(IsShow: Boolean);
end;
{…}
procedure TMediator.Show(IsShow: Boolean);
begin
MainForm.CheckBox.Checked := IsShow;
OtherForm.Visible := IsShow;
end;
Вот и всё.
На клик галочки поставить:Mediator.Show((Sender as TCheckBox).Checked);
На закрытие формы:Mediator.Show(False);
На открытие:Mediator.Show(True);
Что ты получаешь написав эти (подсчитай сам сколько) строк.
1. Ты можешь кроме галочки добвить «Кнопочку», «Палочку», «списочек» — все что хочешь. И исзменять надо будет только медиатор.
2. Вся логика у тебя перед глазами в одном методе.
ЗЫ
Медиатор можешь сделать синглетоном.
← →
Игорь Шевченко © (2007-07-26 11:30) [19]Как делал я:
в главной форме переопределял метод Notification
procedure TfMain.Notification(AComponent: TComponent;
AOperation: TOperation);
begin
inherited;
if (AComponent.ClassType = TfChild) and (AOperation = opRemove) then
Снятьгалкусчекбокса
end;
дочернуюю форму создавал с Owner = основнаяформа
← →
Kolan © (2007-07-26 11:48) [20]> if (AComponent.ClassType = TfChild) and (AOperation = opRemove)
> then
> Снятьгалкусчекбокса
А если в еще одной форме надо чтобы кнопка нажалась?
← →
Игорь Шевченко © (2007-07-26 12:14) [21]
> А если в еще одной форме надо чтобы кнопка нажалась?
Написать для этого нужный код.
← →
@!!ex © (2007-07-26 12:33) [22]Хм. Совсем недавно делал.
Галочка, которая называеться "Предварительный просмотр"
На нее нажимаешь, галочка ставится, появялется окно просмотра.
Снимаешь, окно убирается.
Закрываешь окно, галочка остается на месте.
Однако до сих пор ис пользователей на это никто не жаловался....
Хотя конечно это не есть гуд.
← →
Kolan © (2007-07-26 12:39) [23]> Написать для этого нужный код.
Нетолько, еще надо ту форму подключить в uses главной…
← →
Игорь Шевченко © (2007-07-26 12:54) [24]Kolan © (26.07.07 12:39) [23]
> Нетолько, еще надо ту форму подключить в uses главной…
А это какой код написать. Для реализации предложенного тобой существует хороший паттерн observer.
← →
ЮЮ © (2007-07-26 12:59) [25]> Нетолько, еще надо ту форму подключить в uses главной…
а в uses модуля UMediator с TMediator будто не надо? :) К тому же в обеих формах нужен UMediator в uses. А глобальные переменные MainForm и OtherForm - вообще ЗЛО :)
← →
Sandman29 © (2007-07-26 13:02) [26]Игорь Шевченко © (26.07.07 12:54) [24]
Kolan © (26.07.07 12:39) [23]
Не спорьте, Вы оба правы :)
Специальный класс (обзервер) получает уведомление о том, что дочерняя форма закрылась и вызывает метод медиатора, который уведомляет всех. В простых случаях, медиатор и обсервер - один класс.
← →
Kolan © (2007-07-26 13:10) [27]> а в uses модуля UMediator с TMediator будто не надо?
Ладно, а если 10 форм?
> вообще ЗЛО :)
Еще скажи что Delphi вообще ЗЛО.
> [24] Игорь Шевченко © (26.07.07 12:54)
> А это какой код написать. Для реализации предложенного тобой
> существует хороший паттерн observer.
А как вы будете делать CheckBox И Форму наблюдателями? Что наследников писать?
← →
Kolan © (2007-07-26 13:14) [28]Кроме того в книге GoF для медиатора именно пример с синхранизацией контролов…
← →
Игорь Шевченко © (2007-07-26 13:36) [29]Kolan © (26.07.07 13:10) [27]
> А как вы будете делать CheckBox И Форму наблюдателями? Что
> наследников писать?
Я буду делать просто. Чего и другим советую. Существует одно простое правило, которого я стараюсь сам придерживаться и другим рекомендую:
Алгоритм программы должен быть реализован минимальным количеством ясных и понятных операторов.
Checkbox наблюдателем я делать не буду. Как я буду делать в случае с CheckBox, я написал, через переопределение метода Notification. В этом же методе я могу послать сообщение (не оконное, а объектное)
всем заинтересованным подписчикам о закрытии дочерней формы.
> Кроме того в книге GoF для медиатора именно пример с синхранизацией
> контролов…
Дорогой друг, в книгах GoF и Patterns of EAA ни словом не упоминается о Delphi и ее компонентной модели. Зачем же выбрасывать все, что сделано за 12 лет фирмой Borland, ныне CodeGear Borland в угоду Гамме сотоварищи и Фаулеру ?
Кроме того, советую учитывать еще и то обстоятельство, что код обычно не пишется один раз, а потом не читается. Если ты хочешь напрячь себя через какое-то время или, не дай Аллах, других разработчиков, разбирательством в твоей реализации уже реализованных в RTL и VCL механизмов, то тогда, конечно, можно и GoF вооружаться.
← →
Piter © (2007-07-26 13:40) [30]Kolan © (26.07.07 11:23) [18]
а в каком интересно модуле ты разместишь объявление этого TMediator?
Игорь Шевченко © (26.07.07 11:30) [19]
мне кажется совсем путанно, не наглядно. Тогда уж поступать по принципу VCL - делать событие.
@!!ex © (26.07.07 12:33) [22]
Галочка, которая называеться "Предварительный просмотр"
На нее нажимаешь, галочка ставится, появялется окно просмотра
во, во, даже более удачный пример ты привел.
Тоже рассматривал данный вариант, чтобы и не заморачиваться. Тут уже страдает наглядность программы, но возрастает простота написания.
Косяк есть, чтобы открыть опять окно пользователю надо снять галочку (ничего не произойдет), а потом опять нажать.
← →
Игорь Шевченко © (2007-07-26 13:42) [31]
> мне кажется совсем путанно, не наглядно. Тогда уж поступать
> по принципу VCL - делать событие.
Сколько людей, столько мнений.
← →
Piter © (2007-07-26 13:42) [32]общую я мысль понял. Все таки лучше сделать грамотно, хоть и немного путанно, чем впрямую делать перекрестные ссылки одного юнита на другой.
← →
Kolan © (2007-07-26 14:04) [33]> а в каком интересно модуле ты разместишь объявление этого
> TMediator?
В отдельном.
> Тогда уж поступать по принципу VCL — делать событие.
Сделав событие ты нарушаешь два осн. паттерна.
1. Ты повышаешь связывание(coupling).
Гл. форма будет знать о дочерней.
2. Ты уменьшаешь зацепление(cohesion).
Гл форма будет выполнять работу, которую не должна выполнять
Ессно при 1 галочке и 1 форме можно делать как угодно… Но при увеличении сложности геморой увеличится экспоненциально сложности, а при использовании медиатора линейно :)
> Сколько людей, столько мнений.
+1
← →
Piter © (2007-07-26 14:22) [34]Kolan © (26.07.07 14:04) [33]
1. Ты повышаешь связывание(coupling).
Гл. форма будет знать о дочерней
ну офигеть, а что тут такого? А это абсолютна принятая практика - например, отображение ShowModal форм, главная форма полностью управляет (считывает / записывает) информацию в дочернюю, дочерняя же может только правильность вводимых значений проверяет.
Плюс главная будет знать о дочерней. А в твоем варианте городиться еще один модуль, и этот модуль должен быть связан уже с двумя другими модулями. Не повышается ли связывание?
Kolan © (26.07.07 14:04) [33]
Гл форма будет выполнять работу, которую не должна выполнять
какую работу она не должна выполнять? Снятие СОБСТВЕННОЙ галочки?
← →
Sandman29 © (2007-07-26 14:31) [35]Piter © (26.07.07 14:22) [34]
Как раз для возможности повторного использования кода, он ДОЛЖЕН быть вынесен в отдельный модуль.
Простейший пример использования
with TFormCloseMediator(ChildForm) do
AddListener(MainForm);
← →
Sandman29 © (2007-07-26 14:32) [36]Piter © (26.07.07 14:22) [34]
Как раз для возможности повторного использования кода, он ДОЛЖЕН быть вынесен в отдельный модуль.
Простейший пример использования
with TFormCloseMediator.Create(ChildForm) do
AddListener(MainForm);
← →
Kolan © (2007-07-26 14:57) [37]> А это абсолютна принятая практика
Где сказано, что это хорошая практика?
> Не повышается ли связывание?
Нет связывание понижается. Представть себе что у вас от галочки зависит 10 форм. Тогда гл. форма связана уже с 10 объектами, а в моём случае как был 1 медиатор, так и остался.
> какую работу она не должна выполнять? Снятие СОБСТВЕННОЙ
> галочки?
Правильный вопрос, сразу хотел на него ответить, но решил подождать.
Все верно, согласно паттернуInformation Expert
галочку должен снимать тот, кто о ней знает — то есть форма.
Особенно это заметно если галочку заменить на что-то другое. Тогда придется править медиатор.
То есть вместо:procedure TMediator.Show(IsShow: Boolean);
begin
MainForm.CheckBox.Checked := IsShow;
OtherForm.Visible := IsShow;
end;
В форме надо сделать метод MyShow(назание придумаете сами), который и будет снимать/устанавливать галочку.
А медиатор будет вызывать его:procedure TMediator.Show(IsShow: Boolean);
begin
MainForm.MyShow(IsShow);
OtherForm.Visible := IsShow;
end;
Но большого греха, имхо, нет если медиатор напрямую её поставит.
ЗЫ
Прочтите про медиатор вначале(в GoF страница 263), там именно ваша задача решена в кач примера.
Сделайте так ради интереса — уверен, что поймёте что так лучьше…
← →
Kolan © (2007-07-26 15:06) [38]> главная форма полностью управляет (считывает / записывает)
> информацию в дочернюю,
Это вообще Unacceptable. В дочерней форме надо хотябы методы делать для работы с контролами…
дочерняя же может только правильность
> вводимых значений проверяет.
А че ну пусть главная и проверяет? Пусть она все делать будет, зато модули не городить(кто вообще эту модульность придумал)…
А потом смотришь такой проект и видишь что поиском, и сохранение истории занимается почемуто форма, а не объект «Поисковик» и «Хранитель истории». И все методы в кучу.
← →
Игорь Шевченко © (2007-07-26 15:26) [39]Опыт очень хорошее дело.
← →
Kolan © (2007-07-26 15:33) [40]> Опыт очень хорошее дело.
В смысле провести опыт, или всмысле опыт многих лет работы? Такие штуки с маленьким медиатором я последне время часто делаю…
Страницы: 1 2 3 вся ветка
Форум: "Прочее";
Текущий архив: 2007.08.26;
Скачать: [xml.tar.bz2];
Память: 0.57 MB
Время: 0.052 c