Как жить и развиваться на проектах с историей. Что дает разработчику опыт работы c большой кодовой базой, и почему не нужно стремиться переписать все с нуля, если даже очень хочется.
Содержание
- Для кого этот текст
- Чему вы можете научиться на проекте с историей
- Какие вопросы задавать на собеседовании
- Советы тем, кто только начал работу с легаси-проектом
- Кратко
Я Павел Новиков, участвую в разработке мобильных приложений «МойОфис Документы» и «МойОфис Почта». Это приложение для совместной работы с документами и почтовый клиент, которые начали создаваться в 2013 году, поэтому можно их назвать проектами с большой кодовой базой, где есть место и легаси в том числе.
Описанный тут опыт применим не только к работе над мобильными приложениями и масштабируется на разработку приложений вообще.
Disclaimer для самых маленьких
В этой статье я собрал размышления о своей работе на основе того опыта, который у меня есть на сегодняшний день. Любые статьи подобного рода всегда являются крайне субъективными. Я уверен, что существуют люди с опытом, который противоречит моим наблюдениям. Буду рад обсудить эти расхождения в комментариях.
Для кого этот текст
Текст рассчитан как на тех, кто причисляет себя к уровню Junior, так и на тех, кто попадает под категорию Middle/Senior.
В работе с долгоживущими проектами можно многому научиться на любом из уровней разработки. Чтобы быть на одной волне в понимании уровней, прочитайте посты Вастрика: Войти вайти и К — Команда. Мне нравится его классификация уровней разработчиков, и я буду ее придерживаться в дальнейшем.
В следующем блоке разберем кратко, в чем польза для каждого из уровней на долгих проектах.
Junior
Задача Junior разработчиков — максимальное развитие технических навыков. В ход идет все: языки, фреймворки, библиотеки, подходы к разработке и т.д. На любом проекте с сильной командой вы сможете учиться решать разные задачи.
Но на зрелых проектах у вас, во-первых, будет возможность более глубоко погружаться в какую-либо область и, во-вторых, вы сможете изучать примеры удачных и неудачных решений. Обучение на чужих ошибках дорогого стоит. Особенно если рядом есть более опытные коллеги, которые могут вам подробно объяснить смысл этих ошибок и как их можно избежать.
Middle
Задача Middle разработчика — повышение своей автономности. Вы должны стать членом команды, которому можно доверить практически любую задачу на проекте. Это значит, что чем более разнообразные задачи есть на проекте, тем больше у вас потенциальных направлений роста.
Senior
Задача Senior разработчика — полное осознание, что вам платят не за код, а за решение проблем. Иногда (пока все таки чаще) через написание кода, иногда через управление другими разработчиками, иногда через общение с не-разработчиками. Зрелые проекты — просто кладезь задач, которые можно и нужно решить.
Далее я более детально расскажу о некоторых вещах, которым вы сможете научиться на уже существующих проектах.
Причем тут легаси?
Для начала нужно разобраться с терминологией. Понятие «legacy» давно приобрело негативный окрас, но чем именно плох унаследованный код?
Майкл Фезерс (Michael Feathers), основатель R7K Research & Conveyance, утверждает, что легаси код — это код, не покрытый тестами. Преимущество такого подхода в том что, с первого взгляда, он претендует на объективность. Но в реальности могут быть два сценария:
- Тесты есть, но написаны плохо: запутанные, хрупкие, неочевидно структурированные.
- Тестов нет, но код очень хорошо спроектирован. Это дает возможность относительно безопасно его менять и, в случае чего позволит быстро написать к нему тесты в будущем.
Еще один взгляд на то, что такое легаси от разработчика Дро Хелпера (Dror Helper): No longer engineered — continuedly patched and hacked («Легаси-код — код — код, который постоянно ломают и подпирают костылями вместо того, чтобы его развивать»).
Веб-разработчик Николас Карло (Nicolas Carlo) считает, что легаси код — это код, с которым некомфортно работать.
Из всего этого можно сделать вывод, что легаси — это скорее субъективная характеристика кода. Сам код может работать или не работать, но легаси он станет тогда, когда появится разработчик, который не сможет его эффективно модифицировать.
Еще одна относительно объективная характеристика для оценки легаси — ответ на вопрос «есть ли в проекте какие-то неподдерживаемые зависимости». Код может собираться только какими-то конкретными устаревшими версиями компилятора. Или авторы самостоятельно пропатчили какую-то внешнюю библиотеку, и она теперь стала частью основного проекта. В этом случае, действительно, проект становится специфическим, и для его поддержки нужны дополнительные усилия.
В общем, если проекту больше полугода, то скорее всего в нем будет легаси.
Чему вы можете научиться на проекте с историей?
Итак, вы приняли решение и устроились в компанию, где до вас уже писался код и происходило еще много чего. Добавлю, что вам необязательно идти в новое место, чтобы прокачивать свои профскилы. Легаси скорее всего, есть в каждом проекте, надо лишь знать, как его оценить. И то, о чем я рассказываю, наверняка можно применить к тем вещам, над которыми вы работаете сейчас.
В каких областях прокачка будет полезна одинаково и вам, и проекту? Тут нужно понимать, что ситуация, когда вы развиваетесь там, где болит у проекта — это идеальная среда для обоюдного роста. Потому что если вы будете развиваться в работе над какими-то левыми вещами, то это может быть плюсом лично для вас, но при этом будет сложно объяснять, зачем компании вам в этом помогать.
Анализировать проект
Первое, чему вы можете научиться в работе над проектом с наследием — его анализировать. Допустим, вы пришли на проект, где есть пробелы с документацией, или ее нет вовсе. В этом случае у вас будет только исходный код проекта, поэтому критически важно уметь его анализировать и быстро понимать его структуру и суть. Это важно, потому что чем раньше вы научитесь в нем ориентироваться, тем быстрее вы начнете приносить пользу проекту.
Самое главное, что могу посоветовать для углубления в тему анализа проекта – прочесть книгу «Эффективная работа с легаси-кодом» Майкла Физерса. Она старая и известная. В ней описывается большое количество практик по работе с унаследованным кодом.
И еще один совет — зайти на сайт Understand Legacy Code. Это блог, посвященный одной тематике – работой с легаси. Важно, что там можно подписаться на рассылку. Уверен, многие Android-разработчики знают про рассылки Android Weekly и Kotlin Weekly. Рассылка ULC тоже очень полезна. Она не навязчивая, с практическими статьями про рефакторинг и написание кода.
Делать рефакторинг
Легаси-проекты – это отличное место для того, чтобы качать навык рефакторинга. Вы приходите на проект, в котором скорее всего есть проблемы, и вам его нужно не только менять, но и улучшать, расширять и пилить новые фичи. От того, насколько хорошо и эффективно вы умеете рефакторить (быстро и с маленьким количеством регрессий), зависит то, насколько вы будете полезным и хорошим разработчиком.
В зрелом проекте со здоровой инженерной культурой рефакторинг должен быть постоянной частью разработки.
Вам должен нравиться продукт, над которым вы работаете. Совсем отлично, если вы сами можете им пользоваться. В этом случае случае у вас будет внутренняя мотивация долгосрочно работать над улучшением его качества.
Проектировать и создавать архитектуру
Этот пункт вытекает из предыдущего — вам неизбежно нужно будет прокачиваться в проектировании ПО и архитектуре. При правильной культуре разработки у вас не будет необходимости принимать серьезные архитектурные решения в сжатые сроки. У вас будет время на проработку архитектуры и ваша ответственность будет в том, чтобы сделать это хорошо. Что я тут всегда советую? Читайте книги.
Я считаю книги не менее важными, чем другие источники информации. Чем больше опыта вы наберетесь из книг, тем больше и быстрее будете понимать, как решать типовые проблемы. К типовым/типичным проблемам всегда есть типичные решения, которые можно найти в книгах. Работа с любым видом легаси так же предполагает решение типовых проблем.
Книги по архитектуре
Роберт Мартин (Robert C Martin). «Чистая архитектура», «Чистый код»
Мартин Фаулер (Martin Fowler). «Рефакторинг. Улучшение проекта существующего кода»
Инструменты
для проектирования архитектуры
UML — используем для проектирования.
PlantUML (PUML) — библиотека и сервис, которые позволяют в текстовом виде описывать UML-диаграмму. Его можно хранить в git, следовательно можете к процессу обновления и обсуждения этих диаграмм подключить те инструменты, которые используете для работы с обычным кодом.
Декомпозировать
Когда вы работаете с продуктом, который для вас не полностью понятен, вам, так или иначе, нужно будет научиться оценивать ту работу, которую предстоит сделать. И всегда у вас будет что-то, чего вы не знаете, какие-то подводные камни.
Умение разбить большую и сложную задачу на набор небольших взаимосвязанных частей — очень ценный навык. Один из способов его развить состоит в постоянной ретроспективной работе над ошибками декомпозиции и оценки. В процессе анализа из часто встречающихся ошибок можно составить чек-лист. В дальнейшем он сможет помочь вам не допустить эти ошибки повторно.
Автоматизировать и уметь применять CI/CD
Вам нужно понимать, что происходит с вашим кодом от момента, когда вы его пишете, до момента, когда он достигает устройства пользователя. И у вас будет возможность автоматизацию и CI/CD настроить, поддерживать и улучшать. В компаниях, где нет выделенной инфраструктурной команды, эти операции могут и должны (я в этом убежден) решать члены основной команды разработки. Современные инструменты (cloud CI, Docker) не обладают невероятной сложностью, но очень сильно упрощают жизнь команды. Вы сможете принести ей много пользы, если овладеете этими навыками.
Общаться
Чем больше у вас будет ответственности, тем с большим количеством людей вам придется общаться. Разработка ПО давно перестала быть уделом одиночек: почти все крупные проекты делаются командами. Опять же, чем эффективнее вы научитесь взаимодействовать с окружающими, тем больше пользы сможете принести.
Вам придется общаться с людьми, которые умнее и опытнее вас. В крупных проектах всегда есть «старожилы», у которых можно многому научиться. Также вам будут встречаться люди, которые глупее вас. Хорошая новость в том, что скорее всего вы ошибаетесь в оценке умственных способностей — очень полезно уметь исправлять такие ошибки восприятия.
Я считаю, что развитие навыков общения можно свести к развитию чувства эмпатии. Чем лучше вы научитесь понимать мотивацию и цели окружающих людей, тем быстрее вы сможете стать полезными для них. Например, объясняя бизнесу пользу рефакторингов и работы над техническим долгом, вы должны использовать термины бизнеса, а не программиста. Очевидная, казалось бы, идея, но я неоднократно видел, как одни умные люди общаются с другими умными людьми и не могут друг друга понять.
Какие вопросы задавать на собеседовании
Здесь я буду отталкиваться от того, какие вопросы я бы задал, перед тем, как идти работать на проект, о котором мало знаю.
Как устроен рабочий процесс и почему именно так
Обычно сейчас работают по системам Scrum или Kanban. Но при этом часто адаптируют их под себя: «взяли лучшее, ненужное выкинули». Вопрос: что именно они выкинули, а что оставили? Потому что в Scrum guide, на основе которого строится процесс разработки, есть довольно интересные и полезные практики.
Они имеют смысл, когда применяются, во-первых, осознанно, во-вторых, применяются все. Потому что составляют такую систему, которая сама себя контролирует и позволяет итеративно улучшать не только проект, но и собственные процессы.
Например, если команда работает по Scrum, я бы спросил, что обсуждали на последней ретроспективе. Насколько команда вообще активна на этой встрече? Решаются ли поднятые проблемы?
Другой интересный для меня вопрос по внутренним процессам: как в команде проводится code review? Есть ли какие-то внутренние правила проведения review, которые помогают сократить его время? Существует ли общая база знаний, в которую заносят результаты холиваров, чтобы не устраивать их каждый раз?
Как происходит планирование, кто участвует и насколько активна команда
Этот вопрос я бы задал, чтобы посмотреть, насколько сильна инженерная культура внутри команды. Бывает вариант, когда планирует только тимлид, а команда у него на подхвате.
Другой вариант — это когда вся команда участвует в планировании. И когда приходит задача, ее берется расписать тот, у кого достаточно экспертизы в этом вопросе. А дальше все обсуждают и принимают решение. В этом случае команда получается более самоорганизованной, а рабочий процесс более приятным.
Сколько в команде людей, которые обладают всей картиной
Здесь возможны две крайности. Первая крайность — это когда вы приходите в команду, которая работает над продуктом последние 2-4 года. Если при этом команда не сильно менялась, а только расширялась, то это очень хорошо, потому что у вас всегда будут люди, к которым вы сможете обратиться за помощью. Они смогут что-то подсказать, объяснить причину, рассказать вам историю проекта. Знать контекст и почему все устроено так, а не иначе — очень важно.
Вторая крайность — это когда вы приходите в команду, в которой нет никого из тех, кто был на старте. Например, проект был заморожен, его разморозили, и осталась большая кодовая база. С нуля переписывать нельзя. Соответственно, нужно восстанавливать разработку. То есть вы получаете проект, в котором заново нужно будет все раскапывать.
На основе этой информации вы сможете принять более взвешенное решение о том, хотите вы туда или нет, и, может быть, переоценить какие-то ваши требования к предложениям, на которые вам нужно ответить.
Как ведется бэклог технического долга
Проблемы есть в любом проекте, и важно понимать, как именно команда с ними работает. О работе с техническим долгом очень хорошо написал alexanderlebedev в статье «Ланнистеры всегда платят свои долги! (и технические тоже)».
Если в команде знают о проблемах, но не умеют систематизировано с ними работать, то это плохой знак. Но можно посмотреть на это и как на возможность стать тем человеком, который поможет эти проблемы решить.
Советы тем, кто только начал работу с легаси-проектом
Боритесь с соблазном броситься переписывать все с нуля
Обычная ситуация: вы начали работу над уже существующим приложением и видите, что там все сделано «не так». И с этим «не так» вам нужно работать дальше. Вполне естественное желание в этом случае — взять и переписать все это заново. Это нормальная реакция.
Я думаю, что в ее основе лежит нежелание отвечать за чужие ошибки. Ведь если после ваших доработок появятся новые дефекты, то разбираться уже придется вам. Так уж лучше тогда переписать его полностью, и все будет отлично.
Если вы заметили, что вас посещают такие мысли, задайте себе несколько вопросов:
В коде точно есть достаточно проблем, или вы его просто пока не понимаете?
Вы уверены, что точно понимаете все точки интеграции переписываемого кода?
Вы достаточно хорошо знаете проект, чтобы верно спрогнозировать предстоящее время на работу?
Пока я убежден, что намерение сразу броситься все переписывать с нуля — плохая идея. Улучшения должны быть итеративными и контролируемыми.
Однажды я стал свидетелем того, когда команда сказала, что «Все фигня, давайте перепишем», переписывали полгода и не переписали. В итоге сложилась довольно интересная ситуация, когда проект нужно было опять лидить с нуля, набирать новую команду, потому что старая команда отвалилась. Старайтесь погасить это абсолютно естественное желание переделать все с нуля.
Прогнозируйте изменения проекта
Вам нужно научиться быть немножко оракулом. Работая с проектом долго, вы научитесь понимать его продуктовую составляющую, научитесь понимать бизнес, как этот проект зарабатывает, за счет чего он живет. Это даст возможность оценивать долгосрочную перспективу тех решений, которые вы принимаете.
Весьма полезный навык, потому что плоха ситуация, когда к вам приходит product owner и просит сделать что-то простое с его точки зрения. Например, добавить новый критерий для сортировки списка. А с вашей стороны это будет означать, что нужно весь этот компонент переписать заново. Этого не случилось бы, если бы вы заранее подумали, что разные способы сортировки того списка — вполне логичная функция. Хотя ее и не просили сделать в первую очередь.
Только не нужно впадать в крайность и пытаться всегда делать как можно более универсальные решения. Это прямой путь к растягиванию сроков и проблемам с дальнейшей поддержкой таких решений. Весь смысл этого навыка как раз и состоит в поиске баланса.
Проводите исследования
Когда вы работаете с долгим проектом, важную роль играет то, насколько бизнес доверяет команде. Перед разработкой какой-то крупной фичи мы обязательно проводим полноценное исследование предметной области. Может звучать как капитанское капитанство, но я знаю случаи, когда люди сразу бросались в омут с головой, и вроде бы простые задачи превращались в долгие рефакторинги, которых можно было бы избежать, просто проведя исследование перед разработкой.
Уделяйте время документации
Документируйте то, о чем договариваетесь, документируйте процессы, документируйте архитектуру. Тут я стараюсь придерживаться подхода, что если не записали, то значит не договорились. Потому что в проектах, которые тянутся больше чем полгода, становится критически важной вещью научиться не терять информацию.
Когда вы принимаете какое-либо архитектурное решение, вам оно кажется очевидным. Зачем его как-то пояснять? Через полгода-год в этом архитектурном решении возникают проблемы. И вы думаете: «А почему я его принял? Какой был контекст?». Если вы научитесь записывать эти архитектурные решения, то это станет отличной инвестицией и сыграет вам на руку в будущем.
Одним из способов ведения таких записей является Architecture Decision Records. Его основная идея состоит в том, что для каждого нетривиального архитектурного решения нужно создать файл с несколькими элементами: заголовок, дата, контекст, описание решения, предполагаемые последствия. Этот файл хранится вместе с кодом и не меняется после создания. Его главная ценность в том, что когда придет время менять это архитектурное решение, будет гораздо проще понять мотивацию, которая к нему привела.
Кратко
- Проект с историей — хорошее место для роста разработчика, если ему становится интересно заниматься не только написанием кода, но и задачами, которые помогут развиваться не только как программисту.
- В проектах с бэкграундом проблему создает не код, а люди, то есть такой менеджмент, когда от вас требуют чего-то очень быстрого и постоянно как в геймдеве, например.
- Работа с наследием точно должна быть комфортной для вас в первую очередь. Комфорт создает не код, а люди, потому что код вы переписать сможете, а исправить людей гораздо сложнее.
Текст подготовлен по материалам моего доклада на митапе GDG.