Группа друзей и я работали над проектом в последнее время, и мы хотели изобрести хороший ООП-способ представления сценария, специфичного для нашего продукта. По сути, мы работаем над пули-адом в стиле Тохоу , и мы хотели создать систему, в которой мы могли бы легко представить любое возможное поведение пули, которое мы могли бы придумать.
Так что именно это мы и сделали; мы создали действительно элегантную архитектуру, которая позволила нам разделить поведение маркера на различные компоненты, которые можно прикрепить к экземплярам маркера по своему желанию, что-то вроде системы компонентов Unity . Это работало хорошо, это было легко расширяемо, это было гибко и охватывало все наши базы, но была небольшая проблема.
Наше приложение также включает в себя большое количество процедурной генерации, а именно мы процедурно генерируем поведение пуль. Почему это проблема? Что ж, наше ООП-решение для представления поведения пули, хотя и элегантное, немного сложнее в работе без человека. Люди достаточно умны, чтобы думать о решениях, которые логичны и умны. Алгоритмы процедурного генерирования еще не настолько умны, и нам было трудно реализовать ИИ, который использует нашу архитектуру ООП в полной мере. Следует признать, что недостатком архитектуры является то, что она не интуитивна во всех ситуациях.
Таким образом, чтобы устранить эту проблему, мы в основном перенесли все варианты поведения, предлагаемые различными компонентами, в класс маркеров, чтобы все, что мы могли себе представить, предлагалось непосредственно в каждом экземпляре маркера, а не в других связанных компонентах. Это немного облегчает работу с нашими алгоритмами процедурного генерирования, но теперь наш класс пули - это огромный объект бога . На сегодняшний день это самый большой класс в программе, в котором кода в пять раз больше, чем всего остального. Это тоже немного сложно поддерживать.
Это нормально, что один из наших классов превратился в объект бога, просто чтобы было легче работать с другой проблемой? В целом, нормально ли иметь запах кода в вашем коде, если он допускает более простое решение другой проблемы?
источник
Ответы:
При создании реальных программ часто приходится идти на компромисс между тем, чтобы с одной стороны оставаться прагматичным, а с другой - оставаться на 100% чистым. Если сохранение в чистоте запрещает вам вовремя отправлять ваш продукт, тогда вам лучше с небольшим количеством клейкой ленты, чтобы вытащить грязную вещь из двери.
Сказал, что ваше описание звучит по-другому - кажется, вы не собираетесь добавлять немного клейкой ленты, похоже, что вы собираетесь разрушить всю свою архитектуру, потому что вы не выглядели достаточно долго и усердно для лучшего решения. Поэтому вместо того, чтобы искать кого-то здесь, в PSE, который дал бы вам благословение, вам лучше задать другой вопрос, в котором вы подробно опишите некоторые проблемы, которые у вас есть, и посмотрите, не предложит ли вам идею, которая избегает бога. подход.
Может быть, класс bullet может быть спроектирован так, чтобы быть фасадом для множества других классов, поэтому класс bullet становится меньше. Может быть, шаблон стратегии может помочь, чтобы пуля могла делегировать различные варианты поведения различным объектам стратегии. Возможно, вам нужен только адаптер между вашим компонентом пули и процедурным генератором. Но, честно говоря, не зная больше деталей вашей системы, можно только догадываться вокруг.
источник
Интересный вопрос. Я немного предвзятый, хотя из-за моего предыдущего опыта, который побуждает меня ответить нет.
Короткий ответ: мы никогда не прекращаем учиться. Когда вы врезаетесь в такую стену, это шанс улучшить ваши архитектурные / дизайнерские навыки, а не оправдание для добавления запахов кода.
Более длинная версия состоит в том, что мне уже много раз задавали подобные вопросы в моих проектах на работе, но неизбежно мы закончили тем, что обсуждали проблему гораздо глубже, чем первоначальный спрашивающий дал ей должное. Вы хотите включить в это менталитеты, такие как анализ первопричин.
Я нашел 5 Whys особенно полезными. Ваше объяснение здесь выглядит так же, как первое почему:
Что именно упрощается? И почему это так? Продолжайте идти по этому пути, и обычно происходит то, что вы начинаете распознавать более фундаментальные проблемы, но в то же время они также дают вам более фундаментальные решения.
Короче говоря, после более глубокого осмысления рассматриваемой проблемы и, в частности, ее причин, по моему опыту, первоначальный вопрос оказался недействительным и совершенно неинтересным для всех участников. Если у вас есть сомнения, бросьте им вызов, и либо они исчезнут, либо вы будете знать, что вам нужно делать. Имейте в виду, это хороший знак, на мой взгляд, иметь эти сомнения в отношении кода / дизайна. Другие называют это внутренним чувством, но чтобы бросить вызов этим проблемам, вы должны сначала их распознать. Так как вы сделали этот первый шаг, поздравляем! А теперь иди в кроличью нору ...
источник
Подобный класс богов никогда не желателен, так как это не только означает, что ваши пули теперь являются монолитными объектами, но то же самое относится и к алгоритму процедурной генерации.
Первым шагом было бы проанализировать, почему именно ваш ИИ имел столько проблем со сложностью вашего паттерна?
Вы случайно не пытались превратить свой ИИ в объект класса бога, полностью осознавая семантику каждого возможного свойства? Если вы сделали, вот где проблема возникла.
Тогда решение состояло бы не в том, чтобы интегрировать все стратегии в сам класс пули, а вместо этого перенести подсказку для ИИ из ядра ИИ в сами реализации стратегий.
Это дало бы вам гибкость, которую вы изначально желали, в том числе возможность расширить систему новыми стратегиями по вашему желанию, не боясь столкнуться с побочными эффектами от унаследованного поведения.
Вместо этого у вас теперь есть все проблемы, связанные с объектами богов: не только ваш класс богов трудно понять, трудно отладить монолит, но то же самое относится и ко всем другим компонентам, имеющим доступ к такому классу богов. Из-за отсутствия абстракции ваш ИИ теперь должен превратиться в мерзость аналогичной сложности, так как теперь он должен знать все избыточные, индивидуальные свойства.
Даже сейчас вы уже испытываете проблемы с техническим обслуживанием. Эти проблемы усугубляются, особенно когда вы теряете членов команды, у которых все еще есть когнитивная модель работы этого класса.
До сих пор каждый проект, с которым я сталкивался и который использовал такие классы богов или функции богов, был либо полностью переписан с нуля, либо прекращен, без исключений.
источник
Весь плохой код с незапамятных времен имеет свою историю, которая заставляет его выглядеть шаг за шагом. Ваш не исключение. Кодеры учатся кодированию. Есть аспекты вашей проблемы, которые вы не могли предвидеть, которые кажутся очевидными сейчас. Есть решения, которые вы приняли, которые были вполне разумными постепенно, но в целом привели вашу архитектуру в неправильном направлении. Вам необходимо определить и пересмотреть эти решения.
Спросите у своего офиса, есть ли у людей идеи, как это исправить. В большинстве мест, где я работал, около 10-20% программистов действительно разбираются в подобных вещах и просто ждали этого момента. Выясните, кто эти люди. Часто именно ваши новые сотрудники, которые исторически не вкладывались в текущую архитектуру, могут легче всего увидеть альтернативы. Соедините их с одним из ваших ветеранов, и вы можете быть удивлены тем, что они придумали вместе.
источник
В некоторых случаях это определенно приемлемо. Тем не менее, мне трудно поверить, что не существует хорошего решения, использующего как процедурную генерацию, так и вашу хорошую архитектуру поведения, основанную на прикрепленных компонентах. Если все виды поведения, которые только что были включены в класс bullet, не имеют функциональной разницы между объектом God и аккуратной архитектурой. Что затруднило использование ваших процедурных алгоритмов генерации?
Я думаю, что новый вопрос (может быть, здесь, или на gamedev.stackexchange.com?), Где вы описываете, какие проблемы у вас возникли с вашей архитектурой в сочетании с proc. генерал., было бы действительно интересно. Дайте нам знать, если вы тоже зададите новый вопрос!
источник
Для вдохновения вы, возможно, захотите взглянуть на функциональное программирование или, точнее, на узкие типы. Идея в том, что вещи не работают, невозможно представить в имеющейся у вас системе типов. Например, допустим, у вас есть пистолет с компонентами «стрелять пулями» и «держать пули». Если они представляют собой два отдельных компонента, есть конфигурации, которые не имеют смысла - у вас может быть пистолет, который стреляет пулями, но не имеет его в своем хранилище, или пистолет, который хранит пули, но не стреляет из них.
На этом уровне сложности вы думаете: «Хорошо, человек поймет, что это бесполезно, и избежит невозможных комбинаций». Лучшим способом может быть сделать это совершенно невозможным. Например, для компонента «стрелять пулями» может потребоваться ссылка на компонент «держать пули» (или просто держать его как часть самого себя, хотя это имеет свои проблемы).
Хотя ваши примеры могут быть намного сложнее, ключ по-прежнему ограничивает возможные комбинации, добавляя ограничения. В некотором смысле, если это слишком сложно для процедурной генерации, чтобы понять это правильно, это, вероятно, слишком сложно в любом случае. Подумайте о том, как вы ограничиваете себя при разработке оружия - говорите ли вы себе: «Правильно, у этого пистолета уже есть огнемет, нет смысла добавлять гранатомет»? Это то, что вы можете включить в свою эвристику. Возможно, вы захотите использовать вероятностный механизм, который немного сложнее, чем просто дать фиксированный шанс наличия каждого компонента - у вас могут быть компоненты, которые имеют тенденцию исключать друг друга, или компоненты, которые, как правило, хорошо работают вместе.
И наконец, подумайте, действительно ли это достаточно большая проблема. Это разрушает удовольствие от игры? Являются ли в результате оружие бесполезным или подавленным? Как много? Является ли один из 10 бессмысленным? Такие игры, как Borderlands (с процедурно генерируемыми эффектами оружия) часто игнорируют бессмысленные комбинации эффектов - какой смысл иметь дробовик с 16-кратным прицелом? И все же это происходит очень часто в Borderlands. Это просто игра для смеха, а не как провал механизмов генерации :)
источник