Реализуем задачи на Go (и не только): самая подробная шпаргалка
Даниил Динько, тимлид в компании-лидере в международном кибербезе и эксперт Эйч Навыки, рассказывает, как разработчикам эффективно планировать, анализировать и оптимизировать свои проекты.
3К открытий28К показов
В прошлом году Go попал в десятку самых популярных языков программирования, а в этом — уверенно занимает 7 место. Им пользуются более трех миллионов разработчиков по всему миру, и это количество будет только расти. И если в 2018 году найти работу Go-девелоперу было не так уж и просто, то сейчас количество вакансий сильно растет. Несмотря на то что у Go простой синтаксис и высокая надежность, даже опытные разработчики могут столкнуться с проблемами, когда оценивают реализацию задач.
Я — Даниил Динько, веду свой личный телеграм-канал, где рассказываю о себе, об IT и о Golang, а также являюсь экспертом и спикером в компании Эйч Навыки, TeamLeadом в компании-лидере в международном кибербезе, ex. старшим разработчиком в Ozon Tech. Разбираемся, как четко оценивать задачи, как использовать инструменты для повышения точности планирования и на что обращать внимание в коде и архитектуре, чтобы не допустить скрытых ошибок.
Как подходить к оценке задач на Go (и не только)
1. Понимание бизнес-цели
Первая задача — разобраться в бизнес-ценности задачи. Это критически важно. Если я понимаю, как задача влияет на бизнес и какие цели она преследует, то дальше процесс становится логичнее.
2. Оценка масштаба и сложности
Я анализирую, насколько сложна задача и насколько она совпадает с моей зоной ответственности:
- Если задача близка моему профилю, я быстро схватываю суть.
- Если в команде есть специалист, который лучше разбирается в этой теме (например, коллега Вася), есть два пути: первый — передать ему задачу с вводными, второй — консультироваться, если Вася занят.
У нас в команде, как и в Озоне, часто бывает, что такой «Вася» один на 10 человек. И если он ещё и не слишком общительный, то тут не остаётся ничего, кроме как искать альтернативы: спрашивать на созвонах, разбираться в коде, погружаться в дебаг и изучать продукт самостоятельно. Это дольше, но работает, а Вася потом на ревью укажет на потенциальные минусы.
3. Классификация задачи
После бизнес-анализа и погружения в зону ответственности важно понять, насколько масштабна задача:
- Мелкие задачи: фиксы багов или незначительные фичи, которые редко трогают пользователи, не требуют глубокого обсуждения.
- Крупные задачи: если задача касается хайлоад-флоу или имеет высокий бизнес-вэлью, стоит провести груминг с командой, чтобы избежать багов и дебагов на проде.
Производительность и масштабируемость — еще одни важные аспекты, но с ними на старте всё не так просто.
На практике даже в бигтехе редко можно на старте увидеть крутые производительные и масштабируемые решения. Поэтому обычно делается так: разработка идет к бизнесу, чтобы узнать нефункциональные требования.
4. Нефункциональные требования
- RPS (Requests Per Second) — сколько запросов в секунду выдерживает система?
- Latency — какая допустимая задержка?
- Uptime — уровень доступности в процентах (например, 99.9%).
Часто бизнес не понимает технические термины, поэтому уточняю показатели через DAU (ежедневные активные пользователи), MAU (ежемесячные активные пользователи) и специфику продукта.
На основе этих данных принимается решение:
- Сделать MVP и быстро запустить, чтобы протестировать гипотезу.
- Проработать масштабируемое решение, если проект требует высокой стабильности.
В 98% случаев мы выбираем MVP. Это нормально. Глубокое продумывание архитектуры — редкость на старте, если только проект не требует стабильности с первых дней.
О масштабируемости, отказоустойчивости и производительности, конечно, идут размышления, но в основном в свободное от работы время. Я не считаю это неправильным, потому что в первую очередь мы трудимся во благо бизнеса.
Какие библиотеки и инструменты использовать
Для задач с хайлоадом выбор технологий и подходов критически важен. На рынке много готовых решений, но в реальных проектах, особенно в таких компаниях, как Ozon, часто создаются кастомные библиотеки и прослойки для решения конкретных задач. Причина проста: стандартные инструменты не всегда выдерживают требуемые нагрузки.
Популярные инструменты для хайлоад-систем:
Базы данных:
- PostgreSQL — классика для реляционных данных
- Redis/Memcached — быстрые key-value хранилищ
- ClickHouse — аналитическая база для больших объёмов данных
- ScyllaDB, CockroachDB — новые решения, которые набирают популярность благодаря своей производительности и масштабируемости.
Микросервисные архитектуры:
Используется Transactional Outbox — паттерн, позволяющий сохранять атомарность между базой данных и очередью сообщений.
Выбор инструмента всегда зависит от специфики задачи. Если речь идёт о BigData или финтехе, то ключевые критерии выглядят так:
- Отказоустойчивость: чтобы система не падала.
- Атомарность: операции либо выполняются полностью, либо откатываются.
- Консистентность: все узлы системы видят одно и то же состояние данных, без рассинхрона.
Чтобы сделать атомарность и консистентность, используют две таблицы в PostgreSQL: основная таблица с данными и outbox для задач, которые нужно передать в следующий этап.
Как это работает:
- В таблице outbox собираются записи для отправки в топик.
- Воркер обрабатывает данные из таблицы и передаёт их в топик.
- Это гарантирует, что состояние базы и очереди сообщений синхронизированы.
Монолит против микросервисов:
Конечно, в распределённых системах могут возникать специфические проблемы, но это уже частные случаи, требующие индивидуального подхода.
- Если система монолитная: достаточно транзакций в реляционных базах данных, что упрощает работу.
- Если BigData: переход на микросервисы становится необходимым, но вызывает сложности с консистентностью и отказоустойчивостью.
Распределённые системы требуют дополнительного внимания к проблемам, которые могут возникнуть из-за сетевых задержек, расхождений данных и отказов узлов.
О производительности и оптимизации
Первое, на что нужно обращать внимание при оптимизации — узкие места. Здесь важно понять, действительно ли проблема связана с вашей частью системы или можно спокойно отложить клавиатуру и пойти пить кофе.
Если у вас микросервисная архитектура, начните с анализа трейсов:
- Смотрите, сколько времени занимает обработка запроса конкретным микросервисом.
- Определите, какой из них обрабатывает запрос дольше всего, и начинайте копать в этом направлении.
У вас нет трейсов в большой микросервисной архитектуре? Тут могу выразить только одно — мои искренние соболезнования, поскольку в вашем случае предстоит знатно пострадать, чтобы определить, в чём проблема.
Когда нашли корень проблемы (конкретный микросервис), воспроизведите флоу и пройдитесь дебагером по коду, чтобы разобраться, что происходит. После этого переходим к следующему этапу — профилированию кода.
Материалов по профилированию на Go — миллион. Если вкратце:
- Используйте встроенные инструменты профилирования Go (pprof, trace).
- Обратите внимание на сборщик мусора (GC) — он может отнимать слишком много времени.
- Проверьте наличие утечек горутин.
Что касается трендовых инструментов, Redis Streams обретает все большую популярность. Redis Streams — это основа для построения своего быстрого in-memory брокера сообщений с кастомными алгоритмами ретраев, крутой интеграцией с key/value Redis, а это возможность сделать пуш в стрим и изменение значения по ключу атомарными. Если говорить более глобально, сейчас постоянно растет количество решений в DevOps, облаках, MlOps. Да и Go постепенно набирает обороты — каждая новая версия языка обычно приносит улучшения в производительности компилятора и стандартной библиотеки.
Какие есть риски при оценки задач
На мой взгляд, риски — глобальная история, которая не завязана на одном языке, поэтому самый распространенный риск, который уже стал классикой, — это не уложиться в дедлайны.
Часто оценки разработчиков позитивные, причём чем меньше грейд, тем позитивнее сроки. К примеру, из сеньоров в моей команде приходится выдавливать сроки, просто так они не скажут. Если удалось получить сроки, то они будут на всякий случай умножены в 2.5-3 раза — и это отчасти правильно.
Почему так происходит? Ответ — подводные камни. Предугадать их заранее сложно, даже теоретически. Это объясняет, почему сеньоры завышают сроки, а мидлы, напротив, обещают сделать всё «завтра», а потом либо перерабатывают, либо просят перенести сроки.
Как минимизировать риски
1. Будьте реалистом, а не оптимистом: излишний оптимизм часто приводит к несоблюдению сроков или сбоям на проде. Пессимизм помогает предусмотреть возможные проблемы и снижает вероятность критических ошибок.
2. Тестируйте новые технологии: не доверяйте только хорошим отзывам — ваш кейс может оказаться нестандартным. Всегда проводите локальные тесты перед внедрением.
3. Проводите нагрузочные тесты: без них невозможно предсказать, как система поведёт себя под реальной нагрузкой. Это особенно важно для фич, которые затрагивают основные пользовательские потоки.
4. Будьте готовы к изменениям: изменения бизнес-требований — частое явление. Знания команды о продукте могут не совпадать с реальной спецификой.
Если фича новая и затрагивает ключевые процессы, проведите груминг с командой, чтобы собрать мнения и минимизировать ошибки.
5. Грамотно ставьте задачи в таск-трекере: для опытных разработчиков: достаточно описать, чего хочет бизнес. Для новичков или незнакомых областей: добавьте пошаговую инструкцию.
6. Что важно описать для багов:
- Проблему и путь её воспроизведения.
- Текущее поведение системы.
- Ожидаемое поведение.
- Идеи для решения (если они есть).
Как выстраивать командную работу
Из интересных моментов, которые я взял из разных команд и интегрировал в свою — груминги, кураторство через звонки. Груминги — это про сохранение вовлечённости в продукт каждого члена команды. Если разработчики будут решать задачи сами по себе, без обсуждений, команда легко окажется рассинхронизированной. В итоге каждый станет экспертом только в своей зоне ответственности, а в других частях проекта разбираться не будет, но это не всегда хорошо.
А что если один из разработчиков уйдёт, сколько нам времени понадобится, чтобы обрести экспертизу в его зоне ответственности? Кажется, это сильно замедляет процесс.
Чтобы избежать такого, важно:
- Давать каждому возможность работать в своей зоне ответственности. Это прокачивает навыки и уверенность.
- Периодически поручать задачи вне их основной зоны, чтобы снизить бас-фактор (критическая зависимость от конкретного человека).
Это помогает и в случае перегрузки: если один разработчик зашивается с задачами, а другие — отдыхают, можно обратиться к тем, кто уже выполнял задачи в этой части системы.
Об изменениях в управлении Go-проектами
Да, изменений много. Go растёт и хайпует невероятными темпами. Go идеально подходит для бэкенда. Он прост, эффективен для многоядерных процессоров благодаря встроенному планировщику, поддерживает высоконагруженные сценарии и хорошо сочетается с микросервисной архитектурой.
Что изменилось в последние пару лет:
- Проектов на Go становится всё больше. Это касается и хайлоад-компаний, и стартапов.
- Растёт популярность языка среди разработчиков. Конкуренция за рабочие места увеличивается, зарплаты немного снижаются, хотя они всё ещё остаются одними из самых высоких на рынке бэкенда.
- Сложность найма. Найти хорошего мидла стало чуть проще, но с сеньорами всё по-прежнему сложно.
Если ты сеньор, то, несмотря на то, что у тебя вакансия абсолютно везде скрыта, тебе всё равно будут стабильно писать раз в неделю, находя твои контакты через слитые базы.
Советы тимлидам, которые начинают с Go
- Примите, что найм будет сложным. Если вы не в бигтехе, без хорошего нетворка тяжело быстро нанять нужных специалистов.
- Балансируйте задачи и созвоны. У разработчиков должно оставаться достаточно времени на фокусную работу. В среднем, это 4 часа в день. Старайтесь не перегружать команду митингами.
- Снижайте бас-фактор. Следите, чтобы каждый разработчик периодически выполнял задачи вне своей основной зоны ответственности.
- Не будьте диктатором. Обсуждайте задачи на грумингах, вовлекайте команду в процесс принятия решений. Это повышает их вовлечённость и улучшает качество решений.
- Давайте ответственность, а не только задачи. Если пытаться тащить всё на себе, можно выгореть.
- Заставляйте тестировать код локально. Даже если это сложно, практика локального тестирования сильно снижает вероятность багов.
- Используйте бюджеты на обучение. Развивайте хардовые навыки команды, чтобы повысить их эффективность.
Для новичков в Go
Если возникают трудности, самое очевидное решение — спрашивать у коллег. Но что делать, если боишься надоесть вопросами?
- Найди ментора. Это платный, но удобный вариант для вопросов, не связанных с продуктом.
- Если вопрос связан с продуктом, обращайся к разработчику, который в нем разбирается.
- Если он отвечает «ну посмотри в код», используй дебаггер и локальные тесты, чтобы собрать информацию.
Дебаггер — это must-have. Если его нет, тестируй на тестовом или staging-окружении. Если нет и их — проблема не в тебе, а в процессе CI/CD.
Стоит пойти и мягко намекнуть или спросить, а вот как тестировать? Потому что в таком кейсе только на проде тестить, но это совсем ненормально.
Что еще поможет?
- Читай статьи и смотри доклады вечером. Это ускоряет рост.
- Изучай дебаггер и локальные тесты — это твои главные инструменты.
- Участвуй в технических конференциях, чтобы лучше понимать хайлоад и новые подходы.
Несколько полезных ресурсов
YouTube-каналы:
Курсы и ресурсы — жестко актуальная тема, главное не слететь с дороги. А еще в своем телеграм-канале я недавно сделал ультимативные бесплатные минимальные роадмапы по Go для разных грейдов — для начинающих, для джунов, для свитчеров с других языков, для мидлов и многих других.
Go — это невероятно мощный инструмент, который подходит как для стартапов, так и для хайлоад-проектов. Но успех зависит не только от технологий, а от команды и выстроенных процессов. Делайте упор на вовлеченность, снижайте бас-фактор, прокачивайте людей и внедряйте культуру обмена знаниями.
3К открытий28К показов