Как качать софты — гайд от разработчиков Mindbox. Часть 1. Думать о пользе, а не о коде

Mindbox — крупнейшая облачная платформа автоматизации маркетинга в России. У нас 2 миллиона RPM, сотни баз данных и десятки кластеров kafka. Поддерживают и развивают всё это больше сотни разработчиков, и нам постоянно нужны новые кадры на подмогу.

Хороших разработчиков найти сложно. И дело не в хардах: когда нанимаем джуна, мы не ждем опыта с нашим стеком или знания предметной области. Единственное требование — софты, а именно умение самостоятельно обучаться и желание не делать говна. С этим бывают проблемы.

Пример из практики: наняли трех джунов, все показали хорошие хардскилы, но один из них не прошел испытательный. Причина — недостаток софскилов. Разработчик не учился, писал код ради кода и не хотел разбираться в проблемах клиента, поэтому с ним пришлось расстаться.

Чтобы помочь новичкам закрепиться в компании и расти быстрее, мы составили гайд по софтскилам. Гайд состоит из трех частей. Первая посвящена пользе. Сам по себе код никому не нужен, как бы грамотно и чисто он ни написан — людям важнее решение их проблем. Поэтому прежде всего разработчик должен задумываться о пользе, которую создает.

10beb83ab264363e9030f34ee879d306.png

Пара слов об авторах

Митя Кожевников — senior engineering manager, отвечает за достижения трех команд разработки, 70+ человек под руководством. В Mindbox с 2017 года, за год дорос до мидла и постепенно переключился на тимлидство: занялся обучением новичков, руководством стажерами. 

Юра Соколов — senior software engineer. В 2019 закончил стажировку в Mindbox, за год вырос из джуна в мидла, через еще два — дорос до синьора.

Правило 1. Сначала разобраться в задаче — потом делать

Часто джуны — самые заряженные ребята в команде. Они берут много задач и рвутся быстрее писать код.

be471472f4846e695fa8d911259a52ff.jpgЮра Соколов

Помню это состояние, когда хочется доказать, что меня взяли не зря. Я представлял, как поражу всех: утром получил задачу, а в обед уже принес результат. К сожалению, к желаемому результату это рвение не привело.

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

Мне нужно было работать на верхнем уровне — в коде рекомендаций в рассылках. Я ни с кем не посоветовался и залез в ядро — основной код рассылок. Я так хотел сделать задачу как можно быстрее, что забыл обо всех хороших практиках. 

О своей ошибке я узнал только на ревью, когда уже потратил кучу лишнего времени. Этот случай запомнился надолго — после него всегда проговаривал решение, которое хочу воплотить.

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

1. Узнайте, кто заказчик. Спросите в команде — в чате или на дейлике, — кто и как будет принимать задачу. В идеале найти всех, кто заинтересован в результате — это может быть один или несколько человек, а может — целый отдел. 

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

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

Если вопрос нужно задать занятому коллеге, выделите час–два на поиск решения и возвращайтесь его провалидировать. Так вы сэкономите время коллеге: ему проще оценить готовое решение, чем отвечать на вопрос «Как это делать?»

3. Запишите или проговорите результат, который, по вашему мнению, от вас ждут. Например: «В этой задаче мне нужно научиться обнаруживать зависшие отчеты. Я изучу доступные метрики, выведу нужную в графану и настрою по ней алерт. Я правильно понял? Ничего не упустил?» 

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

Даже пройдя эти шаги, садиться кодить еще рано — нужно спроектировать решение.

Правило 2. Проектировать с конца

Когда есть понимание, к какому результату нужно прийти, старайтесь по цепочке определить, какие действия приведут к этому результату. Причем двигаться нужно из конца в начало. Для этого полезно задавать себе вопрос: «Что для этого понадобится?»

Например, надо изменить отображение заказов, но так, чтобы не пропал доступ к админке админки (не случился даунтайм). Значит, нужна двухфазная миграция фронтенда и бэкенда, поскольку мы меняем контракт обоих сервисов. А перед сложной миграцией хорошо бы еще проверить, что новая форма заказа действительно решает задачи пользователя, например, «пощупав» ее вместе с продактом в админке на локальной машине.

После этой работы вы получите «план на салфетке»: производственный цикл в виде понятных шагов. Этот план нужно показать ведущему, заказчику или команде. Нормально, если показывать его — стыдно. Если не стыдно, то, скорее всего, вы делаете это слишком поздно.

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

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

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

be471472f4846e695fa8d911259a52ff.jpgЮра Соколов

В моей команде нужно было отрефакторить монолит: уменьшить объем шаблонного и дублирующего кода. На этом участке — несколько десятков алгоритмов, и было важно сохранить гибкость их настроек.

Задачу взял джун. Видимо, он не понял, какого результата ждет команда, поэтому спроектировал решение по своему усмотрению, не согласовал и приступил к работе. 

Первый же пуллреквест, который он отправил на ревью, затрагивал большую группу алгоритмов и не предусматривал гибкую настройку. Коллеги посоветовали пойти другим путем и рефакторить алгоритмы по одному: так на ревью сможем договориться, как должен выглядеть код, и поменять его везде.

Джун начал по новой и на этот раз пошел через проектирование с конца. На уровне псевдокода он изобразил, как должен выглядеть код после рефакторинга, согласовал с командой и приступил к работе. Код, который он принес на ревью, решал задачу, и результат быстро приняли.

6d4dcb86d04a522c814ac597255a5965.jpgМитя Кожевников

Недавно перед парой наших джунов стояла задача переделать большой нагруженный кусок кода, поскольку:

  1. Код не работал у нескольких клиентов. Нужно было воспроизвести способы оптимизации из другого похожего кода, в котором применили более производительный подход. 

  2. Код был путаным и сложным в поддержке. При рефакторинге нужно было упростить его.

Изначальный план ребят выглядел так:

  1. Переписываем код.

  2. Переписываем тесты.

  3. Проверяем на клиенте, как работает решение.

План простой, но в нем два больших изъяна:

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

  2. Нет гарантий, что после переписывания код станет читабельнее или хотя бы сохранит работоспособность.

Я предложил перевернуть план работы и сделать все в обратном порядке.

  1. Проверяем гипотезы по оптимизации на выбранном клиенте (для этого у нас есть механизм feature-toggle). Если они подтверждаются, проблемы решены — остается разобраться только с читабельностью кода. Если не срабатывают, мы узнаем об этом в самом начале и не инвестируем в читабельность нерабочего кода.

  2. Фиксируем ожидаемое поведение в новых тестах. Этого не сделать без бизнес-аналитика.

  3. Переписываем код, постепенно «озеленяя» новые тесты, которые теперь еще и помогают сохранять читабельность кода (подробнее об этом можно прочитать в Test-Driven Development Кента Бека)

Правило 3. Вскрыть риски на старте

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

be471472f4846e695fa8d911259a52ff.jpgЮра Соколов

У моей команды была задача — уменьшить размер данных в хранилище аналитики и отчетности продукта. Хранилище состоит из множества таблиц, часть из которых содержали избыточную информацию.

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

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

6d4dcb86d04a522c814ac597255a5965.jpgМитя Кожевников

Эта история произошла, когда я только начинал работать в Mindbox. 

У нас есть конструктор операций — клиент собирает API, которое при вызове выполняет заданную работу, например, меняет информацию в профиле клиента. В этом конструкторе нужно было добавить галочку «Выбрать все поля».

Мне нужно было добавить пункт «Личные данные клиента» со всеми прилегающими полями. Галочка «Выбрать все поля» стоила мне нескольких бессонных ночей

Мне нужно было добавить пункт «Личные данные клиента» со всеми прилегающими полями. Галочка «Выбрать все поля» стоила мне нескольких бессонных ночей

Я предположил, что нет ничего сложного в том, чтобы добавить в верстку простенький стандартный компонент. Поэтому отложил фронт на потом, сначала реализовал весь функционал на бэке.

Как раз на фронте обнаружились проблемы. Оказалось, что существующая архитектура не позволяет добавить поведение, при котором состояние галочки влияет на другие компоненты. Я потратил больше недели, пытаясь красиво и правильно реализовать задуманное, но в итоге всё равно пришел за помощью к более опытному во фронтенде коллеге.

А если бы я сразу реализовал основной пользовательский сценарий вместе с фронтом, то в первый же день столкнулся бы с этой проблемой. А во второй — уже получил бы совет, в какую сторону думать.

Чтобы раньше вскрыть риски, нужно как можно быстрее получить фидбек от команды или увидеть, как решение работает в проде. В Mindbox есть негласные правила, которые в этом помогают:

  1. Пуллреквесты по 300 строк. Такой объем проще ревьюить, а, если в решении ошибка, исправить ее легче. 

  2. Фиксировать задачу в описании. Ревьюеру должно быть очевидно, для чего этот код.

  3. Каждый пуллреквест — законченное самостоятельное решение. В нем нет кода «про запас» или «на будущее».

  4. Оформление кода и рефакторинг — в отдельные пуллреквесты.

  5. Если есть сомнения — показать незаконченный пуллреквест. При этом важно предупредить ревьюера, что это черновик и смотреть нужно на логику решения, а не чистоту кода.

  6. Замечания по пуллреквесту вносить как можно раньше — желательно в первые полчаса. Так выше шанс получить повторное ревью сразу.

  7. Спорные и непонятные моменты выяснять голосом или в мессенджере, в котором общается команда. Обычно переписка в GitHub идет медленно, поэтому проще вынести обсуждение в удобное пространство, а в GitHub зафиксировать принятые решения, чтобы можно было проследить историю.

Еще один вариант быстрее получать фидбек — работа в паре. Так вы можете получать замечания и исправлять их по ходу решения задачи — не дожидаясь ее завершения и ревью от коллег.

Чек-лист, чтобы приступить к задаче

Чтобы качественно выполнить задачу, перед началом работы ответьте на вопросы:

  • Кто и как будет принимать задачу? Кто заинтересован в результате?

  • Какую проблему я должен решить?

  • Какие вопросы по задаче остаются? Что я могу сделать самостоятельно, чтобы найти ответ? К кому обратиться за советом?

  • Как должен выглядеть результат? Согласовали ли его заказчики задачи?

  • Какая цепочка действий приведет к результату? Что сказали о ней ведущий, заказчик или команда?

  • Какие задачи в плане вызывают сомнения? Как минимизировать риск ошибки?

  • Как быстрее получить фидбек от заказчика или команды?

Бонус: что почитать, чтобы прокачать софтскилы

В качестве дополнения к статье советуем:

  • «The Clean Coder: A Code of Conduct for Professional Programmers» Р. Мартина. Здесь вы найдете практические советы развития софт-скилов: как разработчику общаться с коллегами, подходить к оценке проекта, написанию кода, рефакторингу и тестированию.

  • «The Pragmatic Programmer, 20th Anniversary Edition» Д. Томаса и А. Ханта. Здесь множество советов с примерами про то, как писать код, общаться с командой и подходить к решению задач.

Это статья в трех частях. Вы прочитали первую. Две другие появятся позднее — следите за публикациями Mindbox на Хабре.

© Habrahabr.ru