В разработку я хотел попасть давно, но, как это часто бывает, не слишком-то верил в свои силы. Я полагал, что мой поезд давно ушел, и мозги уже не те, чтобы освоить эту сложную профессию. К счастью, меня переубедили, более того, мне дали шанс показать себя и взяли на стажировку в отдел разработки. Это случилось так буднично и просто, что сначала я не мог в это поверить. Мне все время казалось, что вот сейчас-то все наконец поймут, что я неуч и помашут ручкой на прощание. Но этого не произошло, меня продолжали поддерживать, и я изо всех сил старался никого не подвести.
Я стажируюсь в нашем бэкенд-отделе, который занимается продуктами для трекинга и параллельно работаю в своем родном отделе технической интеграции (вот уже на протяжении 6 месяцев). Основной язык в команде — Python. Его я учил самостоятельно, чтобы попасть на стажировку. В основном, конечно, по мануалам и роликам в Интернете.
У меня была небольшая база — я написал несколько учебных проектов на Си, но в целом не могу сказать, что был хоть сколь-то опытным кодером, когда меня приняли на стажировку. С высоты этого скромного опыта я и хотел бы рассказать вам о паре вещей, которые не знал или почти не знал на старте.
Командная работа с Git
Когда человек приходит на свою первую стажировку, он представляет себе, что такое Git (иначе его вообще вряд ли возьмут), однако слабо представляет, как с ним работают в команде. Все мы создавали в свое время аккаунт на GitHub и радостно коммитили в master-ветку первую строчку кода, чувствуя себя настоящими профи. Так вот: это не лучший подход для больших проектов.
В командной разработке работа с Git ведется в соответствии с утвержденным git-flow. У нас, например, есть две ветки: develop и master. Никто, кроме тимлида, не может заливать код в master-ветку, потому что команда должна гарантировать, что там лежит рабочий код, который при деплое не разрушит прод. Ответственность за это ляжет на плечи тимлида, а тимлида злить не хочет никто.
Чтобы предотвратить такие ситуации, существует командное ревью. Каждый разработчик ведет работу над задачей в своей собственной ветке и в конце работы ставит merge request в develop-ветку. А тимлид уже ставит merge request в master-ветку и отвечает за качество кода перед его владельцем. Таким образом гарантируется чистота кода, который попадает в конечном итоге на прод, и минимизируются риски залить что-то, что испортит работу проекта.
Вывод: если вы хотите лучше подготовиться к работе в команде, почитайте о git-flow и начните добавлять новые коммиты в свой пет-проект через ветки.
Архитектура кода важна
Когда я пришел на стажировку, я ожидал, что мне будут говорить, что делать, дадут какую-нибудь маленькую функцию или юнит-тесты, и я буду работать над ними под присмотром команды.
Однако все сложилось иначе. Нет, никто не поручил мне что-то ультрасложное, но мне назначили мини-проект (milestone) по мониторингу (Python + Prometheus + Grafana), который я должен был сделать за время стажировки. Причем я сам должен был продумать архитектуру, декомпозировать проект на задачи и двигать его по стадиям Канбана. Это было волнительно, но очень правильно. Такой подход позволил моему куратору и мне самому отчетливо понять, с чем у меня проблемы, и приступить к их исправлению.
Скажу честно: первое мое решение было неудачным. И второе тоже. Я делал слишком крупные задачи, несколько раз возвращал их в бэклог, выстраивал неудачную архитектуру и не мог учесть нюансы.
Однако на данный момент большая часть проекта уже реализована, и я все отчетливее понимаю, как мой код влияет на остальной проект. Это захватывает. Я прочитал несколько статей о чистой архитектуре, изучил абстрактные классы, научился сначала планировать интерфейс и только потом приступать к реализации. Не могу сказать, что я во всем разобрался, но точно лучше понял фразу «Любую проблему можно решить введением дополнительного уровня абстракции, кроме проблемы чрезмерного количества уровней абстракции». А еще я научился правильно оценивать свои силы (но это не точно).
Вывод: интересуйтесь архитектурой кода. Ничего страшного, если поймете не сразу, это вопрос контекста. Почитайте, как спроектирован Netflix, или загляните на сайт Мартина Фаулера. Попробуйте спроектировать небольшую систему до того, как сядете писать код.
Умение работать с окружением упрощает жизнь
В нашей компании все сервисы запускаются в контейнерах. Соответственно, каждый разработчик должен понимать, как работает тот же Docker, как написать простой Dockerfile или поднять свои сервисы через Docker Compose.
Человеку, который пишет только для себя и на своем компьютере, тяжело понять, зачем нужна контейнеризация. Однако на больших проектах необходимо обеспечить работу кода вне зависимости от окружения. Чуть позднее, когда вы разберетесь с азами, станет очевидно, насколько это удобно. Вам не нужно устанавливать зависимости в свое окружение, нет нужды долго и сложно запускать проект. Вы можете запускать тесты или разделить прод и dev, просто единожды написав пару конфигураций.
В этот же совет можно включить и работу с IDE. До начала стажировки я писал все свои программы исключительно в Emacs, но, когда начал работу, решил перейти на более продвинутый инструмент, и в итоге не пожалел. Кое-где я до сих пор предпочитаю пользоваться консолью (например, опустить все контейнеры удобнее через
docker stop $(docker ps -qa)
), но в остальном я от всей души благодарен Git GUI и подсказкам в PyCharm.Вывод: почитайте о Docker. Попробуйте запустить код в контейнере. Попробуйте IDE для вашего языка и посмотрите, какие возможности она вам может дать.
Документация и тесты — не менее важны чем код
Однажды мой куратор сказал, что тесты — это вторая документация разработчика. И это очень верно, потому что, если реальной документации не хватает, всегда можно пойти в тесты и посмотреть, какое поведение ожидается.
До стажировки я пользовался UnitTest и PyTest, но только в рамках обучения. А Mock, например, не пользовался вообще, потому что мои проекты не были настолько сложны, чтобы нужно было подменять данные (ну, либо мои тесты были настолько плохи).
Я бы рекомендовал всем начинающим разработчикам писать тесты на всю логику, которая встречается в проекте. Даже если вам кажется, что поведение очевидно, лучше подстраховаться. Ведь когда другой человек будет писать функцию, которая использует ваш код, есть вероятность, что он не станет углубляться в детали и именно ваш упавший тест спасет проект от неприятностей.
А чтобы еще больше минимизировать риски, пишите понятную документацию. В Admitad метод или функция без документации вызовут вопросы на ревью. Спустя две недели никто не захочет тратить время на попытки в очередной раз разобраться в чужом коде. Это просто вопрос уважения к коллегам.
В дополнение скажу, что мы еще и подробно аннотируем типы в Python, но если вы пишете на строго типизированном языке, этот комментарий не для вас. (В этом плане очень помогает использование линтера, например Flake8).
Вывод: Уделяйте внимание тестам и документации. Начните с обычного readme-файла на Git — опишите, как запустить проект, что он делает и какой результат ожидается. Попробуйте написать тесты к ключевым методам и функциям, а еще лучше сделайте Docker Compose, который запускает прогон всех тестов.
А какой опыт был у вас?
Состоявшимся разработчикам мои советы могут показаться банальными и очевидными. Я вас прекрасно понимаю, но поначалу мне сильно недоставало системных знаний. Уверен, с этой проблемой столкнулись многие из тех, кто осваивал профессию самостоятельно.
Поэтому я призываю вас поделиться опытом и наблюдениями, которые вы вынесли для себя после первых месяцев (или лет) в отрасли. Что бы вы посоветовали себе на старте карьеры? Какие навыки посоветовали бы развивать? И мне, и другим самоучкам могут пригодиться ваши подсказки, так что не стесняйтесь оставлять комментарии.
SpiderEkb
По поводу работы с гитом.
На мой взгляд, у вас схема несколько упрощенная. Возможно, вам хватает ее для решения ваших задач, но…
Как сделано у нас.
master — в ней находится тот код, который уже установлен в прод. Пока код не на проде, в мастер не мержим. Прямые коммиты в мастер запрещены. Только мерж через пуллреквест. Который должен быть заапрувлен хотя бы одним ревьвером.
develop — ветка для синхронизации. От нее начинаются все новые релизы. Там лежит код, который уже прошел компонентное тестирование и ушел на бизнес-тест. Прямые коммиты тоже запрещены, только мерж из релизных веток с аппрувом PR хотя бы одним ревьвером.
release* — релизные ветки. Из них собираются поставки для компонентного тестирования.
feature* — рабочая ветка. в ней всегда работает один человек. Если релиз собирается из нескольких фич, то каждый разработчик пилит и тестирует свою, а потом они объединяются мержем в один релиз, который уже идет на компонентный тест.
Есть строгий стандарт на именование веток:
feature|release/MNM#nnn_JiraTaskName (плюс еще что-то может быть для фич)
где MNM — мнемоника поставки, nnn — ее номер и далее — имя задачи в Jira (то, что идет после jira.******.net/browse/).
Да, у нас установлена своя Jira и свой гит — BitBucket. И комментарий к коммиту всегда в первой строке содержит
MNM#nnn JitaTaskName
В результате в гите, что в списке коммитов, что в списке веток всегда есть прямая ссылка на задачу, по которой эта ветка делалась
После внедрения поставки на прод, девелоп (в который уже смержен релиз) мержится в мастер и удаляются все релиз и фичи ветки по данной поставке.
Не утверждаю, что это единственно правильный вариант, но нам это позволяет поддерживать хоть какой-то порядок в очень большом гите (несколько десятков проектов, в каждом от нескольких десятков до нескольких сотен репозиториев).
Tekato Автор
Вы абсолютно правы. У нас тоже используются ветки
feature
иrelease
, и мы указываем в названии ветки id задачи, чтобы иметь привязку и через MR всегда можно было перейти в задачу и посмотреть на ревью, что все сделано согласно ТЗ.В статье это не указал, так как посчитал слишком сложным описывать все ветвление абстрактному неподготовленному человеку. Но спасибо за ваш комментарий — он будет многим полезен)
SpiderEkb
Лучше указывать сразу. Потому что как вы описали, выглядит… Ну не знаю. Несерьезно как-то :-) Для личного репозитория ничего, а когда много народа можетв нем работать, уже нужен какой-то порядок и взаимные договоренности по поводу общих правил игры.
sumanai
Можно просто написать git flow и дать ссылку на какую-нибудь статью на Хабре ))
ahdenchik
git хорош свободой.
Если ветки удаляются после мерджа то нет смысла в танцах вокруг красоты их наименования.
SpiderEkb
Вообще есть. Время жизни ветки конечно, но достаточно длительно. У нас ветка может жить и несколько недель и месяц. И в одном репозитории может работать несколько человек по разным версиям поставки. И когда заходишь в репозиторий очень удобно оценить что там сейчас происходит.
Да вот даже простейший пример. получаешь задание на доработку. Мнемоника поставки понятна. Но непонятна версия поставки — видишь, что на бою последняя, скажем, 320. Но это не факт что ты можешь взять 330 (версии с новой логикой увеличиваются на 10, на 1 — это исправления дефектов без новой логики). Потому что 330 может быть уже занята, но еще не внедрена (на тестах). Смотрим в артифактори (когда поставка уходит на тест, она складывается в артифактори) — ага, там есть уже и 330. Но опять не факт — возможно, кто-то уже взял в разработку 340. Смотрим в гите — ага, ветка #340 уже есть. Значит берем себе #350.
Ну и имя задачи в жире позволяет хоть с ветки хоть с коммита перейти на нее прямо из гита. Просто посмотреть — а что там дорабатывалось-то?
В целом это схема, которую мы выстроили в течении долго времени и в наших условиях (большое количество коман д, огромный зоопарк репозиториев, много разработчиков — только на бэке больше сотни, а есть еще фронты, пега...) она успешно работает. Просто заходишь в репозиторий и можно сразу оценить что там происходит — что в тесте, что на проме, что в разработке…