Component-oriented design на консолях, лобзиком по шаблонам

Сегодня в нашей постоянной рубрике “классические отжыги на конале” будут Борины сказки про компонентные системы, console-style. Сказки долгие и хорошие, как раз на ночь.
Отжыг давний, еще с 2005-го года.

Краткие пояснения:
TK – теоретика кайфа
Gauntlet – Gauntlet: Seven Sorrows, Midway

Итак…

<look4awhile> могу рассказать – как это всё легко и дёшево “слепить”
<CEMEH> Ага.
<look4awhile> с прелюдией и интермиссией
<look4awhile> итак прилюдия
<look4awhile> проект на 3 хуятора
<look4awhile> SomeRender
<look4awhile> SomeGameCode
<look4awhile> SomePhysics
<look4awhile> тупо так
<look4awhile> классическая такая ситуёвина.
<look4awhile> может даже есть глав программист, который при этом ещё и архитектор
<look4awhile> и он говорит
<look4awhile> class CObject
<look4awhile> class CActor
<look4awhile> class CAnimatedActor
<look4awhile> class CGameAnimatedActor
<look4awhile> class CPhysicsDrivenAnimatedActor
<look4awhile> итд итп
<look4awhile> кучу проектов видел с этой гадкой древовидной хуйнёй
<look4awhile> особенно CObject
<look4awhile> всякие virtual void Serialize ( …
<look4awhile> итд итп
<CEMEH> Ага.
<look4awhile> потом вся эта доблестная куча народу по этим заебательским прикидкам садится за прототип
<look4awhile> и пишет
<look4awhile> class CRenderObject, тупо так
<look4awhile> который рисует меши
<look4awhile> class CPhysicsObject
<look4awhile> не менее тупо колсолвит сферу в мире
<look4awhile> class CGameObject – в котором есть health, и virtual void Death
<look4awhile> а далее все говорят “уря”
<look4awhile> и наступает
<look4awhile> class CBall : public CRenderObject, public CPhysicsObject, public CGameObject
<look4awhile> и ещё где-то там CObject и CSerialize
<KVaks> hi
<look4awhile> привед
<KVaks> ugosi raskazivajesh ?:)
<look4awhile> их
<look4awhile> продолжу
<look4awhile> далее подонки дружно говорят “заебись”, и сосут у друг-дружки писюльки. до тех пор пока…
<look4awhile> не приходит геймдизайнер и говорит
<look4awhile> надо мячика рисовать красным, когда стукнулся об стену
<look4awhile> и отбавлять 20% здоровья
<look4awhile> “нехуя” говорят подонки, и пишут такое
<look4awhile> void PhysiscObject::OnCollide ( void ) { SetRenderColor(RED); };
<look4awhile> а потом охуевают
<look4awhile> потому как SetRenderColor – это от CPhysiscObject
<look4awhile> вру
<look4awhile> от CRenderObject
<look4awhile> после чего делается например вот так
<CEMEH> А почему охуевают?
<look4awhile> void CPhysiscObject::OnCollide ( CRenderObject * pRender ) { pRender->SetRenderColor(RED); }
<look4awhile> а потом думают, где брать CRenderObject
<look4awhile> и либо кешат его прям в CPhysiscObject
<CEMEH> Казалось бы, пишут void CBall::OnCollide () { SetRenderColor (RED) }
<look4awhile> именно!
<look4awhile> заебись!
<look4awhile> либо пишут строго то, что ты написал
<look4awhile> virtual CBall::OnCollide
<look4awhile> далее приходит геймдизайнер и говорит
<look4awhile> “а надо-бы чтобы если у него меньше 5% здоровья, то он мигал”
<look4awhile> “нихуя” говорят падонки
<look4awhile> и пишут
<look4awhile> void CBall::OnTick ( ) { if ( GetHealth() <20 ) CRenderObject::Blink(); }
<look4awhile> либо прям в CRenderObject пишут аксесор в CGameObject
<look4awhile> падонков всего 3-е, и за пивом они благополучно обсуждают – кто у кого и что вызывает
<look4awhile> более того, говорят “нихуя” и в CBall пишут все всякое по мере поступления идей от геймдизайна
<look4awhile> после чего ещё через неделю вдруг всплывает мячик, который пролетает через стены
<look4awhile> а так-же невидимый мячик. который видно когда у него мало здоровья
<look4awhile> и ещё один мячик – который двоится при соударениях странно
<look4awhile> после малого рефактора всплывают
<look4awhile> CBall, CInvisibleBall : CBall, CUncollideableBall : CBall
<look4awhile> после чего приходит глав-художник и говорит
<look4awhile> “а вот это огненный шар. он не с мешем, а с партиклами”
<look4awhile> и ещё через неделю йобли прототип оживает
<look4awhile> при этом уже совершенно непонятно где какой код
<look4awhile> и кто откуда и что копипастил
<look4awhile> заасим наступает интермиссия
<look4awhile> пока всё понятно? возражения есть? рвотные позывы? дежавю?
<KVaks> fse eto prisutstvujet :)
<CEMEH> Возражений нет, дежавю нет, такого кода почти не писал.
<CEMEH> Точнее, писал, но пока не рефакторил :)
<look4awhile> я тоже писал. и заебло. в года далёкие
<look4awhile> после чего было принято волевое решение
<look4awhile> а именно
<look4awhile> такой хуйни не писать. и при этом не проектировать заранее
<look4awhile> при этом надо чтобы все работали над своим кодом
<look4awhile> и не надо проблем “времени интеграции”
<look4awhile> вот такое вот хочу
<look4awhile> идеальный код в таком раскладе должен выглядеть так
<look4awhile> void CPhysiscObject::OnCollide () { if ( IsRenderObject() ) { SetColor(RED); } else { // do nothing } };
<look4awhile> т.е. банально хочется лазить куда угодно и как угодно
<CEMEH> Точно CPhysicsObject, а не Ball?
<look4awhile> точно PhysiscObject
<look4awhile> хуже даже
<look4awhile> может быть
<CEMEH> А если хочется только для шарика?
<look4awhile> if ( IsRenderObject() && IsBall() ) { SetColor(RED); }
<look4awhile> более того runtime cost на такое не хочется вообще
<look4awhile> т.е 0 тактов – обязательное ограничение
<look4awhile> а именно IsRenderObject && IsBall – константы времени компиляции
<CEMEH> На такое – это на всякие if?
<CEMEH> Ага.
<look4awhile> на любое
<look4awhile> если я пишу
<look4awhile> SetColor(RED);
<look4awhile> или даже
<look4awhile> m_Color = RED;
<CEMEH> Это тоже 0 тактов?
<look4awhile> невидимого overhead-а быть не должно
<look4awhile> никакого abstraction penalty кроме привычного С++ abstraction penalty
<look4awhile> т.е. как раньше писал, так и хочу писать
<look4awhile> обычный, совершенно влобный код
<CEMEH> Ок.
<look4awhile> который влоб компилится
<look4awhile> хуже – он должен быть const correct при этом
<look4awhile> ещё хуже – надо иметь внятный метод борьбы с code-bloat. т.е. вживую указывать
<look4awhile> будет ли код генериться под instance или нет
<look4awhile> и если нет, то иметь минимальный runtime cost
<CEMEH> Как это – код генерится под instance?
<look4awhile> т.е. virtual, и не более
<look4awhile> а вот так
<CEMEH> А, понятно.
<look4awhile> если есть CBall и CInvisibleBall
<CEMEH> Т.е. берем мячик, назначаем параметров, говорим – это codegen.
<look4awhile> то решать – будет ли две функции для OnCollide, либо одна
<look4awhile> и, наконец, самый последний нюанс проблемы
<look4awhile> мы не пишем мегаинструмент. пишем игру
<look4awhile> т.е. если я решил сегодня так кодать, то начать смогу через 2 часа
<look4awhile> на банальном С++
<look4awhile> вот такие были мысли в голове примерно года 2 эдак назад
<look4awhile> теперь буду рассказывать про “как”
<look4awhile> только такой нюанс = я могу налажать с синтаксисом итд итп
<look4awhile> потому как пишу сюда из головы
<CEMEH> Все готовы.
<look4awhile> если потому будут вопросы – расскажу. но уже из кода
<look4awhile> ага?
<look4awhile> ну поехали
<look4awhile> итак банально
<look4awhile> template <class Gluer> class IRenderObject { void SetColor( Color ); };
<look4awhile> template <class Gluer> class IPhysiscObject { void OnCollide ( void ) { THIS->SetColor(RED); };
<CEMEH> THIS – это что?
<look4awhile> class CBall : IRenderObject<CBall>, IPhysiscObject<CBall> {};
<look4awhile> :)
<look4awhile> важный момет. в CBall своего кода собстенно нет
<look4awhile> это Gluer – т.е. буквально “клей”.
<look4awhile> мы банально пишем аспекты (или-же интерфейсы). мы не пишем в CBall всякое – оно там не надо.
<look4awhile> если оно там надо – то мы пишем template <class Gluer> class IBallAspect {};
<look4awhile> и самое интересное во всей этой истории, это тот самый THIS
<look4awhile> или-же CONST_THIS – в тех случаях, когда мы const correct
<look4awhile> идеи есть?
<look4awhile> :)
<CEMEH> Ну, тот самый Ball
<look4awhile> да.
<CEMEH> Который их всех наследовал.
<look4awhile> #define THIS static_cast<Gluer *>(this)
<CEMEH> Почему в этом случае невидимый мячик не станет мерцать? :)
<look4awhile> торопишься. годи
<look4awhile> тут масса всего ещё до “Невидимого” мячика
<look4awhile> то, что мы написали – не будет компилиться, если Gluer не относледовали от RenderObject, а только от PhysiscObject
<look4awhile> почему такое происходит, понятно?
<CEMEH> Ага.
<look4awhile> посему сразу возникает две задачи
<look4awhile> первая – прознать уноследовали-ли
<look4awhile> вторая – сделать так, чтобы всё компилилось в обоих случаях
<CEMEH> Ну, классические темплейтные C++=трюки.
<CEMEH> is_derived и т.д.
<look4awhile> is_derived – это здорово. если помнить про incomplete instantiation – то можно очень ровно бороть эту проблему
<look4awhile> писать 3 версии ф-ции с partial specialization – тоже можно
<CEMEH> Чтобы компилилось – специализации, да.
<look4awhile> можно ещё сделать accessor макрос
<look4awhile> т.е. банально
<look4awhile> declare_accessor(render_object);
<look4awhile> в загаловке класса
<look4awhile> а при юзе
<look4awhile> CRenderObject * THIS_RENDER_OBJECT = get_accessor(render_object);
<look4awhile> тупо так. по цене даже не виртуальной ф-ции, а inline ф-ции
<CEMEH> Ща…
<look4awhile> тогда оно и крассиво скомпилится, и падать будет с понятным exception-ом, и код почти такой, как хотелось
<CEMEH> Я не очень врубил, как это работает.
<look4awhile> ну смотри
<look4awhile> template <bool> CRenderObject * GetAccessor_CRenderObject (void);
<CEMEH> А, угу.
<look4awhile> template <> CRenderObject * GetAccessor_CRenderObject<true> (void) { return static_cast<CRenderObject *> (this); }
<look4awhile> итд итп
<CEMEH> А флаг – enum’ом?
<look4awhile> а в конце CRenderObject * GetAccessor_CRenderObject_Fn ( void ) { return GetAccessor_CRenderObject< is_derived<..>> (); };
<CEMEH> А declare зачем?
<CEMEH> А, генерять эти функции.
<CEMEH> Понял.
<look4awhile> внятно обернуть в макросы. чтобы родило все 4 функции
<look4awhile> точнее 5 даже
<look4awhile> чтобы IsRenderObject() тоже родило. в enum
<look4awhile> или в const bool
<look4awhile> как больше нравится
<look4awhile> практика показывает, что компилятору совсем всё равно
<look4awhile> далее
<look4awhile> class CRenderObject; template <class Gluer> class IRenderObject : public CRenderObject;
<look4awhile> это несколько более внятный вариант
<look4awhile> потому как душит code bloat
<look4awhile> ибо всякий non-instanceable код идёт в CRenderObject
<look4awhile> и, наконец
<look4awhile> можно парой макросов лазить из CRenderObject ( не из IRenderObject ) в куда угодно
<look4awhile> по цене вирт. функции
<look4awhile> ага?
<CEMEH> Ага.
<look4awhile> там есть мал-мала мелких нюансов
<look4awhile> например вместо пары cpp\h теперь cpp\h\i
<look4awhile> потому как надо бороть incomplete instantiation стабильно
<look4awhile> опять-же чуть-чуть доп. правил при написании вот такого
<CEMEH> Мы уже подошли к тому, почему невидимый мячик не блынькает?
<look4awhile> template <class Gluer> class ISomething : ISomethingElse<Gluer>, IOther<Gluer> {} – впрочем такое писать не надо
<look4awhile> невидимый мячик не блинкает, потому что
<look4awhile> class CInvisibleBall : public IPhysiscObject<CInvisibleBall>, public IGameObject<CInvisbileBall> {};
<look4awhile> а рендера там просто нет
<look4awhile> банально так
<CEMEH> Хитрый, да…
<look4awhile> всё это добро отлично работает на большом проекте
<look4awhile> code warrior на PS2 всё это ест с неменьшим удовольствием
<look4awhile> кода получается значительно меньше, чем при обычном подходе
<look4awhile> и просится в статью – если бы у проекта были шансы получиться прибыльным. или хотя-бы удачным
<look4awhile> думаю, что статьи не будет, впрочем
<look4awhile> ещё думаю что тот aruslan меня раскритикует вусмерть с таким подходом
<look4awhile> не знаю правда где
<look4awhile> вот вроде теперь и всё
<look4awhile> .
<CEMEH> Ну, наверное, не все свойства объекта хорошо ложатся на есть/нет.
<CEMEH> И среди тех, которые есть, будут успешно возникать взаимные эффекты.
<look4awhile> оно ни разу не панацея
<look4awhile> оно решает вопросы “программист рендера должен заниматься рендером”
<look4awhile> оно требует очень своеобразной культуры разработки
<look4awhile> местами душит code ownership, и скорее подходит для pare programming
<look4awhile> куча, туча нюансов.
<look4awhile> и требует чтобы те, кто пишут код – понимали почему оно вот так
<look4awhile> а этому пришлось долго учить
<CEMEH> Т.е. гейм-программер может без вопросов написать в коде физики THIS->LowerHitPoints (100)?
<look4awhile> ага
<look4awhile> там код-стандарт своеобразный
<look4awhile> и своеобразная интеракция
<look4awhile> но написать вообщем-то может
<look4awhile> обычно для него пишется OnCollide, в котором он и пишет if ( Is(GameObject) ) Access(GameObject)->LowerHitPoints(100);
<look4awhile> либо физ.программист пишет
<look4awhile> if ( Is(GameObject) } Access(GameObject)->OnCollide();
<look4awhile> вообщем масса вариантов, и кому как удобнее – то так и организует
<look4awhile> penalties почитай что никакие от любого из вариантов
<CEMEH> Ы, а если у GameObject есть OnCollide, то в чем пойнт вообще?
<look4awhile> в том что PhysObject-а может не быть. и в таком раскладе OnCollide не скомпилится
<CEMEH> Разве что в том, что можно и так, и так.
<look4awhile> и (!) в том, что не надо писать код, который “клеит” всё это дело вместе
<look4awhile> т.е. нет CBall::OnCollide
<look4awhile> и тот, кто пишет CBall – он вообще всем этим не интересуется совсем
<CEMEH> А что программисты физики и рендера друг другу пишут?
<look4awhile> он в CBall суёт функциональность только специфичную для CBall
<look4awhile> физики и рендера – меняем цвет при ударе, и “плющим” мяч матрицей
<look4awhile> на практике там
<look4awhile> несколько разных collsolver-ов
<look4awhile> и ещё мал-мала всякого policy добра
<look4awhile> и IFrame
<look4awhile> и IFrameEffect
<look4awhile> какие либо есть, либо нет
<CEMEH> Погоди, а почему collsolver физик не пишет сам себе?
<look4awhile> точнее effect-а может не быть
<look4awhile> colsolver физик себе пишет сам. несколько даже
<CEMEH> [14:18] <CEMEH> А что программисты физики и рендера друг другу пишут?
<look4awhile> есть скользящий, есть искажающий, а есть для ragdoll-ов
<CEMEH> Мне интересно, что они пишут именно в код другого.
<look4awhile> он не решает, как их будут юзать. он ограничивает юз сам
<look4awhile> в коде другого – hook-и, какие другим нужны
<look4awhile> и всё
<look4awhile> обычно в пару
<look4awhile> например в render программист AI дописал
<look4awhile> OnVisible()
<look4awhile> а программист render-а его заставил работать
<look4awhile> а в физику программист рендера дописал SetVisible
<look4awhile> чтобы считать с разной скоростью
<look4awhile> потом физик сказал – “нах” и поменял на IsVisible()
MihaPro (mihapro@ircnet-26563.kuban.ru) joined #gamedeff.
<look4awhile> нормальная такая интеракция, да
<look4awhile> душит дублирование данных капитально
<MihaPro> привет
<look4awhile> потому как обычно tmLocal2World есть и у render и у physic
<look4awhile> а в таком раскладе нет вообще
<look4awhile> привет
<CEMEH> Видимо тем, что заставляет смотреть в код другого :)
<look4awhile> только в header-ы
<look4awhile> и только в те, какие реально юзаешь
<look4awhile> оно банально не скомпилится, если что-то забыл
<look4awhile> не только
<look4awhile> тем что в код
<look4awhile> в рендере нет * tmLocal2World, и в физике нет
<look4awhile> tmLocal2World есть в IFrame
<look4awhile> и его все берут НАПРЯМУЮ
<look4awhile> т.е. THIS->tmLocal2World
<look4awhile> банально так
<look4awhile> нет долбаной тучи cross-reference указателей
<look4awhile> virt. функций становится ощутимо меньше
<look4awhile> уходит куча abstraction penalty
<look4awhile> и можно тупо писать “свой” код. интерфейс со всеми остальными получается крайне тонкий
<look4awhile> очень только трудно научить вначале :(
<look4awhile> .
<CEMEH> Ну, я ощутил какое-то дао, да.
* MihaPro читает логи и получил рвотные позывы, там где надо.
<look4awhile> сложнее всего было понять, как всё просто
<look4awhile> т.е. когда не знаешь как проектировать – тупо дробишь
<look4awhile> и пишешь куски, какие понимаешь
<look4awhile> рефакторить легко. клеить легко
<look4awhile> документировать легко. передавать код – как всегда хуёво
<look4awhile> я бы не взялся агитировать такой подход для произвольной комманды
<look4awhile> хуже – я бы 10 раз думал, прежде чем пробовал бы такому научить
<look4awhile> .
<CEMEH> Окей, look4awhile, я воспринял.
<CEMEH> Расскажи еще какие-то детали и бонусы?
<CEMEH> Скажем, весь код такой надо заново писать?
<look4awhile> мигрировать код давольно таки легко
<look4awhile> берёшь код, какой реально работает
<look4awhile> clutter выкидываешь
<look4awhile> выкидываешь общие данные и выносишь их отдельно
<look4awhile> рефактор большой, но затрагивает не ядро, а наоборот – обёртки
<look4awhile> бонусы – вообщем-то все, какие рассказывал
<look4awhile> граблей – тоже немало. как взде
<CEMEH> [14:38] <look4awhile> берёшь код, какой реально работает
<CEMEH> [14:38] <look4awhile> clutter выкидываешь
<CEMEH> Звучит теоретикой кайфа, да :)
* MihaPro реагирует на ТК.
<look4awhile> ага. так и есть
<look4awhile> на практике рефакторили крайне мало
<look4awhile> особенно смысла не было
<look4awhile> выкидываешь либо переписываешь
<look4awhile> потому как код, который работает – он работает
<look4awhile> а “интерфейсы” получаются очень тонкие
<MihaPro> look4awhile, так ты писал уже так или видел живой проект?
<CEMEH> О, вот я спрошу.
<CEMEH> Сколько всего кодобаза игры? Сколько из нее те аспекты?
<look4awhile> gauntlet такой
<look4awhile> весь
<CEMEH> Т.е. весь код – аспекты?
<look4awhile> кодобаза – что-то около двух мегов
<look4awhile> да.
<look4awhile> весь код такой
<CEMEH> Двух мегов????
<CEMEH> Для PS2/Xbox?
<look4awhile> ага
<CEMEH> Рендер такой? SG такой?
<look4awhile> рендер такой. SG такой
<MihaPro> я вот по другому пытаюсь избежать дублирования данных, напримере worl-матрицы – везде хранится указатель на одну. (а она в render живёт %)
<CEMEH> А в рендерах какие gluer’ы?
<look4awhile> IRenderObject
<look4awhile> IParticleObject
<look4awhile> и ещё всякое, по мелочи
<look4awhile> для 2d
<look4awhile> указатель на world матрицу – 4 байта. влоб – 0 байтов.
<CEMEH> Покажешь объявление IParticleObject?
<MihaPro> look4awhile, ну 20 лишних байт будет на 5 указателей, много ли?
<look4awhile> там всякая муть типа Start, Stop, итп
<CEMEH> Объявление – в смысле от каких аспектов наследуется.
<look4awhile> 20 лишних байт – это сказки. практика – это alignment
<MihaPro> вот тут нечего сказать
<look4awhile> IParticleObject не от чего не наследуется, кроме CParticleObject
<CEMEH> [14:44] <CEMEH> А в рендерах какие gluer’ы?
<look4awhile> не понимаю вопрос.
<look4awhile> где юзаются партиклы?
<look4awhile> ну например в “оружии”
<look4awhile> т.е. там одновременно и Render и Particle объекты
<look4awhile> чтобы аттачить
<look4awhile> партиклы на меч
<look4awhile> опционально
<CEMEH> Т.е. весь рендер – это аспекты.
<CEMEH> А gluer’ы – это только game objects.
<look4awhile> вся функциональность наружу видна как aspect-ы, да
<look4awhile> а gluer-ы – это не только game-object-ы, но и ещё мал-мала всякого. но большей частью да
<CEMEH> Народу поди крышу сносит.
<look4awhile> крышу сносило в начале проекта. заставлял я книжки читать. мучал всяким
<look4awhile> считаю окупилось
<CEMEH> Какие книжки?
<look4awhile> например александреску. чтобы было понимание, полное – как оно внутри работает
<MihaPro> интересно, а не бывает такое class Class: public… и тут стркоа из 20 классов?
<CEMEH> Дык, конечно бывает :)
<look4awhile> в основном так и бывает
<MihaPro> это же сложно для восприятия…
<MihaPro> тут уже хоть кодогенерилку пеши
<look4awhile> оно навевает очень своеобразные паттерны, кстати
<look4awhile> т.е. “менеджеры” получаются сами. вместо того, чтобы писать функциональность в объект
<look4awhile> т.е. class CRenderObject : public IManaged<CRenderObject>; template <class Gluer> class IRenderObject;
<look4awhile> а потом foreach ( CRenderObject ) итп
<look4awhile> или вот scene-graph
<look4awhile> тут совсем просто
<look4awhile> class CBall : ISceneObject<CBall,SG_PHYSISC>, ISceneObject<CBall,SG_RENDER>…
<look4awhile> на практике, правда, чуть вше такое. в render и physisc объектах соответственно
<look4awhile> но идея именно что и такая
<look4awhile> очень “дружелюбный” foreach получается. с prefetch-ем прям в нём.
<CEMEH> По-русски, foreach с очень разбросанными по памяти объектами ;)
<look4awhile> нефига, кстати
<look4awhile> class CBall : IPool<CBall>
<CEMEH> И?
<CEMEH> Теперь можно создавать только через Pool?
<look4awhile> теперь new\delete будут работать через pool. думать не надо
<look4awhile> пишется “как пишется”
<CEMEH> Отличные сказки.
<look4awhile> оно совсем не панацея. но хорошо комбинировать с другими паттернами. получается внятно
<MihaPro> с непривычки страшно за такое браться
<look4awhile> не надо за такое браться
<look4awhile> если нет хорошей причины
<MihaPro> причин нет, есть манящяя ТК :)
<look4awhile> если сам пишешь весь код – такой огород городить смысла мало
<look4awhile> оно хорошо работает чтобы обеспечить работу кучи народа над общим кодом
<look4awhile> на “мало народа” – малоосмысленно. можно проектировать самому себе как угодно
<MihaPro> меня подкупает оптимизация в твоём подходе, нет clutter и лишних абстракций
<look4awhile> а кто мешает без него писать просто так?
<CEMEH> А сколько программистов на Gauntlet?
<look4awhile> 14 сегодня
<look4awhile> я не знаю как оно масштабируется вверх
<look4awhile> я не знаю как у всего этого – с кодреюзом
<look4awhile> я не знаю – какие у всего этого перспективы
<look4awhile> оно совсем не ООП – и потому “готовых” кадров нет
<CEMEH> Как примерно разделяются по областям?
<look4awhile> 2 на рендер. 2 тулсы. 2 аи. 2 рпг + всякое. 2 сетка. 1 физика. остальные разное
<look4awhile> самое противное – никто не мешает формализовать сильно паттерны и “писать проще” итак. без АОП. без этой реализации
<look4awhile> но так для gauntlet-овой комманды оказалось понятнее всего. удивлялся
<look4awhile> опять-же нанять народ – становится проблема
<look4awhile> примерно 2 недели обучать приходится всякому
<look4awhile> тех кто не любит С++, или не любит его достаточно – плохо получается нанимать
<look4awhile> тех, у кого религия не позволяет множественно наследоваться – опять-же
<look4awhile> итд итп
* look4awhile думает, что надо писать статью. но рано, рано…
<MihaPro> вот интересно, а нет такой проблемы что почти весь код живёт в .h?
<MihaPro> слово поменял и пол проекта переколбашивать…
<look4awhile> нет
<look4awhile> большая часть кода – это CRenderObject, а не IRenderObject
<look4awhile> и в итоге cpp/h/i
<look4awhile> меняются по разному
<MihaPro> C – в cpp, I в .h?
<MihaPro> а .i – это что?
<look4awhile> это там где IRenderObject
<look4awhile> а в .h лежит CRenderObject
<MihaPro> короче проблемы с перекомпиляцией не возникает?
<look4awhile> возникает. когда всякое в pch
<look4awhile> 5 мин full rebuild
<look4awhile> вообщем-то не критично перекомпилить переодически
<MihaPro> для большого проекта 5 минут на full – не время :)
<MihaPro> как нибудь в хорошие времена попробуйю такой подход на pet project :) но не сразу.
<look4awhile> лучше не надо. а вдруг понравицца
<MihaPro> если понравицо, то заюзаю по полной
<MihaPro> ищу лёгких путей :)
<CEMEH> Я предлагаю мега-диверсию – пусть это понравится Диме!
<look4awhile> всем придёт пиздец.
<look4awhile> сперва мне – как автору
<look4awhile> потом всем остальным
<look4awhile> кто повёлся

  • Pingback: Блог FX’а » Архив блога » Одной строкой №2()

  • dDIMA

    Ну, в общем-то, повторюсь: оно нравицца, поэтому пиздеца не будет :)
    Меня только насколько смущает моя любимая линия – это линия разреза.
    Ну то есть мой подход хорошо известен – это множественное наследование для подписки на события + агрегирование всяческих physics внутри.
    в этом случае удается четко отделить действительно системный универсальный код и как хочешь, дрочить внутренности.
    из минусов подхода – наличие энного количества врапперов (впрочем, non-virtual) из MyHandler::onTimer(elapsed) в m_physics->timer(elapsed);
    К темплейтам по привычке отношусь подозрительно, поэтому стараюсь не юзать, пока не изучу их поведение на конкретном компиляторе на 103.5%
    Хотя если Боря говорит, что все заебись, то охотно верю.

  • http://blog.fxposter.org/ FX Poster

    Жжоте, господа :)

  • Joes

    Тотальный brain damage. Но да, идея отличная.

  • deemetrius

    Это очень хорошо, т.к. в CBall нет ничего лишнего, а только то, что к CBall относится непосредственно.
    Можно ещё по группам class CBall : public CGroupOne {}; template CGroupOne : public IAspectOne, public IAspectTwo {};

  • deemetrius

    Почему тэги > и < съелись?

  • CEMEH

    Потому что html. Пользуй &_g_t_; и &_l_t_; (убрать прочерки)