Spiiin's blog

Виды сложности

- Сложность предметной области
Поиск “серебрянной пули” — универсального подхода к проектированию чего угодно. Например, проектировать, исходя из того, что “всё есть объекты”, “используем шаблоны проектирования”, попытка натягивать на паттерны всё, даже там, где это не нужно. Или “запретить использование сырых указателей”. Иногда получается хорошо, иногда странно. Идея с классами в геймдеве рождает GodObject (GameObject/GameLevel) + в конечных классах получаются очень неудобные иерархии наследования.

Другой подход — разработка фреймворков/DSL, с помощью которых можно смоделировать на высоком уровне (“на языке специалистов предметной области”) большую часть задач в какой-либо отрасли. Может размазываться в различных пропорциях между “системным языков” и “прикладным языком/программой”, со слоем склеивания в виде файлов с данными или API в коде.

Сложность предметной области плохо устраняется, так как описывает не красивые абстрактные модели, а конкретные частные случаи. Важно не подмешать лишней сложности, напроектировав в голове машины Руба Голдберга. Меньше понятий, сущностей, уровней абстракции и связей. Если без чего-то можно обойтись — нужно это выбросить.

Semantic compression — статья о том, как выбрасывать сущности.

- Сложность выполнения требований

“Выбросить клоунов из машины”

Программы выполняются не на абстрактном компьютере, а на реальном железе. Существует разрыв между задачами, которым с головой хватает возможностей компьютера, и теми, которые упираются в ограничения. Кроме железа, могут вылезать и другие сложности окружения — сборщик мусора, ограничения файловой системы или сети, с какого-то масштаба задач требуют учёта влияния этих факторов. “Common wisdom” про то, что можно начинать оптимизировать с момента, когда начнёт тормозить, работает далеко не всегда. Иногда решения по оптимизации должны быть заложены еще на уровне дизайна.

Отдельная сложность — предсказание ограничений, которые возникнут, но неизвестны заранее. С геймдевом — в индустрии не так много накопленного и обработанного опыта развития игр после выпуска по 5-10 и более лет.

- Сложность старта

Gui приложения, пустое окно OpenGL, настройка и разворачивание веб-сервера для странички — лет 15 назад требовали больше работы, чем сейчас. Более-менее решено с помощью open-source библиотек, бесплатного хостинга, доступного интернета, искусственного интеллекта. Если не поднимать вопрос о качестве этих библиотек (в разных отраслях разное), то можно сказать что стартовать и собирать прототипы стало сильно проще. Менее заметно в больших командах, чем при одиночной разработке.

Solodevs and the trap of the game engine — про разницу разработки игр в одиночку и в больших командах

- Сложность роста

Серьёзная проблема, с частичными идеями решения. Некоторые практики могут работать для программ на 10к-100к строк, написанных 5 людьми, но ломаться после 100к строк, написанных в разное время 50 людьми. Один из приёмов — изолировать сложность на каком-то уровне, и выдать “наружу” зафиксированный интерфейс. Чем более отдельный компонент получается, тем проще с ним общаться извне, без риска поломки. Вариант изоляции более высокого уровня — виртуальные машины и сэндбоксы для приложений.

Второй подход — не изолировать сложность, а искать такие методы решения, которые позволяют избегать роста сложности (“сделать так, чтобы большая программа ощущалась как маленькая”). Отбросить принятые практики, ведущие к запутыванию, встроить что-то в “простой” язык/виртуальную машину (пожертвовав чем-то). Преимущество таких решений — надёжность, за счёт гарантий (даже если частичных) от компилятора. Чем проще система, тем больше шансов, что в ней будет возможно быстрое внесение изменений/добавлений функционала/исправление ошибок. Single responsibility из SOLID или KISS — кодифицированные отсылки к такому подходу, как и Simplicity Рича Хики