skip to main content

Статический анализ — как делать меньше ошибок

js

Кратко 🔗

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

Самый популярный линтер для JavaScript — это ESLint. Он находит участки кода, которые могут потенциально привести к ошибкам, и сообщает об этом.

Как пользоваться 🔗

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

npm install --save-dev eslint

После установки нужно инициализировать конфигурационный файл .eslintrc.json:

npx eslint --init

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

{
// ...
"extends": "eslint:recommended",
// ...
}

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

{
// ...
"scripts": {
"lint": "eslint ./**/*.js"
}
// ...
}

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

Для наглядности положим в папку проекта JavaScript-файл с ошибками, которые ESLint способен отловить.

// script.js

let x = 12

// Сравнения с -0 запрещены стандартной конфигурацией ESLint
// При запуске он выведет ошибку
if (x === -0) {
console.log("Hello!")
}

Как понять 🔗

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

Советы линтера — это не абсолютная истина. Скорее подсветка спорных моментов, на которые стоит обратить внимание.

Типичные проблемы, которые отлавливают линтеры:

Например:

// проблему в такой функции можно отловить статическим анализом
async function parseFiles(files) {
const data = []

// parseFile будет вызываться последовательно
// сначала будет обработан первый файл
// потом второй, третий и так далее
for (const file of files) {
const parsed = await parseFile(file)
data.push(parsed)
}

return data
}

// линтер может предложить переписать функцию так
async function parseFiles(files) {
// parseFile вызовется для всех файлов почти одновременно
const data = await Promise.all(files.map((file) => parseFile(file)))

return data
}

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

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

В работе 🔗

Линтер для CSS 🔗

На самом деле, статически проанализировать можно почти любой язык программирования. Поэтому, при разработке веб-приложений часто не останавливаются на использовании ESLint, а добавляют еще Stylelint — линтер для стилей. Он умеет работать почти с любым языком описания стилей, начиная от чистого CSS и заканчивая разными CSS-in-JS решениями, SCSS или Styles.

Автоматический запуск 🔗

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

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