В Space Ape есть много общего кода, который мы используем во всех наших проектах. На данный момент у нас есть 57 модулей общего кода; они варьируются от систем обмена сообщениями, ведения журнала и нашей игровой консоли до крауд-рендеринга и обработки ресурсов.

Зачем делиться кодом?
- Нам не нужно тратить время на изобретение велосипеда.
- У нас есть гибкость, чтобы использовать необходимые нам общие модули.
- Мы уверены, что этот код поставляется с набором модульных и интеграционных тестов.
- Мы знаем, что это было доказано на практике в предыдущих проектах.
- Все мы знакомы с кодом, что значительно ускоряет запуск проекта.
Совместное использование кода позволяет разработчикам больше сосредоточиться на конечном продукте, в нашем случае на играх, которые мы создаем, потому что они тратят меньше времени, беспокоясь о деталях реализации на низком уровне и нефункциональных требованиях.
Путешествие
Весь этот общий код появился не в одночасье. Мы несколько раз пробовали и терпели неудачу в процессе выпуска, распространения и совместной работы. В результате неудач и извлеченных уроков из этих сбоев мы теперь можем легко делиться своим кодом, и все разработчики из различных проектов вносят свой вклад в это.
Процесс ни в коем случае не идеален - мы все еще работаем над устранением недостатков, - но он значительно улучшил наш рабочий процесс, и, возможно, он сработает и для вас.
В начале были только Ctrl + C, Ctrl + V
Когда Space Ape только начинала, мы все были сосредоточены на одном проекте, поэтому не было необходимости делиться кодом. Мы были стартапом, и нашей основной целью было выпустить продукт.
Когда пришло время начать наш второй проект, часть кода была скопирована из первого проекта, и мы удалили все зависимости проекта, но у нас была база кода для начала. Наша первая игра все еще разрабатывалась, ошибки исправлялись, а функции добавлялись.
В то время как все это происходило, две кодовые базы довольно сильно расходились. Если ошибка была исправлена в одной из наших игр, есть большая вероятность, что исправление не вошло в другую игру - то же самое касается функций и улучшений. По мере развития каждого проекта «общий» код изменялся, чтобы соответствовать каждому проекту, и, в конце концов, совместное использование кода между проектами доставляло больше хлопот, чем пользы.
Контекст проблемы
Прокатитесь на несколько лет вперед. Теперь у нас есть несколько уже известных игр: Samurai Siege, Rival Kingdoms, Transformers: Earth Wars и Fastlane, и мы заключили партнерские отношения с Supercell.
Неудивительно, что цели нашей компании немного изменились. Мы больше не стартап в полном смысле этого слова. Наша цель - создать жанр, определяющий мобильный хит, и при этом мы отходим от нашего наследия строительства и битв.
Мы развиваемся во многих новых жанрах, поэтому нам нужно действовать быстро. Мы не можем предсказать, что каждая новая игровая идея будет успешной. Нам нужно быстро пробовать новое и как можно быстрее учиться.
Наличие прочной основы общего кода поможет нам выполнять итерацию быстрее. Для этого нам нужно будет подумать о том, как мы могли бы делиться кодом между проектами с минимальными трудностями и замедлением, насколько это возможно. Когда дело доходит до совместного использования кода, самым большим препятствием является не написание самого кода, а инструменты и методы его выпуска и распространения.
Введите подмодули Git
Подмодули Git похожи на репозиторий внутри репозитория. Вы можете продолжить работу над своей базой кода, и как только вы закончите работу над функцией или исправите ошибку, вы можете зарегистрировать ее. Вы просто отправляете свой общий код в один репозиторий, а код вашего проекта - в другой.
Сначала это казалось идеальным! Мы уже использовали Git в нашей студии, поэтому все были с ним знакомы. Но вскоре мы столкнулись с проблемами.
Поскольку исходный код доступен для свободного редактирования, команды, очевидно, будут изменять общий код, проверять его, а затем, когда другая команда вносит изменения, их код не компилируется! Это звучит немного лениво и безрассудно, но эта проблема возникает из-за того, что нет границы между общим кодом и тем, что нет. С точки зрения команды, они просто меняют код в одном большом решении. Идеальным решением здесь является предоставление игровым командам простого, но четко определенного API.
Итак, как только это стало проблемой, каждая команда решила отделить общие модули от основной ветки, и мы вернулись к исходной точке. Два расходящихся кода, которые никогда не сливались.
Кроме того, мы обнаружили, что любой, кто не является разработчиком (художники, аниматоры и т. Д.), Может испытывать трудности с использованием субмодулей. Инструменты для работы с субмодулями не так просты. Часто мы обновляли подмодуль, но кто-то не извлекал изменения для этого подмодуля, поэтому проект и общий код не синхронизировались.
Maven
Разработчики наших серверов используют Maven для управления и выпуска пакетов. Maven - это инструмент, разработанный для экосистемы Java. Когда вы будете готовы выпустить свой проект, Maven возьмет всю информацию в pom-файл, а затем упакует ваш код, чтобы его можно было передать другим.
Из-за всех функций, предлагаемых Maven, и того факта, что это не родная цепочка инструментов .Net, она часто казалась более сложной, чем нужно было. Из коробки в него входят такие вещи, как управление жизненным циклом сборки. Но в конце концов все, что нас действительно интересовало, - это управление зависимостями, управление версиями и упаковка; и это было связано с большими накладными расходами. В итоге мы создали настраиваемые этапы сборки для установки наших пакетов, что еще больше усложнило процесс сборки и выпуска. Поскольку он изначально не поддерживался (или не разрабатывался) ни для Unity, ни для .Net, мы сочли, что должно быть лучшее решение.
Пакеты Unity
Поскольку мы используем Unity, следующая технология, которая пришла на ум, были Unity Packages, как вы видите в Asset Store. Интегрировать было действительно легко. Однако весь процесс выпуска и хранения пакетов не регулировался. Нет реальной поддержки версий пакетов и управления зависимостями. Вам также понадобятся дополнительные инструменты для удаления пакета, поскольку нет определенной структуры пакета, поэтому нам придется очистить старый пакет перед установкой нового.
Наконец, пакеты Unity традиционно содержат исходный код. Мы хотели остановить команды, вносящие изменения в исходный код в этих общих модулях, и сократить время компиляции. Это означало, что нам нужно использовать библиотеки динамической компоновки. DLL также позволяют нам легко разрабатывать модули общего кода, которые зависят от других модулей, без необходимости проверять, что исходный код для зависимости является правильной версией и изначально скомпилирован. Более того, использование DLL также приведет к сокращению времени компиляции.
Мы посмотрели в другом месте и обнаружили:
NuGet
Если вы раньше не сталкивались с Nuget, это система управления пакетами, разработанная специально для платформы .Net и поддерживающая управление зависимостями. В настоящее время в публичном репозитории находится более 110 000 пакетов, некоторые из которых мы уже использовали. Однако этот репозиторий является общедоступным, и большая часть нашего кода не предназначена для публичного выпуска, поэтому мы не могли просто продвигать наши пакеты в этот общедоступный репозиторий.
Прежде чем мы смогли начать, нам пришлось немало поработать, чтобы настроить весь процесс разработки и выпуска для Nuget, не говоря уже о настройке нашего собственного сервера пакетов Nuget и чтобы все нормально работало с Unity. В моем следующем посте в блоге я расскажу вам обо всем, от начала до конца.