Эволюция игрового фреймворка. Введение 1. Постановка проблемы
Проблема
Скорость разработки и качество кода — вот, пожалуй, одно из главнейших противоречий IT-индустрии. Можно долго продумывать архитектуру приложения, потом ее совершенствовать, улучшать, а в итоге так ничего и не сделать. А можно быстро что-то сварганить, а потом и зарелизить, но из-за ошибок проектирования завести весь проект в тупик. На каждые два часа разработки, шесть часов будет уходить на поиск и исправление багов, в результате чего вся последующая разработка фактически застопорится.
Таким образом, вопрос: качество или скорость переходит в проблему: хороший, но вечно незаконченный проект или хоть как-то, но работающая программа. Любой менеджер как реалист, естественно, выберет второе.
Так и получается, что куда ни ткнись, у всех код если не дрянной, то по меньшей мере неважный. То, что называется многозначительным словом legacy. Все всё понимают, плюются, но поделать ничего не могут. Код уже есть и с ним нужно работать. Все предложения по улучшению не приветствуются, а то и прямо запрещаются. Ведь нужен функционал, а не код. Код существует для функционала, а не функционал для кода.
Корни проблемы
Механизм попадания в тупик простой. Проект начинается с одним видением. В процессе его реализации требования меняются или обнаруживаются неизвестные ранее особенности, и вот созданный код уже перестает соответствовать задаче. Тут бы его переписать, но все знают, что через неделю откроется еще что-то, и нужно будет всё переписывать снова. В результате проект так никогда и не увидит свет. Поэтому принимается волевое решение — продолжать. Продолжать во что бы то ни стало.
Объем функционала растет на отвратительной кодовой базе, в результате чего качество падает еще больше. Так как код не соответствует видению программистов, они перестают его понимать. Мозгов не хватает, чтобы держать в голове две «картины мира»: то, что нужно сделать, и то, как это сделано в реальности. Код выходит из-под контроля разработчиков, и начинает жить своей собственной жизнью в плохом смысле этого выражения.
Процесс разработки становится непредсказуемым. Любое изменение в программе ведет к целому букету трудноуловимых багов. В нормальной системе, увидев баг еще в первый раз, можно предположить, где сломалось, и как это исправить. В плохой — сломаться может что угодно и где угодно, потому что программисты сами уже не вполне понимают, где что делается. Причину бага становится трудно определить даже через несколько часов поисков, особенно, если сам мистический баг не всегда воспроизводится. Так хаос порождает магию. А если точнее — бессилие перед хаосом рождает магическое мышление. Прямо как у первобытных людей.
Но одно дело найти ошибку, и другое — ее исправить так, чтобы не появились другие баги. На это можно потратить еще столько же часов. А то и дней. Так, почти все время из разработки плавно перетекает в исправление ошибок (багфиксинг), и всякое продвижение по графику останавливается.
В конце, превысив все возможные сроки, изможденные разработчики кое-как доводят проект до релиза с ограниченным функционалом. Потом начинают новый проект, и вся история повторяется. Каждый думает, что в следующий раз уже точно все будет по-другому. Но в реальности колесо сансары не так-то легко сломать. Как жители Урюпинска, которые плохо себя вели, после смерти снова попадают в Урюпинск, так и программисты, не переписывающие проекты прошлого, повторяют свои кармические ошибки снова и снова. И даже если местами и появляются тут хороший код, окружающий его плохой топит все в себе, как ложка меда тонет в бочке дегтя.
Решения
Конечно, следовало бы поступить по-иному. Если есть достаточный опыт и теоретическая подготовка, а проект перспективный, не одноразовый, то нужно сначала хорошенько разобраться в теме, выработать качественное решение, а потом уже на основе его серийно делать проекты. Делать проекты просто в надежде, что однажды они каким-то образом станут лучше, затея практически безнадежная. Сами по себе не станут. Когда разработчик начинает осознавать, что выбранный им путь ведет в тупик, то лучше уже сейчас все бросить и, не оглядываясь на старый код, начать заново. И так несколько раз.
Например, клиентский фреймворк, который тут будет разбираться, переписывался раз 7 на протяжении (с большими перерывами) 12 лет, а серверный — раз 5 в течении 5 лет. Это значит, что компании нужно постоянно и целенаправленно работать над улучшением качества кода, и тогда лет через 5 она дойдет до приемлемого результата. Или нужно найти разработчиков, которые уже прошли этот путь и имеют соответствующий опыт за плечами.
Оба пути затратные, рискованные и явно не для всех. Не всяким программистам можно поручить такое задание, да не всякий и возьмется. Такой разработчик должен обладать целым комплексом качеств, которые все вместе встречаются довольно нечасто.
Во-первых, разработчик должен знать в совершенстве данный язык программирования и прочие инструменты, чтобы разные мелкие вопросы не отвлекали его от основной цели.
Во-вторых, требуется обладание техникой проектирования сложных систем и архитектур. А для этого нужно прочитать немало книг и успеть опробовать прочитанное на практике. Большую помощь в этом деле также может оказать изучение чужих исходников, а также других платформ и языков программирования, пусть они непосредственно и не нужны для работы.
Все это требует больших затрат времени, усидчивости и погруженности в предмет. Невозможно каждый день часами сидеть за компьютером и копаться в программе без того, чтобы тебе это не нравилось. Поэтому, в-третьих, должен быть сильный интерес и склонность к программированию, математике, технике, наукам вообще.
В-четвертых, и интерес, и склонности не берутся из ниоткуда. Все это можно только получить — от родителей, хороших учителей, товарищей, книг. Потом, нужны еще условия, в которых бы интерес не гасился, а, наоборот, поддерживался и укреплялся. И многих вы знаете среди своих знакомых, кто бы жил и работал действительно с интересом?
И это только для того, чтобы просто программировать. Но чтобы сделать что-то новое, нельзя ограничиваться только своей специальностью. Нужно еще иметь неплохие обзорные знания по другим смежным и несмежным наукам. Как минимум, хорошо бы понимать как устроено то, чем ты занимаешься — не только до железок, и даже не до атомного уровня, а вообще до начала времен, до Большого взрыва.
Можно, конечно, писать программы, не зная даже, как устроена операционная система, на которой они запускаются. При этом они будут хорошо работать, а тебе хорошо платить. Но в этом случае ты сам для себя будешь волшебником, творящим магию, смысл которой не понимаешь. А незнание порождает неуверенность и страх. Ну или, как минимум, отвлекает. В идеале, если бы тебя в машине времени перекинуло на 2000 лет назад, ты должен уметь так объяснить все устройство твоего мира и технологий, чтобы древние люди могли перейти в современность в течении жизни нескольких поколений.
Но не только уверенности и спокойствия ради нужно знать другие области знания. В каждой из них проявляются по сути одни и те же закономерности. Например, можно понять многое из жизни людей, изучая как образуются химические связи, а из жизни народов — изучая, скажем, астрофизику или биологию. Постигая каждую следующую науку, каждый новый предмет, мы по сути всего лишь учимся думать, все глубже и глубже постигать отношения и взаимосвязь вещей, противоречия между ними. А атомы или звезды — это всего лишь материал для постижения общих законов мышления. Поэтому если абстрагироваться от конкретного изучаемого предмета, а взять все эти вещи и отношения в чистом виде, в виде чистых мыслей, то мы получим науку о мышлении — логику, или, если взять шире, философию.
Знание философии (не истории философии, а именно философии — например, диалектической логики Гегеля) так же важно для программиста, как и знание языка и основных техник программирования. А порой, даже важнее. Ведь чтобы написать хорошую программу, нужно прежде всего составить правильную модель предметной области, для которой разрабатывается программа. Есть хорошая модель — будет и хорошая программа. Только так. Чтобы составить модель, нужно понять предмет, осмыслить его. Чтобы осмыслить предмет, нужна философия.
Все мы пользуемся на интуитивном уровне такими философскими категориями, как движение, количество, качество, сущность, понятие. Но многие ли из нас смогут сейчас сказать, что они означают? А кто сможет вывести понятие из сущности? Кто знает наверняка, всё ли находится в движении, или есть что-то, что не изменяется? То-то и оно. А ведь если знать, что такое сущность сама по себе, можно гораздо легче и быстрее определить сущность и любого конкретного предмета.
Получается, что хороший программист не может быть только программистом. Парадокс — *чтобы стать хорошим специалистом, нужно перестать быть специалистом*.
Итак, если подытожить, то у программиста только два пути: налево пойдешь — богатому быть, направо пойдешь — убитому быть смириться и мучиться, как все, копаясь в legacy-коде, или потратить долгие годы на самообразование и наработку техники разработки качественного кода.
У менеджеров аналогичный выбор: или терпеть плохой код и постоянно сдвигать сроки релиза, или заранее заложить больше времени и тратить его на периодический рефакторинг кода в надежде однажды получить достойный проект, а потом, может, даже сделать из него фреймворк.
Однако, есть и третий вариант — взять готовый фреймворк, дать своим разработчикам неделю-две в нем разобраться, а потом клепать игры по шаблону и горя не знать. Тут на ваше рассмотрение как раз и представлен процесс разработки такого фреймворка — результата многочисленных переписываний и поисков оптимального баланса между универсальностью, гибкостью и простотой.