Эта статья изначально была опубликована в блоге разработчиков наших друзей по конференции из MEWS Systems.

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

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

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

Мы хотим, чтобы рецензенты сосредоточились на важных вещах, не теряя при этом концентрации, указывая на что-то, на что они уже указывали 50 раз в прошлом. Итак, как программисты, мы решили решить эту проблему, написав программу, которая будет выполнять проверку кода за нас. 👨‍💻 На бэкэнде, где мы используем .NET, мы используем пользовательские анализаторы кода, и когда мы сталкиваемся с анти-паттерном, который регулярно появляется в пулл-реквестах, мы пишем для него анализатор. Если анализатор встречает шаблон, он вызывает ошибку времени компиляции.

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

Запрет DateTime.Now

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

Запрет OrderBy(string)

Mews используется отелями по всему миру, и даже такая базовая вещь, как порядок букв в алфавите, зависит от культуры. Например. в чешской культуре CH — это буква, которая должна идти после H, где в английском языке CH представляет собой две буквы и должна сортироваться с помощью C. Поэтому, используя, например. OrderBy(c => c.Name) — это анти-шаблон, потому что он явно не учитывает культуру. Он неявно использует культуру текущего потока, но это общая глобальная переменная, которая нам не нравится 😄. Анализатор заставляет разработчика всегда указывать компаратор, зависящий от языка и региональных параметров, при упорядочении по строкам.

Вывод

Мы также являемся поклонниками функционального программирования, что означает, что мы используем много строгой типизации и пытаемся превратить ошибки времени выполнения в ошибки времени компиляции. Так что в целом мы запрещаем многие вещи, небезопасные для типов, которые доступны в библиотеках .NET или даже в языке C#. С другой стороны, мы используем анализаторы для гораздо более простых проверок, например. чтобы обеспечить некоторую согласованность в комментариях или стиле кода (поверх Stylecop).

И последнее, но не менее важное: не все люди привыкли получать много отзывов и критики своего кода. Новички иногда удивляются, насколько мы тщательны, и мы можем почувствовать, что им не очень удобно получать много комментариев от своих сверстников. Это, конечно, со временем у нас улучшается, но мы понимаем, что поначалу это может немного обескураживать. Однако, если обратная связь предоставляется компилятором во время написания кода, она внезапно кажется гораздо более объективной и приемлемой для разработчиков. Не похоже, что кто-то просто придирается к ним, потому что они новые. А также это делает рецензентов счастливыми, потому что им не нужно быть машинами для решения одних и тех же проблем каждый день.

Узнайте больше о том, как мы работаем в Mews, на наших Github и Twitter.