Pull to refresh
81.14
SimbirSoft
Лидер в разработке современных ИТ-решений на заказ

Борьба за кодстайл или Bracket Wars

Reading time8 min
Views5.9K
Привет хабровчанам! В этой статье мы попытаемся рассмотреть такой «скользкий» вопрос, как оформление кода и кодстайл, и предложить одно из решений, которое имеет успех в ежедневной практике.

Для JavaScript'а, который долгое время оставался «за бортом» большой разработки, настала золотая эра быстрого развития и появления все новых и новых технологий на его основе, а приложения становятся все комплекснее с каждым днем. Учитывая, что принятие ежегодных стандартов, появление нового синтаксического сахара и «плюшек» делают его очень привлекательным для большего числа разработчиков, данная тема будет актуальна не один год. Новички в JavaScript с энтузиазмом берутся за его изучение, пробуя все новые и новые фишки, однако в большинстве своем они забывают об оформлении кода и о такой вещи, как технический долг.

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

И это не говоря о том, что в интернет заливают петабайты материалов, связанных с JavaScript, зачастую весьма сомнительного качества. В некоторых обучающих материалах, рассчитанных на новичков, творится форменный ад. Не удивительно, что, когда нанимаешь на работу даже разработчиков с опытом работы и программирования на JavaScript, ждать сформированного стиля и уж тем более приверженности к определенному стилю оформления кода не приходится. О понимании “best practices” речи вообще не идет.

Отмечу, что с ростом количества программистов, качество их подготовки, знаний и “ламповость” падает с ужасающей скоростью.

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

Что он дает:
  1. Читабельность. Структурированный код всегда читабельнее неструктурированного, иначе б мы сразу писали код, близкий к минифицированному, и не парились.
  2. Единообразие. Немаловажный аспект, о котором многие почему-то не думают. Мозг человека — штука ленивая, он формирует некий инлайн кэш для чтения исходного кода, и как результат переключение между разными по стилю кусками или файлами требует времени для формирования новых паттернов чтения. Как по вашему, будет здорово, если разработчик при переходе с файла на файл будет «подвисать», формируя новую модель чтения? Вряд ли.
  3. Единый стиль оформления кода дает возможность освободить ресурсы разработчика, которые он тратит на чтение и переопределение стиля оформления для их более продуктивного использования. Например, кроме безусловного ускорения разработки, он может увидеть «узкие» участки в коде, потенциальные потери производительности, дефекты и прочий мусор и соотвественно увидеть возможности для улучшений.
  4. Быстрое вхождение нового разработчика. Этот пункт, как и пункт 3, скорее следствие единообразия и читабельности. Новому разработчику все же придется построить инлайн кэш для чтения, но в силу единообразия этот кэш будет строиться один раз для одного проекта. А в идеале — если все проекты следуют единому стилю — то единожды.


В чем минусы:

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

Я не зря вынес это в название, как «Bracket Wars». Это была чуть ли не основная проблема первого этапа внедрения единого кодстайла. Именно отсутствие единого мнения на некоторые вопросы оформления порождала настоящие холивары. Тему холиваров я освещать не буду, а постараюсь предоставить решение данной проблемы.

Чаще всего можно встретить две противоположных точки зрения: «Работает же» и «В строке 21 7 пробелов в начале вместо 4». Обе точки зрения одинаково спорны. В них нет золотой середины, одна выльется в жуткий говнокод с огромным техническим долгом и кучей разъяренных разработчиков, которым придется разбираться с таким наследством, вторая может надолго застопорить разработку и выкатку новых релизов. Они обе не оправданы и ведут к рискам и недовольству клиентов.

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

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

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

К счастью, на сегодняшний день эти проблемы прекрасно решаются инструментами разработчика — самими IDE или плагинами к ним. Собственно автоматизацию процесса проверки и поддержки кодстайла и рассмотрим далее на примере трех редакторов/IDE, с которыми приходится сталкиваться чаще всего: Sublime Text, Atom, WebStorm.

Еще немного теории: то, что освещается дальше, относится к статическому анализу и линтингу (проверке) кода, соответственно плагины — это линтеры (парсеры) и/или их интеграция в тот или иной редактор или IDE.

Ранее я бы рассмотрел два основных, на мой взгляд, инструмента — это JSHint (статический анализ кода на предмет ошибок) и JSCS (JavaScript CodeStyle — анализ оформления кода на основе соглашений по оформлению или отдельных правил), но на сегодняшний день эти 2 инструмента прекрасно заменяет ESLint(почти всегда, но об этом ниже). Так что его интеграцию я и рассмотрю. Главное отличие ESLint от JSCS и JSHint — модульность и большая кастомизация.

Здесь стоит сделать уточнение по тому, насколько ESLint заменяет эти два инструмента. Парсер JS, который используется в ESLint (Espree — тоже подключаемый по факту), если судить по странице на npmjs, полностью заменяет JSHint, однако более настраиваемый, нежели предшественник, и более медленный, однако для цели ежедневной поддержки кодстайла это имеет крайне низкое значение. Стоит учесть, что скорее всего, замещение по поддержке правил кодстайла еще не полное, сами разработчики данного инструмента говорят о том, что хоть они и объединили усилия с командой JSCS для реализации более универсального инструмента, поддержка еще неполная. Список разночтений можно посмотреть здесь. Поддержка пресетов ограничена. Вернее будет сказать, что реализация этой поддержки теперь изменила вид, если JSCS поддерживал ограниченный набор пресетов из коробки, то теперь эти пресеты стали подключаемыми плагинами, которые нужно установить отдельно и прописать в конфигурационном файле. Я с ходу нашел пресет для Яндекса и пресеты для AirBnB и Google (последние 2 — можно выбрать при инициализации плагина на момент написания статьи).

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

Но перейдем к практической части, а именно настройке EsLint. Стоит отметить наличие двух частей настройки: общей и редактор-специфичной. Начнем с общей.

Глобальная установка Eslint:

npm i -g eslint


Cтоит учесть, что при использовании nvm в linux может сложиться ситуация, когда eslint глобально не виден, в моем случае достаточно было создать символьную ссылку на eslint внутри /usr/local/bin/ командой:

ln -s /usr/local/nvm/vX.X.X/bin/eslint /usr/local/bin/eslint


где vX.X.X версия текущей Node.js, которую вы в последний раз использовали в

nvm use X.X.X


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

eslint --init


Данная команда приводит к диалогу генерации конфигурационного файла. Гайд очень похож на аналогичную генерацию package.json. По факту у вас 2 выбора: ответить на вопросы об используемых технологиях и кодстайле или выбрать пресет- в списке, как уже упоминалось ранее; можно выбрать Google, AirBnB и Standard — рекомендованный пресет от команды ESLint. Есть и третий вариант с проверкой кодстайла ваших файлов, который по сути действует так же, как и опрос, но также делает попытку определить кодстайл.

image

image

image

image

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

Далее идет выбор формата конфигурационного файла — Javascript, JSON, YAML. После выбора одного из форматов генерируется конфиг и доустанавливаются необходимые плагины. EsLint рекомендует использовать локальную установку EsLint и необходимых плагинов, устанавливает их в рабочую директорию и прописывает в раздел devDependencies вашего package.json.

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

{
    "env": {
        "browser": true,
        "es6": true,
        "commonjs": true
    },
    "extends": [
      "eslint:recommended",
      "plugin:react/recommended"
    ],
    "installedESLint": true,
    "parserOptions": {
        "ecmaFeatures": {
            "experimentalObjectRestSpread": true,
            "jsx": true
        },
        "sourceType": "module"
    },
    "plugins": [
        "react"
    ],
    "rules": {
        "indent": [
            "warn",
            "tab"
        ],
        "linebreak-style": [
            "warn",
            "unix"
        ],
        "quotes": [
            "warn",
            "double"
        ],
        "semi": [
            "warn",
            "always"
        ],
        "react/prop-types": "off",
        "no-console": "off",
        "no-unused-vars": "off"
    }
}


Перейдем к настройке вашего редактора.

Atom.

image

С плагинами для атома все ясно — ставим в разделе настроек Install плагин linter-eslint, настраиваем его:

image

Также устанавливаем пакет linter, если он не стоял — это зависимость linter-eslint. Возможно нужно будет обновить Атом, в моем случае при каждом изменении в файле выпадала уйма ошибок и обновление редактора решило проблему. Простота установки плагинов для Атома — одно из его достоинств. Данный плагин также исправляет кодстайл при сохранении, если отметить “Fix errors on save”.

Sublime.

image

Через PackageControl нужно установить по факту три плагина. Это SublimeLinter, SublimeLinter-contrib-eslint и ESLint-formatter. Первый, как и linter в Atom, является основой линтинга кода в Sublime — этот фреймворк имеет обширную документацию, настройка его очень подробно описана. SublimeLinter-contrib-eslint — мостик для подключения eslint к SublimeLinter и имеет свою документации и воркэраунд в случае проблем. В настройках SublimeLinter в секции linters нужно прописать следующий код:

"linters": {
  "eslint": {
    "@disable": false,
    "args": [],
    "excludes": []
  }
}



Oстальное — дело вкуса. Настройте внешний вид линтера под ваши нужды. Описание тем и настройки можно найти на сайте документации.

ESLint-formatter — позволяет автоматически отформатировать файл по вашим настройкам ESLint. Его также нужно настроить — прописать пути до Node.js и ESLint, также рекомендую как минимум поставить «format_on_save»: true. Возможно, стоит учесть проектную специфичность и создать .sublime-project и настройки для конкретного проекта прописать там.

WebStorm.

image

Настройка показана на скриншоте. Достаточно активировать ESLint в Settings > Languages & Frameworks > Javascript > Code Quality Tools > ESLint, прописать путь к локальной установке ESLint, если он не был определен автоматически. Рекомендовано автоматическое определение наличия конфига, но вы также можете указать путь к нему.

Единственный минус — автоматического форматирования по ESLint в WebStorm я не нашел — есть импорт кодстайла из JSCS конфига и Code > Reformat Code, a импорта из ESLint конфига нет. Однако функция линтинга работает:

image

Для WebStorm стоит учесть данный аспект и не отказываться от JSCS. Это именно тот аспект, из-за которого ESLint “почти всегда” заменяет предшественников — его поддержка в некоторых IDE все еще проигрывает JSCS и JSHint.

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

Какой профит от всего этого:
  1. Никаких “Bracket Wars”. Инструментарий заботится о кодстайле, а не вы. Это дает простор для коструктива вместо холиваров;
  2. Не нужно больше знать кодстайл — во всяком случае форсировать его изучение и насаждать. Со временем разработчик запомнит специфические правила, а если что-то и пропустит — “fix on save” всех спасет;
  3. Поддержка кодстайла автоматическая, не требует времени разработчика;
  4. Проект однороден по стилю, а это дает все плюшки, которые были описаны в начале статьи в “плюсах”.


Спасибо за внимание.
Tags:
Hubs:
+1
Comments27

Articles

Information

Website
www.simbirsoft.com
Registered
Founded
Employees
1,001–5,000 employees
Location
Россия