aruslan
ээ ... моя не понимает %) про специализацию понимает, про coupling/cohesion не понимает :)
мой пойнт: не давать каких-то мутных/субъективных определений, по поводу coupling/cohesion, а исходить из того, что cohesion это "сильная связность", которую в следствие объективных причин мы не можем уменьшить (то есть превратить в coupling, оторвать мне голову/ногу/руку, можно конечно но очень не желательно). Если же связность возможно уменьшить, тогда это coupling.(отделить одежды)
То есть coupling это использованная возможность уменьшения связности, а cohesion - высокая степень связности, которую нельзя уменьшить. Другими словами некоторая "процедурная" точка зрения, мы не говорим что это такое, а говорим что с этим можно сделать и из чего это получилось. Основная цель - на сколько это _возможно_ уменьшить связность.
Я понял. Ты пытаешься их противопоставить. Это не всегда так.
Давай попробую по другому.
Cohesion - это "сфокусированность".
Вот здесь - низкий cohesion - потому что методы одного класса заняты разными вещами, и одновременно - низкий coupliung:
struct string { explicit string( int ); // maxx -- НЕ ИСПОЛЬЗУЙТЕ sprintf!!! убью нафик! int to_integer() const; // explicit string( float ); // shurik -- тогда уж сразу и из float explicit string( int value, int width, char filler ); // kolya -- вообще-то у sprintf параметров больше! explicit string( float value, int width=0, char filler=' ' ); // shurik -- Колян дело говорит. explicit string( const char* format... ); // maxx -- короче, надоели void transform_by_xlst( const string& xlst ); void encrypt_by_vigenere( const string& key ); // 180299 added by PVV - для отсылок пароля по почте vector<unsigned char> compress(); // shurik -- сжимает по LZSS explicit string( const vector<unsigned char>& ); // kolya -- и разжимает! hashcode calculate_hash() const; bool does_match( const string& regexp ) const; // задрали уже все велосипеды писать! теперь одинаково! -- smash bool search_and_replace( const string& super_regexp... ); // amax -- так круче! does_match - в помойку! superfasthashcode calculate_hash_fast() const; // для Шурика private: немножко кучи кэшей и т.п. для ускорения работы всех методов одновременно };
Но ведь г. же, а не класс :)
А вот здесь - высокий coupling и одновременно - высокий cohesion:
struct mesh { void render() { ... renderer::get_instance().get_lights() ... viewport ... if( device_lost ) ... ... if( texture[0].is_not_loaded() ) load_texture... if( reflective_surface ) { scene_manager::get_instance().get_active_scene().render_to_texture( .... ) ... } ... } };
Я понимаю, что примеры дебильные, но некоторое ощущение правды в них есть ;)
Плюс вопрос цели.
Неверно считать, что цель - отделить всё, что отделяемо.
Потому что истина - она посередине (ц)
Coupling/cohesion - это метрики достижения внутреннего баланса и гармонии.
> Я понял. Ты пытаешься их противопоставить. Это не всегда так.
не, противопоставить не хочу, на самом деле хочу их просто выбросить :) и заменить концепцией связности существующей в различных формах и на различных уровнях системы, а построение эффективной архитектуры свести в основном к совместной максимизации/минимизации различных видов связности. (да, я извращенец! :)
То есть на твоем примере стринга, по мимо связности порождаемой взаимодействием, существует другой вид связности,а именно "концептуальная связность". При этом, связность взаимодействия желательно минимизировать,а концептуальную максимизирвоать, естественно, что данные цели часто противоположны, поэтому задача - найти "золотую середину" (совместная "оптимизация" получаемая при некоторой степени минимизации связности взаимодействия и некоторой степени максимизации концептуальной связности)
ps: в общем звучит бредова-то, но надеюсь смысл понятен %)
> При этом, связность взаимодействия желательно минимизировать,а концептуальную максимизирвоать,
> естественно, что данные цели часто противоположны, поэтому задача - найти "золотую середину"
Ну, собственно, ты всё сказал правильно.
"Связность взаимодействия" - это и есть частный случай coupling.
Есть много других разновидностей (скажем, сколько нужно перекомпилировать или переписывать), но для 5:15 утра достаточно и этого :)
Концептуальная связность - это натурально cohesion.
Я просто не очень понимаю, зачем использовать одно и то же слово в двух противоположных смысловых и эмоциональных оттенках, но дело, в общем, хозяйское.
Просто тут такой нюанс - "связность взаимодействия" по-русски может быть наполнено благородным позитивом.
Например - класс общается только с тем, с кем нужно, и только по делу.
А вот дать "спутанности (coupling) взаимодействия" позитивную оценку можно только обкурившись.
Англичанам - проще :)
P.S. Я так понял, что ОО и data driven вопросов не вызывают? ;)
Кстати, классический пример разрушения ОО простым (читай - незрелым) data drivenом.
В большинстве случаев достаточно только одной структуры данных - ассоциативного массива (хэш-таблицы) и только двух функций:
wstring get( string id )
и
void set( string id, wstring value )
При этом вся ОО модель будет либо в головах пишущих, либо в нормативных документах.
Пойду-ка я баиньки :)
Завтра будет еще холоднее, бррр...
aruslan
Под ригидностью имелось в виду жесткая статическая типизация С++ или что-то еще?
T.е. просто в C++ нет выразительных средств для эффективной реализации data driven (например классическая проблема сериализации типов)?
Но с другой стороны пусть для того же окошка с кнопкой создали файлик из которого читаются размеры, создаваемого окна.
ОО-дизайн не изменился, однако чем не data driven?
Другими словами ОО-дизайн рушится только тогда, когда некоторые концепции вступают в противоречие со средствами языка. До этого момента все ок.
> Но с другой стороны пусть для того же окошка с кнопкой создали файлик из которого читаются размеры, создаваемого окна.
> ОО-дизайн не изменился, однако чем не data driven?
Считывание размеров окна из файла - это первые шажки data driven, не более того.
> Другими словами ОО-дизайн рушится только тогда, когда некоторые концепции вступают в противоречие со средствами языка.
Именно так: data-driven создает вне языка (вне кода) высокосистемные артефакты с высокой степенью связности и низкой зацеплённостью ценой разрушения ОО и связности в коде.
В жизни многих игровых компаний есть фаза конструирования data-driven (table-driven, blabla-driven, Общая Шина (тм) - driven) движка.
Конец этой фазы обычно совпадает с концом непрофильного инвестора глубоко в недрах компании.
Как правило развитие data driven системы проходит следующие стадии:
- нулевая фаза: только код
В чистом виде не встречается из-за минимальной культуры программирования плюс минимального понимания процесса разработки.
Если бы встречалось - получился бы здоровенный шмоток фарша, в который замешано всё.
Характерные признаки: programmers' art, чудовищная гибкость в сочетании с активным сопротивлением к изменениям.
- первая фаза: факторизация на код и "чистые" данные (т.е. изолированные константы, без проблем выносимые из кода).
Речь идёт о примитивных (value-type, нессылочных) константах.
Это различного рода числа, текстовые строки, битмапы, звуки, - тупые "константы".
Обычно всё начинается с простых quake-like "консольных переменных", config-like-файлов, ogg, bmp etc.
С человеческой (эксплутационной) точки зрения речь идёт о кое-как организованной каше из файлов.
Появляется структура каталогов (как неявное средство организации каши).
Соответственно, появляются "списки консольных переменных", "таблицы значений по умолчанию" и "HOWTO: настройка тумана".
Всё неформально, всё - изустное творчество.
Массивы данных с ad hoc структурой.
Преобладает pull-модель: клиентский код считывает "константы" напрямую; если её нет вовне - используются "умолчания" и т.п.
Типичные низкоуровневые паттерны в коде - примитивные фабрики прямого действия, прототипы, синглтоны, фасады.
Типичные дизайн паттерны: библиотеки и utility классы.
Типичные архитектурные паттерны: специализация по скиллам, снизу-вверх, ad hoc programming.
- вторая фаза: вынесение "чистых" связок (т.е. констант, задающих ассоциации между уже вынесенными наружу константами).
Типичные представители - примитивные ненастраиваемые (максимум - ограниченно настраиваемые) моникёры или URLы.
Имена текстур, пути к файлам etc. Материалы, связки шейдеры-текстуры, простые сцены и т.п.
С человеческой (эксплутационной) точки зрения - появляются примитивные "ресурс менеджеры".
Соответственно, начинается исключение из клиентского (игрового) кода подробностей загрузки и обработки конкретных объектов.
Структура файлов/каталогов начинает фиксироваться более формально - в "движковом" коде.
Всё реже встречается чтение изолированных констант, всё чаще - билдеры. Причём билдеры уходят в нижний слой.
За чтение битмапа путём LoadBitmap("blabla.jpg") бьют по рукам.
Типично появление нетипизированных композитов и баз данных, структура которых задаётся в коде.
Как следствие - резкое падение связности кода, обилие приведений типов, паттерн-матчинг и поиск подобъектов руками.
Всё зарастает умными указателями, поскольку в коде становится невозможным отличить полную (целую) сущность от её части.
Возникают зачатки разделения семантики копирования (clone, прототипы) и разделения (shared_ptr).
Появляется идея "инициирующей сущности". Игра как LoadGame(argv[1])->PlayGame().
Появляются зачатки push-модели.
Типичные низкоуровневые паттерны: билдеры, визиторы, прокси, композиты, простые стратегии, мементо, сигналслоты.
Типичные дизайн паттерны: frameworks, layers, messaging.
Типичные архитектурные паттерны: специализация по функциональному признаку, изнутри-наружу, KISS.
- третья фаза: вынесение структуры композитов вовне, образование в данных связок "фича-код".
Типичные признаки: появление внеязыкового метаописания игровых объектов, обширное применение фабрик стратегий.
Как следствие - развитые механизмы десериализации, генерация кода по описаниям.
Часто - скрипты в той или иной форме.
Схемы (в смысле XML schema), структуры отношений в контенте, - всё выносится из кода.
Контент как базы данных, структура которых задаётся вовне.
В движковом коде остаётся только структура метаописания. Как следствие - агрессивная push-модель.
Вынесенная вовне структура ассоциаций внутри игровых композитов остро ставит вопросы копирования/разделения.
Появляется понимание, что one size doesn't fit all.
Игра превращается в базу данных с прикольным интерфейсом.
Резко усложняется инфраструктура.
Игровой код агрессивно упрощается, как правило с помощью DSL/скриптов/надстроек/генерации кода.
Из игрового кода исчезает практически всё, что обычно обсуждается на gamedev.ru.
Игровые программисты начинают работать в песочницах, как правило не знают низкоуровневых API.
Впервые проявляются фундаментальные проблемы контроля версий при одновременном редактировании схемы и собственно контента.
Появляется asset management.
Топик статьи "Compile-time vs run-time" - на третьей фазе.
Типичные дизайн паттерны: content/engine, table-driven design, frameworks, scripting.
Типичный архитектурный паттерн: конвейер, создание новых узких специальностей в команде, сверху-вниз.
- четвёртая фаза: вынесение игрового кода вовне, круг полностью замыкается.
Движок становится виртуальной машиной.
Окончательно фиксируются на мета-C++-уровне процессы make/debug/edit-and-continue.
Большинство технических проблем третьей фазы превращаются в вопросы оптимизации контента.
Большинство организационных проблем - в вопросы управления документооборотом, его трекинг и т.п.
На этой фазе начинается новый виток спирали.
Если вынесенная вовне модель страдает аналогичной C++ ригидностью - всё неминуемо начнётся с начала.
Скажем, внутренний порок трёхлетней давности статических спецификаций напрямую связан с ригидностью описаний.
Типичные DSL устраняют классические проблемы C++: асинхронные потоки управления, машины состояний/параллельные CSP, жёсткая типизация, нерасширяемые объекты, inheritance-based delegation etc.
ммм, немного невнятно написано.
спрашивайте, если вдруг интересно.
Определенно понравилось.
(Сохранил страницу).
Если убрать немного непонятные мне примеры, типа:
>Скажем, внутренний порок трёхлетней давности статических спецификаций напрямую связан с ригидностью описаний
То я достаточно легко всё воспринял. Хотя впечатления такие, как будто слушаю иностранца: понимаю о чем говорится, но, в терминах информатики, плотность информационного потока между страницей и мной колеблется в процессе чтения. Впрочем, это из-за того что я еще сам не успел набить себе достаточно шишек, пройдя все фазы.
Как связаны во второй фазе
> Структура файлов/каталогов начинает фиксироваться более формально - в "движковом" коде.
и
> За чтение битмапа путём LoadBitmap("blabla.jpg") бьют по рукам.
?
Тема в архиве.