Code Conventions: как мы сохраняем быстрый темп разработки PHP-проекта

в 8:43, , рубрики: code conventions, github, open source, php, roistat, Блог компании Roistat, никто не читает теги, Совершенный код, управление разработкой

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

TL;DR: Мы выложили на github наш Code Conventions и рассказали в статье о том, как его применять на практике.

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

За 4 года существования нашего проекта мы сделали больше 20 000 Pull Request’ов (далее PR) и под катом я расскажу, как же мы решили эти проблемы.

Code Conventions: как мы сохраняем быстрый темп разработки PHP-проекта - 1

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

Если вы технический директор или техлид:

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

Если вы product manager:

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

Начало

В начале 2014 года в Roistat работало всего 2-3 разработчика, но первые проблемы начались уже тогда. Мы столкнулись с тем, что каждому разработчику необходимо объяснять одни и те же ошибки. И с ростом количества разработчиков эта ситуация только усугубилась.

Также с опытными разработчиками возникала другая сложность. У них у каждого был свой накопленный опыт и своё понимание, как надо строить архитектуру проекта. Очень часто их мнения противоречили друг другу.

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

Поиски решения

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

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

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

И это сработало. Проблемы с разным пониманием договоренностей стали сводиться к минимуму. В документе мы писали подробные разъяснения с примерами кода, чтобы никто не смог трактовать их по-разному. Каждый новый разработчик в нашей команде сразу мог понять, что от него требуется и как у нас принято поступать в различных ситуациях. Code Review вместо бесконечных обсуждений и споров превратились в довольно прозрачный и прагматичный процесс.

Спустя полгода работы этот документ содержал уже много полезной информации и стал незаменимым инструментом в работе команды. Мы назвали его Code Conventions (или сокращенно Code Conv).

Code Conventions

Code Conv — это правила, которые нужно соблюдать при написании кода. Мы различаем Code Style и Code Conv. Для нас Code Style — это внешний вид кода. То есть расстановка отступов, запятых, скобок и прочего. А Code Conv — это смысловое содержание кода. Правильные алгоритмы действий, правильные по смыслу названия переменных и методов, правильная композиция кода. Соблюдение Code Style легко проверяется автоматикой. А вот проверить соблюдение Code Conv в большинстве случаев может только человек.

Мы придерживаемся следующего подхода при использовании Code Conv.

Для разработчика:

  • Разработчик изучает этот документ перед тем, как написать первую строчку кода в нашей команде.
  • Разработчик должен понять и осознать написанные правила. Просто выучить этот документ не получится.
  • Разработчик строго соблюдает правила из Code Conv при написании кода.
  • Разработчик создает PR и сразу сам же его просматривает и проверяет на соблюдение Code Conv
  • Разработчик передаёт PR на Code Review и исправляет ошибки и несоответствия Code Conv, на которые ему указывают и которые он упустил сам

Для Code Reviewer’а:

  • Ревьювер проверяет код на соответствие правилам, описанным в Code Conv

  • Если во время Code Review к разработчику появляется какое-то замечание, то оно должно сопровождаться ссылкой на Code Conv.
  • Если в Code Conv нет нужного пункта, то собирается рабочая группа, которая вырабатывает новое правило и фиксирует его в документе. После этого ревьювер возвращается к проверке PR

Немного примеров

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

В начале документа есть оглавление. Со временем информации становится всё больше и без оглавления — никуда.

У нас есть 3 основных раздела: ценности, общие принципы и конкретные правила.

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

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

Но всё же ценности и принципы можно интерпретировать по-разному. Чтобы избежать недопонимания, в документе есть конкретные правила и примеры кода, показывающие как можно делать, а как нельзя.

Code Conventions: как мы сохраняем быстрый темп разработки PHP-проекта - 2

Таких правил очень много и именно они составляют основной объем документа. Благодаря им соблюдается порядок.

На практике применение документа выглядит следующим образом.

Делающий Code Review разработчик оставляет комментарии к участкам кода, в которых он заметил несоблюдение Code Conv. В комментарии он указывает, какое правило нарушено. И опционально, если это не очевидно, добавляет пояснение, почему он так считает.

Code Conventions: как мы сохраняем быстрый темп разработки PHP-проекта - 3

Например, на этом скриншоте мы видим, что нарушен принцип DRY (Don't Repeat Yourself). Несмотря на то что в этом конкретном PR разработчик написал код без повторов и, казалось бы, использовал его только один раз, он все же создал такой метод, который нельзя использовать в дальнейшем без дополнительной проверки. То есть он создал метод, который заведомо требует повтора кода и логики.

Частые возражения разработчиков

Разработчики часто пытаются протолкнуть под различными предлогами свой код, не соответствующий Code Conv. Они находят самые разные оправдания своим нарушениям, но есть несколько самых частых.

«Но один раз-то можно?»

Разработчики думают, что однократное нарушение Code Conv не принесет никакого вреда. Также иногда они считают, что в каком-то не особо важном месте эти правила не несут ценности или не критичны. В ответ на это мы всегда ссылаемся на теорию разбитых окон: «Если в здании разбито одно стекло и никто его не заменяет, то через некоторое время в этом здании не останется ни одного целого окна». Если мы будем делать исключения из правил, то через полгода мы окажемся в ситуации, когда весь код проекта состоит из подобных нарушений.

«Но ведь нужно очень срочно!»

Разработчики часто говорят, что делать нормально будет долго, а клиент ждет решения проблемы и на бой правку надо выложить как можно быстрее. Но, во-первых, Code Conv нигде не запрещает делать первые итерации с упрощенным кодом. Просто этот код всё равно должен отвечать стандартам качества. Во-вторых, если всё же нужно нарушить Code Conv, то допустимо это делать, если созданная энтропия будет не злокачественной (об этом ниже). Но даже в этом случае, у всех должно быть общее понимание, что следование Code Conv в этой ситуации действительно будет стоить намного дороже.

Несколько слов об энтропии. Энтропия — это количество информации, из которой состоит проект (информационная емкость проекта). Если разработчик пишет код, добавляющий критичную информацию, которую обязан знать каждый разработчик, то такая энтропия является злокачественной. Часто такой код является миной замедленного действия. То есть в данный момент это незнание может ни на что не повлиять, а в будущем из-за него могут быть допущены критические ошибки. Такую энтропию мы называем злокачественной. Если же незнание информации никак не повлияет на работу остальных разработчиков, то такая энтропия не несет вреда, и мы называем её доброкачественной.

Например, если мы делаем отдельный микросервис, который будет слушать какие-то события и складывать куда-то статистику, то этот сервис не вносит злокачественной энтропии. Если про этот сервис не будут знать остальные разработчики, то они не допустят никаких ошибок, он не повлияет на их работу. Если он сломается, то кроме владельца этого сервиса никто не пострадает. Так что для такого сервиса допустимо сделать первую итерацию (как Proof of Concept) с низким качеством кода. А затем, если его надо будет развивать, то нужно будет исправить заложенный технический долг и работать с ним уже по всем правилам. В итоге, Code Conv не запрещает экспериментировать и делать быстрые и легкие концепты, если это не влияет на остальную систему.

Заключение

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

Из минусов можно отметить, что с таким подходом Code Review проходит дольше обычного. Даже маленькие задачки могут задержаться на несколько дней или дольше из-за не самых критичных ошибок.

Но этот минус перекрывается плюсами, так как на бой не попадает злокачественный код и все «окна» остаются целыми.

К нам неоднократно обращались с просьбами поделиться примером Code Conv.
Мы решили поделиться со всеми и сделать его публичным. Вы можете взять его как есть и использовать сразу. Или можете изменить под себя. Также мы открыты для PR и рассмотрим ваши предложения по улучшению.

Ссылка на наш Code Conv

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

Автор: flr

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js