информационная безопасность
без паники и всерьез
 подробно о проектеRambler's Top100
Атака на InternetГде водятся OGRыSpanning Tree Protocol: недокументированное применение
BugTraq.Ru
Русский BugTraq
 Анализ криптографических сетевых... 
 Модель надежности двухузлового... 
 Специальные марковские модели надежности... 
 Бэкдор в xz/liblzma, предназначенный... 
 Три миллиона электронных замков... 
 Doom на газонокосилках 
главная обзор RSN блог библиотека закон бред форум dnet о проекте
bugtraq.ru / форум / programming
Имя Пароль
ФОРУМ
все доски
FAQ
IRC
новые сообщения
site updates
guestbook
beginners
sysadmin
programming
operating systems
theory
web building
software
hardware
networking
law
hacking
gadgets
job
dnet
humor
miscellaneous
scrap
регистрация





Легенда:
  новое сообщение
  закрытая нитка
  новое сообщение
  в закрытой нитке
  старое сообщение
  • Напоминаю, что масса вопросов по функционированию форума снимается после прочтения его описания.
  • Новичкам также крайне полезно ознакомиться с данным документом.
[C++] Спасибо за мнение 31.07.03 10:49  Число просмотров: 1781
Автор: void <Grebnev Valery> Статус: Elderman
<"чистая" ссылка>
Хотел было кинуть ответ в «приват», но как ни искал «приват», не нашёл. Вероятно, в движке форума этого нет? В «приват», т.к. думаю мой пост вряд ли будет интересен другим. Там, ниже – я почти по всем пунктам согласен.

********************
>>Небольшое замечание: на самом деле такой "нудный код" тоже является признаком плохого >>стиля. Уже хотя бы потому, что при добавлении нового объекта, менять нужно не только в том >>месте, где производится собственно добавление (что неизбежно), но и в данном (и других, >>потому как код нужно добавлять не только для ClearControls) обработчике. То же самое и с >>удалением.

Согласен – натяжка;)). Ну уж очень хотелось;)))



********************
>>Вывод: везде, где родителю необходимо что-то сделать со ВСЕМИ своими детьми (если >>количество больше 2-3-х), я ПРОЕКТИРУЮ класс так, чтобы родитель мог ПЕРЕЧИСЛИТЬ всех >>своих детей в цикле. Количество кода стремительно уменьшается. И при добавлении/удалении >>детей изменениям подвергается только само место добавления (удалять можно тоже >>перечислением).

Согласен при ~ >= 3. А так, можно и «нудным кодом».



********************
>>Еще раз напомню, что развитие парадигм программирования шло именно по пути уменьшения >>связей между частями программы. И даже если ООП ничего не говорит о таком подходе, важно >>понимать, куда именно движется программирование и соответсвовать, так сказать. То, что при >>подходе с перечислением уменьшается количество связей, думаю объяснять не стоит. Тем >>более что в этом вопросе никто не собирается вставлять палки в колеса. Все системные >>контейнеры (взять окна, tab control-ы и др.) хранят список дочерних объектов и предоставляют >>возможность их перечисления, если ты при проектировании своего класса будешь поступать так >>же - будет тебе счастье :-)


Понятно. Твой пример о TabCtrl, для которого я ранее сделал перепост, думаю, всё равно, будет полезен для многих программеров. Хотя, сам я делаю немного по другому, т.к. мне недостаточно только lparam – мов для пейджей. В неком CTabPageCtrl:public CTabCtrl у меня есть мембер-массив структур, который хранит кроме указателя на диалог пейджи ещё разную ерунду, которая мне необходима для работы с БД. Понятно, что и в этом случае, можно было обойтись lparam, присваивая ему адрес этой структуры, для которой делаем new в ран-тайм, когда вставляем пейдж. Но для такой мелочёвки мне было удобнее тупо, по быстрому и надёжно. Как обрабатывать перечисления – дело вкуса, имхо.



********************
>>Причем сказанное выше касается КАЖДОГО из родителей. Вплоть до диалога, который может >>выключить всех своих детей при помощи EnumChildWindows. Кроме того, как ленивый >>программист, я пытаюсь вынести общий код как можно выше в базовые классы. То есть >>добавлять/перечислять всех детей однотипных объектов одной и той же функцией (а не >>похожей, или даже copy/paste-нутой). То есть сделать, например, класс страницы, которая умеет >>выключать всех своих детей перечислением в for-е и отнаследовать все страницы от нее. >>Главное не переусердствовать и не вводить в иерархию ничего натянутого. Например, если >>способ перечисления для окна существенно отличается от способа перечисления для >>табконтрола, то не стоит пытаться сделать им общую базу только для того чтоб "вынести как >>можно выше". Связь база-наследник должна появляться только в том случае если анализ >>выявил такую связь. То есть надо стараться, но знать меру.

В начале 90-х мне надо было прикрутить графической «интерфейс» кастомизированного приложения в среде AutoCad 11.0 (досова штука). Писал в то время исключительно plain C,
хотя уже и был Турбо С++ 1.0. Поскольку это был плайн-С, а без абстракций – никуда, то многообразие данных моделировалось указателями на структуры данных, а многообразие методов – указателями на структуры функций. Для моделирования эламентов GUI ( в графике!!!! , под ДОСом. В то время – кул!!!) я именно ЭТО и делал (то, о чём ты говоришь). Т.е. выстраивались двусвязанные списки, которые были «контейнерами», и в которые «ставлялись» кнопки, диалоги и т.д. Там и были перечисления «контролов», которые обрабатывались в цикле. Были там и FillControls вместе с Дисплеем;))

Для чего я это рассказываю? Было всё это непросто. Хотя и работало. Не поверишь – даже продать удалось в одну контору (в единственном экземпляре)!!! Но вот посоветовать пойти по этому пути другим – у меня не хватает духу. Очень уж тернистый путь. Опасаюсь я, что это простое решение, которое можно отсоветовать кому-либо. Опасаюсь, т.к. помню ту головную боль. Но согласен – если сделать, то будет счастя. Может и так. Всёж С++ на дворе, не плайн-С.



********************
>> Если в «ЧИСТО ООП» переход в новое состояние всегда
>>выполняется, начиная с рут (например, theApp), как было
>>Самое интересное, что в данном случае переход в новое состояние начинается тоже с рута, >>которым в данном случае является мессенгер и дальше вниз по иерархии. Такой подход имеет >>право на жизнь. Так как хотя в принципе могут регистрироваться все (расплющивая иерархию в >>одну горизонталь), но реально регистрируются только ключевые объекты, которые на самом >>деле можно считать и так находящимися на одном уровне (и в мессенгер они попадают тоже на >>один). А иерархия при этом не разрушается.

Плохо то, что для «…иерархия при этом не разрушается…» очень много перекладывается на «вменяемость» программера;))



********************
>>НО!!! Единственный реально необходимый пример такой архитектуры, я вижу в том, чтобы >>иметь несколько мессенгеров. То есть иметь несколько разных частей приложения в разных >>состояниях.

Если ты заметил, то мессангер я для этого и сделал без сингентона. Хотя последнее очень красивое слово (это тоже паттерн). С Singleton–ном – это у того программера, для кода которого я сделал перепост в «шагах».



********************
>>Добавлять в список нужно не путем регистрации, а прямо при создании объекта. То есть >>родитель (приложение) создает детей (виды и др.) и тут же добавляет их в список. >>Терминология немного прихрамывает, потому как динамические родитель-ребенок отличаются >>от статических база-наследник, по крайней мере, то что Я называю так, имеет разную основу. >>Родитель - это контейнер, хранящий детей (и умеющий добавлять/удалять их), а база - это >>просто базовый класс, который выражает утверждение, что наследник ЯВЛЯЕТСЯ кроме всего >>прочего и базой. То есть родитель-ребенок это связь типа мессенгер-подписчики (то есть >>содержит), а база-наследник - типа окно-диалог (то есть является). Короче родитель и ребенок >>это объекты, а база и наследник - классы. Так вот эти дочерние объекты должны иметь общий >>базовый класс и переопределять виртуальные функции реакции на некоторые события (о >>которых им будет сообщать родитель путем вызова этих функций).

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

Если это совет другим, кто читает пост – то ???????????? Люди поделают, поделают, а потом будут пилюваться в нас и костерить.



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

Это и есть ОБЯЗАТЕЛЬНАЯ разрегистрация, когда подписчик уходит со сцены;)))



********************
>> Как это делается смотри виндовый LIST_ENTRY и сопутствующие макросы.

Думаю, что это мелкософт у меня «посмотрел»;)))
Когда я это делал для досовых задач в плайн-С, виндовз ещё не было. Я постил, чуть выше.
Шучу, конечно.



********************
>>А ребенок в деструкторе (деструкторе той самой базы) сам удалится из списка.

Мессангер так и работает, в смысле в деструкторе.



********************
>> Разрегистрацию можно и ввести, но только для динамического изменения топологии дерева, по >>которому проходят сообщения (то есть для случая: ребенок остался, но не хочет получать >>сообщения).

Кстати да. Хотя мне трудно придумать, где это может быть на практике – «…ребенок остался, но не хочет получать сообщения ….»


********************
>>Я же предпочитаю не надеяться на сознательность. Может быть даже я сам когда нибудь забуду >>о том, из каких побуждений я исходил и какие предположения делал. Если мне просто запретят >>делать, то что нежелательно - я вспомню быстрее :-)

То, что и меня это смущает, я уже постил.


********************
>>Но вот даже при "чистом ООП" можно ограничиться одним вызовом, а не "нудным кодом". Я >>привел пример с CPage-ем. Оставаясь иерархичным этот пример делал все в одном цикле. >>Точно так же любой контейнер может хранить однородный список своего содержимого, а не 20 >>указателей на разные типы. И это не будет отходом от ООП, потому что данный список >>создается и поддерживается самим контейнером, и в него не может попасть никто посторонний. >>В случае с мессенгером - может, но ты лично решил этого не делать, что и придает твоему >>приложению видимость ООП.

1) Если контейнер будет мессангером, то для такого КЛАССА можно в принципе по ООП-вски определить его поведение – каких деток он умеет включать в свой список подписчиков.

2) Если сделать п.1, ДАЖЕ ЕСЛИ ОБЪЕКТЫ БУДУТ РАЗНЫХ КЛАССОВ, то всё равно будет по ООП-вски, т.к. грубо говоря, будем в цикле говорить всем – «нарисоваться», и все нарисуются в соответствие с поведением своих классов.



********************
>>Вывод: текущий вариант можно доработать, подвергнув минимальным изменениям. То что >>рассылка сообщений вынесена в отдельный класс - хорошо (как сказал далай-Страутсруп: как >>можно большее количество сущностей должно иметь свой класс :-) ). Но то, что мессенгер один >>и глобальный - плохо. Нужно отнаследовать приложение от мессенгера и регистрировать >>подписчиков прямо при создании (этих подписчиков). Причем регистрироваться должен не сам >>подписчик, а родитель может зарегистрировать своего ребенка в качестве подписчика на >>сообщения СВОЕГО мессенгера.
>>Стоит упомянуть, что классы всех контейнеров, которые не могут напрямую перечислить свое >>содержимое (как табконтрол или окно) следует отнаследовать от мессенгера (ну или мессенгер->>подобного класса).
>>Иерархия сохраняется, код упрощается, количество связей уменьшается, добавление объектов >>с разных уровней иерархии в один мессенгер не НЕЖЕЛАТЕЛЬНО, а НЕВОЗМОЖНО, короче >>все счастливы и все работает.

Да. Надо попробовать. То, что от мессангера можно будет отнаследлваться, в любом классе, понятно. Надо подумать, как сделать так, чтобы такой класс будет одновременно отнаследоваться от подписчика. Это надо, так как сам контейнер, может быть включён в контейнер «выше».

PS. В очередной раз спасибо.
<programming> Поиск 






Rambler's Top100
Рейтинг@Mail.ru


  Copyright © 2001-2024 Dmitry Leonov   Page build time: 0 s   Design: Vadim Derkach