Привет, Хабр! Меня зовут Даниил Зиненко, руководитель направления разработки Online Shop в Lamoda.

Online Shop – это одно из IT-подразделений в Lamoda, которое отвечает за сайт и за мобильное приложение. Всего у нас 121 сервис, 67 из которых мы написали на Go за последние 4 года.  При этом мы активно продолжаем создавать и внедрять новые. 


Эта статья — расшифровка моего мини-доклада с Golang Live 2020. Под катом я расскажу о том, как мы упрощаем задачу написания новых сервисов и облегчаем поддержку существующих. Какие инструменты для этого мы нашли или написали, какие процессы нам в этом помогают.

Обмен экспертизой и опытом


Когда в нашу команду выходит новый разработчик, он проходит технический онбординг. Через 2 недели новичок хорошо понимает те принципы, подходы и технологии, которые мы используем в разработке. В результате он готов сразу включиться в разработку настоящих продакшн-сервисов.

Мы очень активно работаем над тем, чтобы знания и экспертиза распределялись по компании.  Для этого у нас есть:

  • Tech Talks – встреча, где команда в течение часа обсуждает проблемы и решения, идеи, новые технологии, которые хочется привнести в проект.  
  • IT Fest– подобный формат в более крупном масштабе. Он дает возможность  рассказать коллегам из других команд о проблемах и как удалось с ними справиться. Так весь IT в компании может узнать о том, какие проблемы мы уже умеем решать и как, что помогает избавляться от «велосипедов». 
  • Архитектурный комитет – еще одна важная активность в компании. Его задача – это валидация будущих изменений архитектуры наших систем. По формату это часовая встреча, на которую обязательно собираются техлиды, тимлиды и представители DevOpsа. А также могут присоединиться все желающие.

На архитектурном комитете инженеры презентуют технические решения проектов, которые сейчас находятся в работе. Например, ребята рассказывают, какие сервисы хотят написать, какие технологии планируют использовать, как выстроят коммуникацию, как поменяют архитектуру в существующих сервисах. В ответ они получают уточняющие и корректирующие вопросы. По итогам встречи техническое решение получает или апрув на разработку, или рекомендации, как его стоит улучшить и принести на комитет еще раз. 

Первая цель этой встречи — найти вопросы, которые помогут разработчику сделать архитектуру проекта лучше. Вторая — рассказать техлидам, тимлидам, DevOps-инженерам о том, какие изменения в архитектуре систем следует ожидать в будущем. Это важно и помогает избегать проблем, когда команды одновременно берутся за решение похожих задач, не зная друг о друге. Архитектурный комитет помогает им встретиться и сделать единое хорошее решение. 

Кроме того, есть приятный сайд-эффект – мы понимаем, какие общие практики есть в компании и влияем на их формирование. Это уменьшает зоопарк решений в системах. 

Замораживаем разработку старых сервисов


Нам важно не только уметь писать новые сервисы, но и еще уметь НЕ писать старые. Мы называем такой процесс холдированием или заморозкой разработки. У нас в Online Shop есть старые сервисы, написанные на РНР или на Python, и иногда поддержка таких старых систем немного болит. 

В какой-то момент мы перестаем развивать тот или иной сервис. Разработка там прекращается и максимум, что туда можно коммитить – это критичные фиксы. Если команде нужен новый функционал, за который отвечает устаревший сервис, ребята пишут похожий сервис на Go. Там же реализуют все функции, которые нужны для их проекта. В дальнейшем задачи со старого сервиса плавно перетекают в новый. И однажды мы просто выключаем “пенсионера”. Так мы идем к тому, чтобы уменьшить количество сервисов, которые неудобно поддерживать.

Технологии и инфраструктура нам в помощь


  • Мы исповедуем подход specification first. Разработка нового сервиса начинается с того, что мы пишем спецификацию на его API. Затем используем специальные утилиты, которые по этой спецификации генерируют обвязку для сервиса, которая решает много задач: мониторинг, логирование, роутинг, трейсинг и много чего другого. По сути, нам не нужно каждый раз решать одни и те же технические задачи при написании нового сервиса. Вместо этого мы генерируем код и начинаем писать бизнес-логику. 
  • Мы активно используем Docker-compose, поскольку хотим обеспечить низкий порог вхождения разработчика в новый для него сервис. У нас есть простой способ понять все зависимости: как минимум, база данных, как максимум – другие сервисы, если без них тестирование функционала сервиса не очень удобно. Все они обернуты в Docker-compose. Благодаря этому, разработчик может быстро проверить работу сервиса до и после изменений. 
  • Мы используем линтеры – особенно в сервисах, которые развиваются и поддерживаются несколькими командами. У нас есть golangci-lint, который помогает уменьшить время code review, улучшить качество кода и его чистоту.
  • Фреймворк функционального тестирования Gonkey, который мы написали сами. Его прелесть в том, что он декларативный. То есть мы не программируем тесты, а описываем их в YAML и запускаем. С помощью Gonkey мы довольно просто ушли  от ручного тестирования в пользу автоматизированного во многих сервисах. 
  • Все наши сервисы работают в Kubernetes. Разработчики пишут и редактируют  helm-чарты. Этот подход позволяет инженерам лучше понимать, в какой конфигурации будет работать их сервис на продакшн. При этом экспертиза по Kubernetes не в полной мере находится на стороне разработки, поэтому подключаем DevOps-инженеров. Они делают code review helm-чартов и настраивают деплой в продакшн. 

Когда новый сотрудник выкладывает свой первый сервис в Kubernetes, то у него не будет никаких доступов к зависимостям или к ресурсам по умолчанию. Новичок даже не сможет подключиться к базе данных. Это сделано для того, чтобы избежать ошибок, когда, например, сервис в продакшне ходит в базу данных, лежащую в тесте. Вместо этого мы специально настраиваем доступы: заводим тикеты с описаниями зависимостей и ресурсов, к которым необходим доступ нашему сервису. Затем инженер по безопасности валидирует,  должен ли сервис иметь доступ к указанным ресурсам. 

Подведём итоги


  • Мы получаем эволюционный набор общих подходов к разработке, которые получаются благодаря активному обмену опытом и знаниями. Мы совместно обсуждаем свои решения. 
  • Мы стараемся не делать руками всё, что возможно: генерируем обвязку для сервисов, автоматизируем проверку кода с помощью линтеров и автоматизируем тестирование. 
  • И мы понимаем, что не вся экспертиза должна быть именно на стороне разработки.  В частности, экспертиза Kubernetes или экспертиза по безопасности должна находиться на стороне DevOps-инженеров и инженеров по безопасности. Мы процессно подключаем соответствующие команды, чтобы валидировать те решения, которые принимает разработка.