Войти
ПрограммированиеФорумОбщее

статья Compile-time vs. Run-time

Страницы: 1 2 324 25 Следующая »
#0
17:25, 29 июля 2003

Compile-time vs run-time: назад в будущее

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

А чем так плохо наследование?? (и, если можно, пример злоупотребления этой техникой).

Таким образом, то, что автор описывает уже не объектно-ориентированную систему, правильно я понял?? И (если правильно), использует ли эта техника ОО в качестве реализации своих "частностей", если можно так выразиться...ну как процедурное программирование используется для локальных задач ОО.

Заранее спасибо.

#1
18:10, 29 июля 2003

Вообще, неплохое введение в вопрос дано в GoF ("Шаблоны проектирования").

Общая идея в том, что наследование фиксирует взаимоотношение классов на этапе компиляции, что приводит к их жесткой сцепке.
Собственно, ничего плохого в этом нет, пока это именно то, что тебе надо (тогда сцепка - cohesion).
То же самое - с вызовом функций. Чтобы ее вызвать, надо знать 1) у кого 2) что.

В общем, рано или поздно, cohesion превращается в coupling.

Почитай выступление Алекса Дюрана из Ion Storm на GDC 2003:
http://www.ionstorm.com/GDC2003/AlexDuran/AlexDuran/GDC_BOS.ppt
там много полезного

#2
18:25, 29 июля 2003

aruslan
the page cannot be found

GoF - автора, если можно :))

Так вот я и спрашиваю: можно 2 примера кода с грамотным наследованием и со злоупотреблением. Вот, например, классический Страуструповский Shape с наследующими Triangle, Circle, Square (наследование _только_ интерфейса) - это грамотно или неграмотно?? Если нет - как по-другому??

Если позволяет время, посмотри остальные вопросы - очень хочется разобраться 8))

#3
18:47, 29 июля 2003


new
GoF = Gang of Four = http://c2.com/cgi/wiki?GangOfFour

Наследование (как принцип) - это инструмент. Он не может быть грамотным или нет.
А вот использование этого инструмента (особенно множественного и виртуального наследования) требует аккуратности и выдумки.

По поводу примера. На скорую руку, так что не обессудь.

1 (из Дюрана):
У тебя есть базовые классы: renderable, AI, task.
У тебя есть классы door, player, guard.
Будет door иметь AI или нет - это не вопрос статической структуры классов. Это вопрос контента.
Здесь бесполезно строить иерархию - необходима композиция.

2.
Берем Страуструповский Shape. Насколько я помню, там был virtual void Draw() =0.
Для простоты возьмем цепочку наследований Shape - Triangle.

Берем GDI, Direct3D и OpenGL. Надо реализовать Draw().
Получаем три параллельные иерархии:

Triangle : Shape, причем Triangle сам по себе имеет Draw()=0.
Заметь, что в Shape нет ничего.
В Triangle есть только вершины треугольника. Draw() не определен, поскольку ты не знаешь под чем его рисовать.

Пусть есть GDIShape (хранит HWND, HDC, ну в общем не важно, главное, что-то хранит).
Пусть есть D3DShape (опять же, где-то нужна ссылка на интерфейсы D3D).
Пусть есть GLShape (для общности).
Обрати внимание, что мы можем унаследовать его (виртуально) от Shape. (Впрочем, можем и не наследовать :))

Как сделать Triangle для GDI?
Пусть будет GDITriangle : GDIShape, Triangle.

Проделай все это для всех трех рендеров.
В худшем случае ты получаешь компот из трех сильносвязанных иерархий.

#4
18:58, 29 июля 2003

aruslan
а, ну да, Банда Четырёх... :)) Спасибо.

1. А кому в голову может прийти пронаследовать door от AI??
[исправлено]
( ну да, понял, ты имел в виду - бесполезно пихать door, guard, player в одну иерархию... )
[добавлено]
о какой композиции идет речь в данном случае??

2. Да... Ботва. А шо ж делать?? Снова шаблонами??
И кстати, в чем проблема сильно связанных иерархий??

3. Тык он наследования ты предлагаешь совсем отказаться??
(кстати, а как насчет примера разумного использования inheritance?? ;)

Спасибо.

ЗЫ http://www.ionstorm.com/GDC2003/AlexDuran/AlexDuran/GDC_BOS.ppt
не работает

#5
19:10, 29 июля 2003

new
Поправка: http://www.ionstorm.com/archives/oldIon/gdc2003/default.asp

1. Пришло, когда потребовалось поговорить с дверью :)
2. Я ни в коем случае не предлагаю отказаться от наследования, это просто смешно :)
Напротив, я просто предлагаю пользоваться им по назначению.
Просто гибкость иногда нужна. А иногда - нет.
В каждом случае это решается отдельно (собственно, это и называется проектированием).
Что я предлагаю, так это уменьшение стоимости ошибки (если это ошибка) и увеличение гибкости - каждый
клиент может определить для себя, что ему надо. А движок ты пишешь один раз.

Пример разумного наследования?
Ну, например, Shape - Triangle :)
Тут ведь проблема не в наследовании, а в том, что в данной конкретной задаче я изначально повел тебя не тем путем.

#6
1:30, 30 июля 2003

aruslan
spasibo bol`shoe chto podnyal etot vopros i potratil vremya chtob podelit`sya muslyami iz svoego oputa ...
tut na forume eta tema redko podnimaet`sya ....
horoshaya ochen` stat`ya ... no eta tema ne dlya dvuh stranic ... eto celaya nauka ... pravil`naya arhitektura mojet sekonomit` v budushem nemeryannoe kolichestvo chasov ... a ne pravil`naya mojet privesti k polnomu perekodirovaniyu vsego i vsya ... mu postoyanno lyubim perepisuvat` svoi dvijki s nulya ... pochemu ? potomu chto kajduy raz kogda zakanchivaesh` kakoy to bol`shoy proekt tu vurostaesh` ... imenno vzrosleesh`, esli eto tvoya global`naya ideologiya ... tu nachinaesh` chustvovat` pod konec , chto mojna bulo luch`she organizovat` eto ... no vremeni uje ne ostaetsya ... bulo bu navernoe horosho otkrut` forum na gamedev.ru po problemam global`nogo proektirovaniya arhitekturu dvijkov ...

P.S. sorry za translite ....

#7
10:18, 30 июля 2003

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

Ну и общие фразы про наследование, шаблоны...
ИМХО, нужен более конкретный пример %). И - я не наезжаю, просто хочу разобраться.. Да, согласен, что "GDITriangle : GDIShape, Triangle" выглядит отвратно, а "Triangle: Shape" жить будет.. но вот конкретно что ты имеешь ввиду под сompile-time - какие техники - не понятно (чем она от метапрограмминга и ООД в общем случае, отличается)?

#8
10:39, 30 июля 2003

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

>У тебя есть базовые классы: renderable, AI, task.
>У тебя есть классы door, player, guard.
>Будет door иметь AI или нет - это не вопрос статической структуры классов. Это вопрос контента
А слабо door/player/guard наследовать от одного unknownobject у которого хватит места для ссылок на renderable,AI,tack..

#9
10:45, 30 июля 2003

hate
Спасибо, за объем статьи сорри, не был уверен, что тема вообще интересна совсем широкой общественности.
Просто надоело играть в испорченный ICQ, захотелось иметь единое место для обсуждения.
gamedev.ru был очевидным и удачным :)

doig-u
Пример действительно не вполне удачен, просто нормальный (жизненный :)) пример потребовал бы куда большего объема статьи.
Впрочем, этим я сейчас и занимаюсь, так что ваша конструктивная критика будет весьма ценной!

Дело не в реорганизации кода, кэшировании на более низком уровне и т.п.  Жаль, если этот момент прозвучал невнятно.
(Впрочем, на КРИ народ меня, кажется, понял, может в http://aruslan.nm.ru/external/kriconf_aosrkmi_final.ppt мысль выражена яснее?)

Вот ты считаешь, что это странно.  Что это против OO.  Почему?
С точки зрения OOA/D/P, если игровой программист думает о самолете как об объекте, имеющем box как свойство,
то хороший движок должен дать ему интерфейс к самолету ровно той ширины, которой необходимо - не шире, не уже.

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

Кашей
Я не предлагаю смешивать с чем-то шаблоны (наоборот, крутые извраты с #define и прочими сильными средствами уродуют код, как правило).
Это просто не выполнит необходимых задач.
Мы просто описываем объекты так, как мы их видим в отдельных файлах описаний, а кодогенератор
генерирует все необходимые h/cpp и т.п. для нашей работы.

Более того, этими же файлами пользуются все инструменты движка - при экспорте, если крыла нету - ничего не сэкспортируется.
Сборщик ресурсов создаст оптимальный memory layout для объектов на основе их описания.

А слабо door/player/guard наследовать от одного unknownobject...
Давай вообще все унаследуем от CObject (или object, или IUnknown :))? Прикольно же получится.
А дальше что? QueryInterface? dynamic_cast? касты в стиле java?

#10
11:16, 30 июля 2003

aruslan
Виртуальные функции и реальные сообщения.

Хотя кодо генератор вешь забавная.
Тоесть вы описываете обьект и этот генератор генерит файлы именно для этого обьекта, при этом более менее оптимально?

Хотя на самом деле тут очень много зависит от самой идеи постоения внутренестей системы.

>А дальше что? QueryInterface? dynamic_cast? касты в стиле java?
В любом случае надо зафиксировать функциональность системы.
Компонент не может выполнить что-то что не предусмотрено системой.
Если вы реализовываете что-то сверх того что было вами придумано вы должны имень возможность это "что-то" использовать.

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

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

#11
11:28, 30 июля 2003

Кашей
Виртуальные функции не помогут.
Мы говорим о движке, который пишется один раз.
И об играх, использующих движок.

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

Предлагается дать игровым программистам возможность самим определить, что им надо, а что нет.

По поводу оптимальности результирующих структур - см. доклад на КРИ.

Основные проблемы, которые решает данных подход:
1. Отсутствие необходимости принимать решения на этапе разработки движка (заранее и за игрового программиста)
2. 100% гарантии целостности ресурсов
3. Возможность мощной оптимизации контента, поскольку вся информация на руках

#12
11:49, 30 июля 2003

Теперь понял.
У меня это было реализованно немного по другому.
Свою систему я строил изначально распределеной
Если взять пример с крылом самолета то будет выглядеть примерно так
PlaneInterface = Plane.GetInterface(_PLANE_INTERFACE)
PlaneInterface.OnDataIncoming = somefunc;
PlaneInterface.SendRequest(_GET)
return;

somefunc
работает с данными интерфейса.

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

после того как даные прийдут и попадут в свои поля можно с обьетом работать.
Если обьекта крыло нету - данные не прийдут, прийдет Cansel и интерфейс будет уничтожен.
Ограничение свойств я преоделел обычным switch
сначало обьект определяет все свои экспортируемые параметры и функции, потом делает свич для обработки сообщений.
главное наследовать обьект от CBase. А так пока 2 функции - SendMsg,ResiveMsg;

Работает на ура. Спер примерно это систему с работы, тут тоже на ура работает. Плюс в том что все распределяется как на сеть ,так и на много процесоров.

#13
11:58, 30 июля 2003

Кашей
Описанный тобой подход применим лишь в определенных ситуациях (кстати, очень редких).
Проблема в том, что пока у тебя единый (в смысле, единственный) интерфейс к самолету, то все хорошо.
Но, есть 2 но:
1. Разным людям от твоего самолета нужны разные вещи.
Ты их изначально ограничиваешь твоим представлением об их надобностях.
2. Разным подсистемам от твоего самолета нужны разные вещи.
А как бы сделал интерфейс к самолету в рендере? Ввел бы в _RENDER_OBJECT_INTERFACE интерфейсы _RENDER_PLANE_INTERFACE? ;)

#14
12:22, 30 июля 2003

У меня все просто, хотя конечно ограничения есть, и сильные.
В своей системе я сделал эмуляцию CORBA.
Сам обьект сидит на сервере.
Потом он посылает клиенту команду\параметы фабрики и клиент создает этот же обьект.
после чего сервер пересылает клиентскому обьекту все свои свойтва и их значения, на этом этапе происходит синхронизация номером свойств.
С этого момента обрашение на клиенский обьект транслиуются на сервер и результат транслируется обратно.
Когда мы просим клиентский обьект(интерфейс серверного) создать интерфейс  мы указываем номера экспортируемых параметров или методов.
Происходит синхронизация обьектов тока по этим поляем.
Насчет того что с кем синхронизировать я честно говоря не решил. В моем случае интерфейс синхронизируется с клиенским обьектом, хотя может и с серверным.
Эта операция требудет как минимум один такт главного цикла.

итого
>1. Разным людям от твоего самолета нужны разные вещи.
>Ты их изначально ограничиваешь твоим представлением об их надобностях.
Огранициваю параметрами самолета, запросишь что-то сверх - ничего не получишь. Меньше - пожалуйста.
>2. Разным подсистемам от твоего самолета нужны разные вещи.
>А как бы сделал интерфейс к самолету в рендере? Ввел бы в _RENDER_OBJECT_INTERFACE интерфейсы >_RENDER_PLANE_INTERFACE? ;)
Интерфейс предопределен - ему даются имена параметров, на этапе создания первого экземляра обекта имена заменяются номерами.

Для рендера обьект имеет тока свойство Draw(точнее подсоединяет себя как Sourse и выдает набор команд для своей отрисовки) . Все предварительные подготовки обьекта выполняет scene graph имея позицию и ориетнацию обьекта как ВСЕГДА сушесвуюшее свойство. И он(рендер) работает с обьектами на прямую.
Если обьект не имеет этих свойств - проверте код, обьекту не место в этом секторе, отправляйте его в другой рендер.

Страницы: 1 2 324 25 Следующая »
ПрограммированиеФорумОбщее

Тема в архиве.