Линтеры: необходимость или излишество?

0
1236
views

Перевод статьи «If you like it, you should have put some lint on it…».

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

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

Я считаю, что если вы тратите несколько часов в день на проведение ревью кода и при этом:

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

— значит, вам очень нравится отлынивать от работы.

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

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

Так что, когда кто-то говорит, что линтеры делают разработчиков ленивыми, он, по сути, не ошибается, но он и не прав.

Поручите это линтеру

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

Прекрасный пример — оставление нескольких пустых строк между методами или вызовами функций. Лично мне было плевать на множественные пустые строки, но у меня был коллега, который постоянно указывал на каждую лишнюю пустую строку в кодовой базе. Он всегда ставил пометку needs work («Нужно доработать») на моих пул-реквестах, и часто именно по причине пустых строк. Исправить было не сложно, однако после этого мне приходилось ждать, пока два других человека проверят мой код, прежде чем я смогу влить его в базу. На помощь мне пришел Tslint с установленным правилом no-consecutive-empty-lines (запрет на последовательно идущие пустые строки) — и внезапно мы стали выпускать функционал быстрее. В процессе никто не пострадал.

Идем дальше. Установки линтера не должны быть чем-то, блокирующим вашу работу. Например, было бы сумасшествием блокировать компиляцию typescript из-за того, что написанный вами код неправильно отформатирован (и не может быть исправлен автоматически). Линтинг не должен быть частью горячей замены модулей, но есть три стадии, на которых вы можете его использовать:

  1. Ваша IDE
  2. Хуки pre-commit
  3. Конвейер CI/CD

Я всегда советую ставить линт-проверку в начале конвейера CI/CD, таким образом никакие изменения, не соответствующие принятым правилам стиля, не пройдут дальше. Запуск линтера вручную перед отправкой кода это тоже действие, о котором придется помнить, поэтому я предпочитаю использовать хуки pre-commit. Их можно легко настроить. Я чаще всего работаю с JavaScript/TypeScript и в последнее время использую для своих проектов NX Workspace, который поставляется с уже готовой настройкой.

npm install husky lint-staged --save-dev

Обычно я начинаю с установки Husky и Lint-Staged, затем вношу изменения в свой файл package.json:

"husky": { "hooks": { "pre-commit":
"lint-staged" } }

Раньше у меня команды lint-staged запускали инструмент форматирования кода и линтер NX для всего проекта перед коммитом, но это отнимало много времени. К счастью, мой друг помог мне с файлом lint-staged.config.js:

const path = require("path")

module.exports = {
  "*.{html,js,ts,json,md,css,scss}": files => {
    if (
      files.length > 0 &&
      files[0] !== "[filename]" &&
      files[0] !== "[file]"
    ) {
      const cwd = process.cwd()
      const relativePaths = files.map(f => path.relative(cwd, f))
      return [
        `nx format:write --files="${relativePaths.join(",")}"`, //
        `nx affected:lint --files="${relativePaths.join(
          ","
        )}" --fix --parallel`, //
        `git add ${relativePaths.join(" ")}`,
      ]
    } else {
      return []
    }
  },
}

Таким образом анализируются и форматируются только подготовленные и измененные файлы. Как видите, NX в своем скрипте format использует prettier.

Вот конфиг prettier, который я использую:

{
  "arrowParens": "always",
  "singleQuote": true,
  "trailingComma": "es5",
  "endOfLine": "lf",
  "printWidth": 140
}

Правило end of line помогает предотвратить проблемы с проверкой кода, а именно — в случаях, когда кто-то присоединяется к команде и работает на машине с Windows, где у него установлено autoclrf = true. Это очень затрудняет поиск настоящих изменений.

Также важен файл .editorconfig. Большинство IDE принимают его по умолчанию, в некоторых нужен плагин, но это достойная причина для его установки.

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

Самое замечательное в эстетическом линтинге то, что он экономит много времени и помогает разработчикам сосредоточиться на читаемости кода и архитектуре, а не на спорах о 2 (4) пробелах и табах.

Чем полезны более строгие правила форматирования?

Обычно при помощи линтеров можно автоматически исправлять отклонения от согласованного стиля написания кода. Это означает, что новичок в команде может писать все что хочет и как хочет, не отвлекаясь на запоминание новых правил. Затем pre-commit hook отформатирует его код и все будут счастливы. То есть, разработчик может, наконец, сосредоточиться на том, что писать, а не как это писать.

Конечно, есть и более строгие правила для линтеров. Мне нравится SonarQube, но это не всегда доступно по финансовым причинам.

Тем не менее, у нас есть наборы правил для линтера sonar-js и sonar-ts, установленные в качестве пакетов, и это очень помогает.

Одним из моих любимых правил линтинга является cognitive-complexity (когнитивная сложность). Оно существенно облегчает мне жизнь, потому что благодаря ему в кодовой базе перестали появляться слишком сложные методы. Хорошо читаемый код легче поддерживать, а когда функции разделены на маленькие понятные кусочки, это приносит пользу всем в команде. Когнитивная сложность это очень важный показатель. Если вы используете VSCode, очень полезный плагин можно найти здесь.

Все эти соглашения и конфигурации должны располагаться в непосредственной близости от самого кода. Вот почему у вас есть .eslintrc, tsconfig.json и .stylelintrc в корневой папке вашего проекта. Благодаря этому в случае присоединения к команде новых людей им не придется настраивать все в своем рабочем окружении так, как это предписано в вики, посвященной правилам стиля. По этой же причине я не люблю помещать эти правила в .vscode или .idea, или какие-либо папки. Я считаю, что заставлять разработчиков менять настройки их IDE это серьезное вторжение в их личное пространство.

Можно ли контролировать IDE разработчика?

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

При использовании VSCode мне нравится пользоваться peacock: это дает мне возможность выделять разные окна цветом.

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

Конечно, вы в своей команде можете сами решить, какой набор правил применять. Но я рекомендую установить правила для скобок, member-ordering и вообще всего, что можно исправлять автоматически. Например, если вы установите правило arrowparens, это облегчит поиск стрелочных функций. Представьте, что вы смутно припоминаете, что использовали стрелочную функцию с какой-то конкретной переменной. Вы можете очень быстро найти ее по имени этой переменной (specificVariable) => {).

Я бы хотел закончить этот пост историей о том, как линтинг помог предотвратить ужасную ошибку в продакшене. Я работал с моим хорошим другом, который в то время был новичком под моим руководством. Он был превосходен! У него была жажда знаний и он сразу принял тот факт, что написание модульных тестов очень важно. Так что тесты он делал, но однажды он столкнулся с проблемой, для решения которой ему нужно было что-то исправить в одном сломанном тестовом модуле. Решая проблему, он «сфокусировал» этот тест (fit в Jasmine) и забыл «расфокусировать» его. Изменения были отправлены, и на них была перенесена другая ветка.

Эта другая ветка провалила множество модульных тестов, но поскольку в CI-конвейере запускался только один «сфокусированный» тест, мы не сразу заметили проблему. К счастью, один разработчик заметил, что конвейер CI/CD ускорился. Мы просмотрели отчеты по тестам и обнаружили только «сфокусированный тест». Тогда это нас спасло, но очевидно, что один маленький fit очень легко пропустить, когда в качестве изменения помечен весь файл.

После этого случая мы интегрировали в нашу процедуру линтинга набор правил tslint-jasmine-rules. Правила no-focused-tests и no-disabled-tests очень нам помогают. Есть также пакеты для jest и mocha, да и другие фреймворки.

Какие у вас любимые правила линтинга? Бывали случаи, когда они вас спасли? Или ситуации, когда могли бы спасти? Делитесь в комментариях!

ОСТАВЬТЕ ОТВЕТ

Please enter your comment!
Please enter your name here