Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Прочее";
Текущий архив: 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;

{&#133}

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 главной&#133


 
Игорь Шевченко ©   (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 для медиатора именно пример с синхранизацией контролов&#133


 
Игорь Шевченко ©   (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 форме можно делать как угодно&#133 Но при увеличении сложности геморой увеличится экспоненциально сложности, а при использовании медиатора линейно :)


> Сколько людей, столько мнений.

+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), там именно ваша задача решена в кач примера.
 Сделайте так ради интереса — уверен, что поймёте что так лучьше&#133


 
Kolan ©   (2007-07-26 15:06) [38]

> главная форма полностью управляет (считывает / записывает)
> информацию в дочернюю,

Это вообще Unacceptable. В дочерней форме надо хотябы методы делать для работы с контролами&#133

дочерняя же может только правильность
> вводимых значений проверяет.

А че ну пусть главная и проверяет? Пусть она все делать будет, зато модули не городить(кто вообще эту модульность придумал)&#133

А потом смотришь такой проект и видишь что поиском, и сохранение истории занимается почемуто форма, а не объект «Поисковик» и «Хранитель истории». И все методы в кучу.


 
Игорь Шевченко ©   (2007-07-26 15:26) [39]

Опыт очень хорошее дело.


 
Kolan ©   (2007-07-26 15:33) [40]

> Опыт очень хорошее дело.

В смысле провести опыт, или всмысле опыт многих лет работы? Такие штуки с маленьким медиатором я последне время часто делаю&#133


 
Игорь Шевченко ©   (2007-07-26 15:37) [41]

Kolan ©   (26.07.07 15:33) [40]

В смысле многих лет конечно. Когда начинаешь ценить простоту.


 
Kolan ©   (2007-07-26 15:42) [42]

> Когда начинаешь ценить простоту.

Дык вы считаете перекрёсные ссылки пойдут?
Не, я согласен что для случая из сабжа(два объекта) пойдёт, но как только их станет три, я сделаю медиатор&#133
А вы?

ЗЫ
 Надо же опыт перенимать :)


 
Piter ©   (2007-07-26 15:50) [43]

Kolan ©   (26.07.07 14:57) [37]
Где сказано, что это хорошая практика?


а где сказано, что плохая?

Kolan ©   (26.07.07 14:57) [37]
Тогда гл. форма связана уже с 10 объектами, а в моём случае как был 1 медиатор, так и остался.


Зато все 10 форм связаны с медиатором. Не понял.
Опять же 10 связей.

Kolan ©   (26.07.07 14:57) [37]
В форме надо сделать метод MyShow(назание придумаете сами), который и будет снимать/устанавливать галочку


ага, ну офигеть. Это просто городить огород. Для такого элементарного действия придумывать такие ходы...

Ну нафиг. Версия с событиями куда нагляднее, имхо. Есть объект как черный ящик. Хочешь - делай над ним действия (показывай, скрывай), если хочешь узнать о событиях черного ящика - ты ему говоришь "если у тебя такая фигня случится - ты мне свистни" и указываешь куда свистнуть. Ну логично же?

Вместо этого заводишь посредника, который говорит форме "ты если что случится - свистни мне, а я уже свистну кому надо, и наоборот". В случае с галочкой это уже перебор. В более сложной логике - ну может быть это упростит задачу.


 
Sandman29 ©   (2007-07-26 15:55) [44]

Игорь Шевченко ©   (26.07.07 15:37) [41]

Простота часто вступает в противоречие с удобством дальнейших изменений


 
Игорь Шевченко ©   (2007-07-26 16:01) [45]

Kolan ©   (26.07.07 15:42) [42]

Я считаю, что в данном примере достаточно сделать Notification, потому что механизм оповещения срабатывает автоматически и никакого дополнительного кода для этого писать не надо.

Например:

unit main;

interface
uses
 Classes, Graphics, Controls, Forms, StdCtrls;

type
 TfMain = class(TForm)
   CheckBox1: TCheckBox;
   procedure CheckBox1Click(Sender: TObject);
 public
   procedure Notification (AComponent: TComponent;
     AOperation: TOperation); override;
 end;

var
 fMain: TfMain;

implementation
uses
 Child;

{$R *.dfm}

procedure TfMain.CheckBox1Click(Sender: TObject);
var
 ChildForm: TComponent;
begin
 if CheckBox1.Checked then
   with TfChild.Create(Self) do
     Show
 else
 begin
   ChildForm := FindComponent("fChild");
   if Assigned(ChildForm) and not (csDestroying in ChildForm.ComponentState) then
     ChildForm.Free;
 end;
end;

procedure TfMain.Notification(AComponent: TComponent; AOperation: TOperation);
begin
 inherited;
 if (AComponent.ClassName = "TfChild") and (AOperation = opRemove) then
   CheckBox1.Checked := false;
end;

end.


unit Child;

interface
uses
 Classes, Graphics, Controls, Forms;

type
 TfChild = class(TForm)
   procedure FormClose(Sender: TObject; var Action: TCloseAction);
 end;

implementation

{$R *.dfm}

procedure TfChild.FormClose(Sender: TObject; var Action: TCloseAction);
begin
 Action := caFree;
end;

end.


Можно попробовать...


 
Игорь Шевченко ©   (2007-07-26 16:02) [46]

Sandman29 ©   (26.07.07 15:55) [44]


> Простота часто вступает в противоречие с удобством дальнейших
> изменений


Никогда


 
Kolan ©   (2007-07-26 16:19) [47]

> а где сказано, что плохая?

Во многих книгах/статьях, еще раз говорю это повышает связывание. Сильно связание объекты сами посебе — не проблемма вообще. Проблема возникает когда они изменяются.

Опять же 10 связей.
Вы не понимаете термин связывание. Прочтайте литаратуру, по сам паттерн хотябы&#133
Высокая степень связывания — когда объект зависит от большого числа других объектов.

Без медиатора форма зависит от 10 объектов.
С медиатором от одного.

В худщем случае, при вашем подходе, кажды объект будет связан с каждым. медиатор же разбивате эти связи. С медиатором каждый объект знает только медиатор.
То что сам медиатор будет свзан со всеми — нестрашно(это его предназначение по сути), так как он один, изменяется редко.

ага, ну офигеть. Это просто городить огород.
Я повторяю. если вы пишете фигню на 100 строк, то вы правы. Если вы пишете серьёзный(сложный) проект, то вы его в итоге провалите(хотябы по срокам).

Ну логично же?
Конечно логично, только:

> ты ему говоришь «если у тебя такая фигня случится — ты мне
> свистни»

А что будет если этих ТЫ не один а много, как тогда? В Delphi вы не подключитесь к одному событию несколькоми объектами.


> Вместо этого заводишь посредника, который говорит форме
> «ты если что случится — свистни мне, а я уже свистну кому
> надо, и наоборот».

Нет, не так.

Форма говорит медиатору: «Свести всем».


> с галочкой это уже перебор

Если вы спрашиваете про конкретный сабж с галочкой, то перебор. Я думаю вы хотите понят как делать это в более сложном случае. а галочка — это пример.

Сделать перекрёсные ссыки — быстро только в начале, при добавлении новых, зависящих от галочи, объектов с медиатором вы сэкономите гораздо больше времени, чем потратите на его создание вначале.


 
Kolan ©   (2007-07-26 16:21) [48]

> Я считаю, что в данном примере достаточно сделать Notification

Да ниче подход, согласен. Проще медиатора/наблюдателя и лучьше перекрёсных ссылок.


 
Kolan ©   (2007-07-26 16:23) [49]

Удалено модератором


 
Sandman29 ©   (2007-07-26 16:39) [50]

Игорь Шевченко ©   (26.07.07 16:02) [46]

Никогда

Проще скопировать, чем унаследовать, Вы не находите? Дальше продолжать?


 
Игорь Шевченко ©   (2007-07-26 16:39) [51]

Kolan ©   (26.07.07 16:19) [47]


> Если вы спрашиваете про конкретный сабж с галочкой, то перебор.
>  Я думаю вы хотите понят как делать это в более сложном
> случае. а галочка — это пример.


Еще раз (возвращаясь к вопросу о DataLayer и прочем): Демонстрировать всякие паттерны на простых примерах вроде таблиц с двумя полями или галки с формой при реализации на Delphi просто бессмысленно.
Для простых вещей в Delphi, слава Аллаху, достаточно простых и опробованных методов, а всякие паттерны только собьют с толку.
Хочется демостраций - их надо изучать на сложных примерах.

Хороший пример для демострации, правда, совсем иного, приведен у Мартина Фаулера в книге "Рефакторинг", в самом начале.


 
Piter ©   (2007-07-26 16:43) [52]

Kolan ©   (26.07.07 16:19) [47]
С медиатором от одного


зато сам медиатор зависит от этих самых 10-ти форм!

Kolan ©   (26.07.07 16:19) [47]
То что сам медиатор будет свзан со всеми — нестрашно


Ну да. Если форма связана - это страшно, это нарушение паттерна и высокая степень связывания.

Когда медиатор связан - это не страшно, это фича!

Не вижу логики.

Kolan ©   (26.07.07 16:19) [47]
А что будет если этих ТЫ не один а много, как тогда? В Delphi вы не подключитесь к одному событию несколькоми объектами


если есть такая нужда - сделать многособытийную версию. Не просто присвоение события, а типа:

AddListener(<ссылка на функцию>)
DeleteListener(<ссылка на функцию>)

А информацию о тех, кто требует уведомления - отлично хранить в TList

Kolan ©   (26.07.07 16:19) [47]
Я думаю вы хотите понят как делать это в более сложном случае


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


 
Игорь Шевченко ©   (2007-07-26 16:46) [53]

Sandman29 ©   (26.07.07 16:39) [50]


> Проще скопировать, чем унаследовать, Вы не находите? Дальше
> продолжать?


Дружище, я имею в виду не простоту труда, а простоту реализации. Это две совершенно разные вещи.

Простота, а не легкость.

И, кстати, иногда проще (и легче) скопировать.


 
Sandman29 ©   (2007-07-26 16:46) [54]

Piter ©   (26.07.07 16:43) [52]

Когда медиатор связан - это не страшно, это фича!

Не вижу логики.


Медиатор завязан на конкретное приложение, а каждую отдельную форму можно использвать где угодно.


 
Sandman29 ©   (2007-07-26 16:49) [55]

Игорь Шевченко ©   (26.07.07 16:46) [53]

Что есть простота реализации?


 
Kolan ©   (2007-07-26 16:52) [56]


> Когда медиатор связан &#151; это не страшно, это фича!

Ну ты ленивый что ли? RTFM

Лана давай считать вместе. У тебя есть 10 объектов и все они должны быть связаы(по логике) друг с другом, сколько связей?
&#151; Правильно 100.

Теперь с медиатором. Каждый объект связан с медиатором &#151; 10 связей. И медиатор знает всех &#151; 10 связей. Сколько всего?
Правильно 20.

Ок?


> А информацию о тех, кто требует уведомления &#151; отлично хранить
> в TList

Ну вот вы и приближаетесь к &laquo;Наблюдателю&raquo;.


> Просто интересно кто как на самом деле делает.


Вот чес слово, вот лично я делаю(не сделал бы, а делаю) медиатор.


 
Игорь Шевченко ©   (2007-07-26 16:52) [57]

Sandman29 ©   (26.07.07 16:49) [55]


> Что есть простота реализации?


пост № 29:

"Существует одно простое правило, которого я стараюсь сам придерживаться и другим рекомендую:
Алгоритм программы должен быть реализован минимальным количеством ясных и понятных операторов."


 
Kolan ©   (2007-07-26 16:57) [58]

> Еще раз (возвращаясь к вопросу о DataLayer и прочем):

Нет, это не тот случай. С DataLayer &#151; согласен, на Delphi слишком много надо написать, чтобы работало&#133


> или галки с формой при реализации на Delphi просто бессмысленно.

Тут очень смысленно.


> Для простых вещей в Delphi, слава Аллаху, достаточно простых
> и опробованных методов, а всякие паттерны только собьют
> с толку.

В данном случае язык не важен. Да я и не демонстрирую, я говорю что я так делаю. Все остальное &#151; док-во что это не самый полохой подход.


> Хочется демостраций &#151; их надо изучать на сложных примерах.

Мой поедены Ктулху мозг с трудом в простые примеры вникает, а вы про сложные&#133


> Хороший пример для демострации, правда, совсем иного

Про провалившейся проект?


 
Игорь Шевченко ©   (2007-07-26 16:59) [59]

Kolan ©   (26.07.07 16:57) [58]


> > Хороший пример для демострации, правда, совсем иного
>
> Про провалившейся проект?


Я про пример из книги Фаулера "Рефакторинг". Фаулер не одну книгу написал.


 
Kolan ©   (2007-07-26 17:01) [60]

> пост № 29:

Что-то я его проглядел.


> нечно, можно и GoF вооружаться.

Уверен что GoF знает большее кол-во людей чем VCL&#133


 
Sandman29 ©   (2007-07-26 17:02) [61]

Игорь Шевченко ©   (26.07.07 16:52) [57]

Так я же и говорю - копирование. Куда уж минимальней и понятней.


 
Kolan ©   (2007-07-26 17:03) [62]


> Я про пример из книги Фаулера &laquo;Рефакторинг&raquo;.

Я про  неёже и Говорю(Refactoring Improving the Designof Existing Code)&#133

Вы про это:
Once upon a time, a consultant made a visit to a development project.
{&#133}
Six months later the project failed, in large part because the code was too complex to debug or to tune to acceptable performance.


 
Kolan ©   (2007-07-26 17:03) [63]

> Так я же и говорю &#151; копирование.

Игорь Шевченко не об этом, имхо&#133


 
Игорь Шевченко ©   (2007-07-26 17:05) [64]

Kolan ©   (26.07.07 17:03) [62]


> Once upon a time, a consultant made a visit to a development
> project.
> {…}
> Six months later the project failed, in large part because
> the code was too complex to debug or to tune to acceptable
> performance


Нет, я не про это. Я про пример с видеопрокатом,  собственно, демонстрации рефакторинга.


 
Kolan ©   (2007-07-26 17:08) [65]

> Нет, я не про это. Я про пример с видеопрокатом,  собственно,
> демонстрации рефакторинга.

So I have to ask you to look at this and imagine it in the context of a much larger system.


Что я и пытаюсь сделать, и этого же про DataLayer хотел от вас&#133


 
Sandman29 ©   (2007-07-26 17:16) [66]

Kolan ©   (26.07.07 17:03) [63]

А о чем? Может ты объяснишь?


 
Игорь Шевченко ©   (2007-07-26 17:23) [67]

Kolan ©   (26.07.07 17:08) [65]

Я по русской книге смотрю, это глава 1.
Но даже тот пример, что приведен у Фаулера, это не таблица из двух бессмысленных полей (ID,Value), а вполне себе достаточный кусок кода.

Я, когда приобрел эту книгу (почти сразу, как появилась в России), смотрел на приведенный код и считал, что код, как код, многие так пишут, вполне себе. Потом, когда автор начал его корежить, я понял, в чем суть того, о чем дальше будет книга и мне это понравилось :)

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


 
Kolan ©   (2007-07-26 17:31) [68]

> Я по русской книге смотрю, это глава 1.

Ну все правильно, после [65] Kolan ©   (26.07.07 17:08) в русской версии идут слова &laquo;исходная программа&raquo;

> Это я к тому, что хороший осмысленный пример чего-либо дает
> гораздо больше, чем демонстрация чего-либо в отрыве от практики.

+1, только выходит что если я хочу вопрос задать(не понятно мне что-то) мне надо книгу написать, ну или пример листов на 100&#133
Ессно такой пример я не напишу, вот я и упрощаю.


 
Piter ©   (2007-07-26 17:33) [69]

Sandman29 ©   (26.07.07 16:46) [54]
Медиатор завязан на конкретное приложение, а каждую отдельную форму можно использвать где угодно


ага. Особенно там, где нет медиатора.

Не понял.

Kolan ©   (26.07.07 16:52) [56]
Лана давай считать вместе. У тебя есть 10 объектов и все они должны быть связаы(по логике)


это по какой такой логике интересной?! Если одна форма знает о двух других, это вообще не означает, что эти две формы знают друг о друге. В большинстве случае это и не так вовсе.

Игорь Шевченко ©   (26.07.07 16:52) [57]
Алгоритм программы должен быть реализован минимальным количеством ясных и понятных операторов


гы. Напрашивается логичное продолжение - "и, видимо, максимальным количеством неясных и непонятных операторов"

:)))))

Kolan ©   (26.07.07 17:01) [60]
Уверен что GoF знает большее кол-во людей чем VCL


но с другой стороны твой код скорее всего будет смотреть человек, который знает VCL, чем GoF


 
Игорь Шевченко ©   (2007-07-26 17:34) [70]

Kolan ©   (26.07.07 17:31) [68]


> только выходит что если я хочу вопрос задать(не понятно
> мне что-то) мне надо книгу написать, ну или пример листов
> на 100…
> Ессно такой пример я не напишу, вот я и упрощаю.


даже такой, как у Фаулера не напишешь ? Там не 100 листов, а от силы 2.

Книгу надо не писать, книгу надо читать.


 
Игорь Шевченко ©   (2007-07-26 17:35) [71]

Piter ©   (26.07.07 17:33) [69]


> Напрашивается логичное продолжение - "и, видимо, максимальным
> количеством неясных и непонятных операторов"


И такое случается. В этом случае автора программы обычно долго вспоминают нелестными словами. После его увольнения.


 
Sandman29 ©   (2007-07-26 17:39) [72]

Piter ©   (26.07.07 17:33) [69]

Как ты собираешься использовать форму, которая сама обращается к десятку других форм?


 
Kolan ©   (2007-07-26 17:50) [73]


> Если одна форма знает о двух других, это вообще не означает,
> что эти две формы знают друг о друге.

Ты непробиваем, имхо это пройдет. Это пример, теория, которая часто подтверждается практикой&#133

Меняю свйо совет тебе(только в этом случае) &#151; делай перекресные ссылки и не парься.


 
Piter ©   (2007-07-26 17:58) [74]

Sandman29 ©   (26.07.07 17:39) [72]
Как ты собираешься использовать форму, которая сама обращается к десятку других форм?


а такие главные формы из приложения в приложение и не переносятся, ибо очень индивидуальны. А вот например диалоговую формы настройки TCP/IP соединения вполне можно перенести, они никуда не обращается. В том числе она не обращается ни к какому медиатру.

А вот теперь объясни как ты собираешься использовать форму, если у тебя в другом приложении нету никакого медиатора?


 
Piter ©   (2007-07-26 18:06) [75]

по-моему, любой класс должен быть как можно более самодостаточек (как раз с вашими минимальными числами связи).

Такая форма самодостаточно. Обычно это некая форма настройки, она не использует никакой медиатор. И рассматривать ее можно как отдельное целое.

В твоем случае она использует медиатор - значит надо рассматривать еще и медиатор. А медиатор использует главную форму, надо рассматривать еще и ее. Ну и где тут модульность?

Я понимаю смысл этого медиатора - это типа как диспетчер сообщений. Что-то навроде виндового диспетчера. Но наверное это нужно только в случае очень сложной иерархии.

И, кстати, не в такой реализации как представлена. Тогда уж такой медиатор вообше не должен знать ни о главной форме, ни о дочерних, он вообще ни о чем не должен знать.

Просто разные классы могут регистрироваться у этого диспетчера. Ну например одна форма зарегистрируется как возможный источник события M_SETTING_FORM_CLOSE, а другая форма допустим может подписаться у диспетчера на это событие. Этот диспетчер тогда получится ядром программы в сложных проектах.


 
Bless ©   (2007-07-26 18:08) [76]


> Piter ©   (26.07.07 17:58) [74]
> А вот теперь объясни как ты собираешься использовать форму,
>  если у тебя в другом приложении нету никакого медиатора?
>
>


Дело обстоит приблизительно так, насколько я себе это представляю:

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

Форме пофигу, кто именно подписался и сколько их.
Если медиатор (в одном приложении) есть, он подпишется и форма будет слать ему сообщения, если нету (в другом приложении) - не подпишется и слать ему форма ничего не будет.


 
Игорь Шевченко ©   (2007-07-26 18:10) [77]

Sandman29 ©   (26.07.07 17:39) [72]

В любом приложении обязательно существует нечто, что определяет его структуру и механизма взаимодействия составных частей. В Delphi это традиционно главная форма или датамодуль, в других средах разработки это контроллер приложения (по Фаулеру) и т.п.

Вот оно и не переносится, ибо незачем. А все остальные потроха завязаны не так уж и сильно друг на друга, вполне себе переносимы. Особенно если это каркас, он же Framework.


 
Piter ©   (2007-07-26 18:13) [78]

Bless ©   (26.07.07 18:08) [76]

похоже на мой вариант, только подписчиком у меня является сама форма, а не медиатор.

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

Мне моя версия кажется более логичной. Источник сам объявит - "я умею делать вот это", а уж другие у диспетчера могут спросить "а есть ли тот, кто может сделать это". Большая степень абстракции, диспетчеру не надо знать вообще о всех, кто может сделать то или иное. Так мне кажется логичнее, на этом принципе построена система плагинов в Miranda.


 
Bless ©   (2007-07-26 18:26) [79]


> Piter ©   (26.07.07 18:13) [78]


Я никоим образом не хотел твою версию принизить или опровергнуть.
Просто показал, что наличие/отсутствие медиатора никак не усложняет повторное использование формы и ответил на [74] (хоть ты и не меня спрашивал), не более того.


 
Piter ©   (2007-07-26 18:30) [80]

Bless ©   (26.07.07 18:26) [79]
Я никоим образом не хотел твою версию принизить или опровергнуть


дык я об этом и не говорил. Просто два разных подхода

Bless ©   (26.07.07 18:26) [79]
Просто показал, что наличие/отсутствие медиатора никак не усложняет повторное использование формы


не. В указанных до этого версиях медиатора как раз без него не обойтись, там все жестко.

А с регистрацией источника события и "клиентов" - это уже чуть другое.


 
Kolan ©   (2007-07-26 18:36) [81]

> по-моему, любой класс должен быть как можно более самодостаточек
> (как раз с вашими минимальными числами связи).

И да и нет все зависит от конкретике. Если класс будет делать слишком много у него буде низкий уровень зацепления. ОО система это всегда система вз. меж собой классов.


> Ну и где тут модульность?

Каждый паттерн решает конкретную проблемму и создает другие. Например синглетон хз кто должен удалять.
Медиатор должен знать о коллегах. Тут ничего не сделать. так они устроены&#133

Можно пойти  дальше и сделать обозревателя. Тогда и тебя получится оюъект пр. области &laquo;Состояние вкл/выкл&raquo; и кто хочет от него зависеть юудут подключаться.


> Этот диспетчер тогда получится ядром программы в сложных
> проектах.

Именно, я так и сделал:
http://delphimaster.net/view/1-1183471965/

Имхо хороший вариант&#133


 
Bless ©   (2007-07-26 18:52) [82]


> не. В указанных до этого версиях медиатора как раз без него
> не обойтись, там все жестко.


да вроде нет. Без медиатора не обойтись приложению. А сами формы без него прекрасно обходятся и могут быть использованы повторно без изменений.


 
Piter ©   (2007-07-26 19:13) [83]

Bless ©   (26.07.07 18:52) [82]
да вроде нет. Без медиатора не обойтись приложению. А сами формы без него прекрасно обходятся


ну что ты такое говоришь. Был ясно указан пример:

На закрытие формы:
Mediator.Show(False);


Форма обращается к Mediator, нетрудно догадаться что это экземпляр класса TMediator, поэтому форма зависит от модуля, где объявлен этот класс. Никакой автономии формы для переноса.

Автономна она как раз будет в моем варианте, когда К НЕЙ обращаются с просьбой сделать вызов при наступлении того или иного события.


 
Bless ©   (2007-07-26 19:24) [84]


> Piter ©   (26.07.07 19:13) [83]


Ты прав. Я ветку просмотрел бегло, обратил внимание на [26], а [18] пропустил. От предложенно в [18] медиатора толку, имхо, немного.


 
Kolan ©   (2007-07-26 22:26) [85]

> Никакой автономии формы для переноса.

Видишь, то была просто галка и форма, то вот уже тебе надо решить задачу автономности. Ты определись что ты хочешь. Решения вытекаю из задач&#133


 
_Mike_   (2007-07-27 01:05) [86]

Ужас. А ответ был дан аж

>>Псалтырь   (26.07.07 02:10) [16]
>>TAction?

TAction OnUpdate + F1


 
Sandman29 ©   (2007-07-27 09:59) [87]

Piter ©   (26.07.07 17:58) [74]

А вот теперь объясни как ты собираешься использовать форму, если у тебя в другом приложении нету никакого медиатора?

Значит, будет :)
К тому же можно анализировать, присвоен ли медиатор. Аналогично тому как события обрабатываются - если есть обработчик, то вызывается, иначе - нет.


 
Sandman29 ©   (2007-07-27 10:11) [88]

Piter ©   (26.07.07 18:06) [75]

Медиатор не использует никаких главных форм! Он с интерфейсами работает (или с абстрактными классами).
В одном модуле описан интерфейс слушателя, в другом описан абстрактный медиатор. В идеальном случае слушатели ссылаются только на эти 2 модуля, используя фабрики для получения конкретных медиаторов.
В общем, почитай наконец теорию, на пальцах всё равно долго объяснять.


 
Sandman29 ©   (2007-07-27 10:19) [89]

Игорь Шевченко ©   (26.07.07 18:10) [77]

А с чего Вы взяли, что "главная" форма, обсуждаемая в данной ветке, именно главная? Она вполне может оказаться пятнадцатой по счету модальной формой :)
Главная она лишь по отношению к "дочерней", которую показывает.


 
Игорь Шевченко ©   (2007-07-27 10:20) [90]

Sandman29 ©   (27.07.07 10:19) [89]


> А с чего Вы взяли, что "главная" форма, обсуждаемая в данной
> ветке, именно главная?


Я этого не брал


 
Sandman29 ©   (2007-07-27 10:22) [91]

Kolan ©   (26.07.07 18:36) [81]

Медиатор должен знать о коллегах. Тут ничего не сделать. так они устроены…

Вовсе нет. Я уже писал:

with TFormCloseMediator.Create(ChildForm) do
 AddListener(MainForm).

Медиатор знает только то, что он должен подписаться на событие экземпляра TForm из конструктора и вызвать метод Listen всех подписавшихся слушателей.


 
exactly2   (2007-07-27 10:29) [92]

p.s.
киньте линки на книги Фаулерв в электронном виде


 
b z   (2007-07-27 11:04) [93]


> exactly2  

http://www.martinfowler.com/
это конечно не книги, но всетаки электронное :)


 
Kolan ©   (2007-07-27 18:38) [94]

> киньте линки на книги Фаулерв в электронном виде

http://www.uml2.ru./index.php
Тут куча книг по ОО. И все бесплатно.


> Вовсе нет.

Нет, тот что в GoF должен.


> что он должен подписаться на событие экземпляра

Это уже более продвинутые решения. От медиатора в них остается только идея.
Для ядра системы я пользуюсь чем-то таким:
 TSystemMediator = class
 strict private
   FColleagues: TColleaguesList;
   FCommandList: TCommandList;
   class var FInstance: TSystemMediator;
   constructor Create;
 strict protected
   procedure ProcessSavedCommands(CommandList: TCommandList;
     Colleague: TCustomColleague);
   procedure ProcessMediatorCommand(Command: TCustomCommand);
 public
   class function GetInstance: TSystemMediator;
   class procedure DestroyInstance;
   class function IsInstanceAssigned: Boolean;
   destructor Destroy; override;
   procedure SendMessage(Command: TCustomCommand);
   procedure Attach(Colleague: TCustomColleague;
     First: Boolean = False);
   procedure Detach(Colleague: TCustomColleague);
 end;


 
Piter ©   (2007-07-27 19:01) [95]

а я когда посмотрел ту ветку еще, стало интересно, что такое TCustomCommand?

Я думаю логичнее просто обозначать константы, начиная с нуля и далее.

В Miranda эти комманды являются строками, тоже свои преимущества, особенно для plugin системы.


 
Kolan ©   (2007-07-27 19:19) [96]

> особенно для plugin системы.

Для плагин системы эта архитектура просто супер. По суту вся программа-набор плагинов. Причем плагины могут делать все что угодно&#133


> В Miranda эти комманды являются строками

Дык это команданая строка какаято :).


> стало интересно, что такое TCustomCommand?

TCustomCommand = class
 strict private
   FAutoDestroy: Boolean;
   FProcessed: Boolean;
 public
   function CommandName: string; virtual;
   constructor Create;
   function This: TCustomCommand;
   property AutoDestroy: Boolean read FAutoDestroy write FAutoDestroy;
   property Processed: Boolean read FProcessed write FProcessed;
 end;


Это просо объект.



Страницы: 1 2 3 вся ветка

Форум: "Прочее";
Текущий архив: 2007.08.26;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.89 MB
Время: 0.045 c
15-1180857262
Zagaevskiy
2007-06-03 11:54
2007.08.26
Кто что думает?


15-1185293461
Slimer
2007-07-24 20:11
2007.08.26
Джойстик вместо мыши


15-1185519203
Сатир
2007-07-27 10:53
2007.08.26
Восстановление клиента Оракла


11-1168515485
Mabia
2007-01-11 14:38
2007.08.26
Установка Report&amp;Print в D6


15-1185260598
boriskb
2007-07-24 11:03
2007.08.26
"Кысь"





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский