Доброго дня. Меня зовут Илья и я — перфекционист.
Одна из главных проблем большинства стартаперов состоит в том, что они так и не становятся стартаперами: они просто не в состоянии закончить свой первый проект. Схожие трудности испытывают некоторые фрилансеры — у них не всегда выходит закончить проект в срок.
У этих проблем есть общее достаточно тривиальное решение. Но никто не решается отказаться от идеальности своего кода и вместо того, чтобы получить завершённый проект, обычно делают проект мечты.
Месяц назад наша команда, состоящая из полутора дизайнеров и полутора кодеров взяла первое место на региональном чемпионате по скоростной разработке игр. На разработку давалось всего 48 часов. Двое суток, целиком состоящих из кофе и нервов дали итогом самый завершённый из проектов конкурса. Я расскажу вам, что мне пришлось сделать с собой и своим желанием написать идеальный код, который не страшно будет показать людям.
Если говорить отстранённо – то конкурсная игра должна была стать маленьким проектом, без долгосрочной поддержки с одним-двумя патчами и подготовительным этапом. Два главных критерия оценки таких проектов — это логическая завершённость и соответствие тематике. Очень многое зависело от условий конкурса. Сразу оговорюсь: по его условиям можно было выбрать любой язык, любой фреймворк, любые движки и любой арт, при условии что все лицензионные проблемы ложатся на исполнителя. Были также усложнённые варианты правил, по которым в конкурсе должен был участвовать один человек и по окончанию предоставить все исходники, но наши организаторы от них отказались. В любом случае мной был выбран чистый ActionScript без каких либо движков.
Работа без ТЗ. Подготовительный этап
Конкурс начался в восемь вечера в пятницу. С этого момента можно было начинать делать уже что-то — рисовать основные заготовки дизайна, писать базовые модули кода, придумывать концепцию игры. Однако, тематику игры все команды получили только к утру, общую для всех и заранее неизвестную. Изначально был известен лишь массив в 25 возможных тем, из которых общемировым голосованием к восьми утра субботы была выбрана очень неожиданная для всех «Эволюция». Тут проявилась наша первая проблема, решив которую мы и поймали ту самую волну раздолбайства, позволившую вовремя закончить игру.
Вечер пятницы мы потратили на движок игры, подходящей под 20 из 25 тем. Мы пропускали сильно разнящиеся моменты, надеясь что к следующему дню просто подгоним уже готовый движок под любую тему. Когда мы узнали, что тема входит в те пять неучтённых, результат подготовительных работ пришлось просто выбросить. На деле этот подготовительный этап, когда уже точно известно, что мы будем делать, но ещё не известно, что мы будем делать, очень важен, и он есть всегда и у всех. У фрилансеров — когда они взяли заказ, но заказчик не торопится с ТехЗаданием; у энтерпрайзов, у которых производство ПО поставлено на поток — есть ядро, которое они выращивают и дебажат всё свободное от заказов время; у инди — момент, когда дизайн-документ ещё не выверен, а руки уже чешутся написать хоть что-то. В этот момент лучше всего делать действительно общие для всех проектов вещи. Например, во всех играх нужен таймер — сделайте таймер универсальным, выверенным до миллиметра, с удобным запуском и вызовом нужных вам методов. Или главное меню. Или прелоадер/установщик. Даже для дизайнеров можно придумать какие-нибудь шаблоны того же главного меню и наброски интерфейса. Я бы сэкономил себе кучу нервов, если бы за те восемь часов первого дня писал движок для сообщений с клавиатуры и мыши, чем оттачивал бы оказавшийся никому не нужным движок передвижения персонажа.
Волна раздолбайства, или когда пора перестать планировать и начинать делать.
Утром в субботу мы с дизайнером пришли в офис, чтобы в срочном порядке придумать игру, которая подходила бы под неожиданную тему. Тут надо сделать лирическое отступление и заметить, что наша команда называлась «Who cares?», что в вольном цензурном переводе может означать: «А кого вообще волнует?». Мы стояли у проектной доски и смотрели на неё без единой мысли в голове, пока кто-то из нас не произнёс: «А кого вообще волнует эволюция? Кому нужны сложные игры с разветвлённым сюжетом, тем более построенные за два дня?». Решено было делать очень простую игру с примитивным геймплеем, построенную на чистом фане. Сутью игры было провозглашено скучающее божество, решившее опровергнуть теорию эволюции на практике, при помощи своего божественного тапка уничтожающее наиболее приспособленные виды монстров на некой абстрактной планете. Дизайнер сел искать примеры арта и цветовые гайдлайны (понятия не имею, что это значит), а я написал дизайн-документ.
Сначала в диздоке было всего одно предложение: «Это игра про нарушение законов эволюции божественным тапком». На протяжении двух суток диздок пополнялся всё новыми и новыми фичами, но ни одна из них не противоречила первоначальному утверждению. Прелесть подобной формулировки в том, что она позволяет начать работу сразу же, не продумывая подробности по несколько часов. Она даёт однозначный ответ на вопрос «что делать?» не заморачиваясь на условности, вроде: «как именно делать?». Наилучшим вариантом будет, если хотя бы первое время не возникает вопросов, подобных «как?». Задача есть, она сформулирована и, хоть не уточнена, её уже можно помаленьку реализовывать. Обсуждая пополнение дизайн-документа с командой я не заострял внимание на подробностях. Всё, что нужно было добавить в этот документ — отвечало на вопрос: «что?». Если дизайнеры спрашивали меня «а какой должен быть цвет у элемента интерфейса» — я отвечал просто «Do your best». Если я сам себе задавал вопрос: а как монстры должны бороться друг с другом, как должны общаться с остальным кодом — отвечал «как-нибудь, лишь бы это работало». Стоит ли говорить, что вопрос планирования архитектуры даже не поднимался?
Причина подобной отстранённости весьма проста. Как бы идеален не был ваш код, насколько бы он не соответствовал стандартам и какие бы сложные паттерны программирования он не реализовывал — конечный пользователь их не увидит. Для пользователя важно, чтобы программа не падала и не тормозила. А если в процессе основного workflow пользователь не поймает ни одного исключения, если он пройдёт вашу игру на одном дыхании — он не вспомнит о том, что провалился в текстуры на третьем уровне или на пятом его как-то не так атаковал противник. По сути, пользователя надо взять за ручку и показать ему все интересные места вашего продукта, старательно избегая тех, которые могут вызвать проблемы. Верно и обратное: внимание лучше всего акцентировать на тех участках кода, к которым пользователь обратится вероятнее всего.
Не переусердствуйте
Однако, фанатизм вреден даже в таком полезном методе разработки, как игнорирование конкретики. Есть несколько узких мест, на проработку которых всё же стоит потратить немного драгоценного времени. Например, когда предстоит однообразная монотонная работа, особенно если выполнять её придётся не вам. Чтобы описать проблему, которая стоила нашей команде потере дизайнера на полпути, надо сделать небольшое отступление и пояснить суть программирования графики на Flash.
Изначально flash был предназначен для проигрывания и простого управления разнообразными анимациями. ActionScript третьей версии это вполне себе объектно-ориентированный управляемый событиями язык, но ранее во флешевых приложениях мало кто использовал классы и вообще отдельные файлы. Весь код обычно вызывался не какими-то пользовательскими действиями, внутренним таймером или общением с сервером, а просто по входу на какой-то определённый кадр анимации. У флеш-разработчиков есть даже свой исторически сложившийся ярлык: «код в кадрах», означающий обычно способ работы начинающего кодера. Код в кадрах как таковой и так называемый принцип «программирования мышкой» обычно приводят к тому, что исправить замеченную ошибку становится довольно трудно. Если же эта ошибка типовая и присутствует сразу в нескольких анимациях — время исправления ошибки вырастает прямо пропорционально. Поиском-и-заменой обойтись не получится — надо вручную заходить в каждую анимацию и вручную же исправлять.
В нашей игре изначально планировалось реализовать анимации к тридцати девяти видам монстров, на каждого по четыре действия. Запуск и остановка анимаций производятся кодом по наступлению некоторых внутриигровых событий. Из-за того что сходу аниматору не был предоставлен шаблон, которому должны соответствовать все эти анимации — незначительная, но очень заметная игроку ошибка закралась в большую половину анимаций. Исправлять пришлось всем вместе, была потрачена куча времени, дизайнеры разругались и один из них отказался продолжать работу.
Ещё один момент, который заслуживает проработки — это интерфейс начала и конца работы каждого из обособленных блоков кода. Для команды, в которой работает больше одного программиста — это правило становится ещё более важным. Через границу зон ответственности каждого из них должны быть прокинуты однозначные и прочные мостки вызова и завершения. Строго говоря, вторым программистом при некоторых условиях может стать единственный, когда возвращается к старому коду через продолжительное время. Поэтому, если вы не планируете закончить работу над блоком кода с первого захода, лучше будет озаботиться наличием такого интерфейса.
Завершение разработки, путь к релизу
Когда время разработки подходит к концу, а проект — к своему первому релизу, очень полезным будет умение смириться с мыслью о том, что в первый релиз могут войти далеко не все запланированные фичи. Чем раньше вы смиритесь, тем быстрее можно будет приступить к порезке фичелиста. Если вы сами писали для себя дизайн-документ, сделать это проще простого: берётся весь нереализованный функционал и ставится в соответствие с первым предложением «Это будет проект о...». Если фича логически не связана с ним — её можете выбросить без сожалений. Если список на реализацию всё равно остаётся достаточно длинным — сортируйте его в приоритете скорости выполнения, не обращая внимания на важность функционала для самого проекта. Даже если функционал был очень важен — думать об этом перед релизом уже поздно. Более того, чем больше важного вы упустите — тем больше мотивации у вас будет на скорый выпуск патча. К примеру, из нашей игры без особого сожаления был выброшен арсенал оружия, анимацию которого пришлось бы долго отрисовывать дизайнеру и резко был понижен приоритет проблемы отсутствия музыки в игре в пользу добавления двух дополнительных слайд-шоу концовок.
Если времени осталось действительно мало, можно даже не обращать внимания на большинство некритичных багов: фиксить стоит лишь те, которые ломают основной workflow программы. Так, например, в первом релизе нашей игры остался баг с бесконечностью битвы монстров, выяснявших отношения в момент попадания по ним тапком. Зато у меня осталось время убрать ошибку с двойной рассылкой сообщения о смерти монстра, незаметную, но значительно увеличивающую нагрузку на процессор. Опять же, совсем игнорировать такие баги не надо, их исправление лучше перенести в первый патч. Как говорил мой учитель информатики: порой лучше иметь десять ошибок в программе, чем одну. Особенно когда те десять — синтаксические, а одна — «программа не работает». Проекты первого типа уже давно зарабатывают деньги и могут себе позволить их тратить на саппорт и выпуск патчей, а вторыми никто не пользуется.
Пострелиз. Патчи и рефакторинг
И вот, этот момент наконец-то настал. Вы выпустили проект. Это и только это главное. Вы получили поздравления, или нагоняй — не важно. У вас есть готовый проект. Немного забагованный, чуть более простой, чем планировалось, но готовый. Теперь можно расслабиться после гонки со временем и приступить наконец к рефакторингу. Именно сейчас, и ни минутой раньше можно сесть и подумать, как же лучше связать код сам с собой, чтобы было проще его поддерживать. Если вы осознаете, что проект перешёл из стадии разработки в стадию поддержки — работать над проектом станет гораздо проще. Когда вы взглянете на список не попавшего в релиз — баги разбегутся перед вашим величием, а нереализованные фичи сами встанут на свои места, лишь с небольшой вашей помощью. Всё это время вы терпели и копались в своём же говнокоде, били себя по рукам и останавливали, когда хотелось срочно расставить код по своим местам: теперь вы можете себе это позволить и приступить наконец к патчам.
А как делать следующий проект — вы уже знаете.
Автор: bukt