Перевод статьи Леонардо Лима «How to keep your JavaScript code simple and increase its readability».
После нескольких лет работы почти исключительно с Ruby on Rails и немножко с jQuery я сменил фокус на фронтенд-разработку. Я открыл для себя красоту синтаксиса JavaScript ES6 и потрясающие современные библиотеки, такие как React и Vue. Я начал внедрять новые свойства не пользуясь ничем кроме ES6 Vanilla JavaScript и просто влюбился во все эти новые абстрактные классы и стрелочные функции.
Сегодня и пишу JavaScript-код в больших объемах. Но, поскольку я еще считаю себя падаваном в JavaScript, мне есть, куда расти. В ходе обучения и наблюдений я понял, что даже с использованием синтаксического сахара, представленного в ES6, если вы не следуете главным принципам SOLID, у вашего кода есть все шансы стать слишком сложным для чтения и поддержки.
Чтобы показать, что я имею в виду, я проведу вас через одну фантастическую сессию ревью кода, которая была у нас с приятелем на прошлой неделе. Мы начнем с класса JavaScript на 35 строк и закончим прекрасным кусочком кода в 11 строчек, использующим только простые функции. Проявив терпение и настойчивость вы сможете применять этот шаблон в своей собственной базе кода.


Свойство, которое нужно реализовать
Мне нужно было сделать нечто простое и тривиальное: получать некоторую информацию со страницы и посылать запрос к стороннему отслеживающему сервису. Мы создавали трекер событий на стороне клиента и наряду с этим отслеживали некоторую активность на странице.
Примеры кода ниже реализуют одну и ту же задачу с использованием различных тактик создания кода.
День 1 — Использование синтаксиса классов ES6 (также известный как Object Prototype Pattern wrapper).
Вы можете заметить в вышеуказанном коде, что начал я умно: изолировал generic tracker SuccessPlanTracker чтобы использовать его повторно на другой странице помимо Empty Index.
Но погодите. Если это трекер empty index, что, черт побери, здесь делает TrackNewPlanAdd?
День 2 — Избавляемся от бойлерплейт-кода в классе
ОК, теперь имя файла ясно отражает назначение фичи и – только посмотрите! – там больше нет класса EmptyIndexTracker, что дает нам меньше бойлерплейт-кода. Узнать больше можно здесь и здесь. Мы используем простые переменные функций, а также прекрасным выбором является использование блистательных многоточий (операторов расширения) ES6 Object Spread.
Я обнаружил, что метод querySelectorAll уже возвращает массив, так что мы можем удалить функцию Array.from() из Array.from(document.getElementsByClassName(‘js-empty-index-tracking’)) `. Помните, что метод getElementsByClassName возвращает объект.
Также, поскольку главным назначением является связывание HTML-элементов, вызов функции document.addEventListener(‘DOMContentLoaded’) больше не относится к файлу.
Прекрасно!
День 3 — Удаление старых приемов ES5 и дальнейшее разделение ответственности.
Если вы внимательно посмотрите, то заметите, что в вышеуказанном коде нет класса SuccessPlanTracker — его постигла та же судьба, что и старый EmptyIndexTracker. Установка на “классоубийство”, однажды принятая, ширится и размножается. Но не бойтесь, мои добрые друзья.
Помните, что в своих JavaScript-файлах всегда следует держаться простоты. Теперь нет необходимости знать о состояниях экземпляров класса, а классы раскрывали практически только один метод.
Вам не кажется, что использование абстракций классов ES6 было немного излишним?
Заметили ли вы также, что я удалил экземпляры переменных вверху файла? Эта практика восходит к ES5, а сейчас, когда у нас есть синтаксис ES6+, нам уже не нужно так волноваться об этом.
Наконец, последнее важное изменение в этой третьей версии. Наш empty index tracker binder теперь делает только одно дело: связывает элементы.
Прохождение этих шагов очень приблизило код к принципу единственной ответственности — одному из самых важных принципов в SOLID.
День 4 — избегаем небрежной манипуляции с DOM
Эй, ты наглый лжец: теперь здесь больше строк!
Дело в том, что наша третья версия была немного сломанной. Мы неправильно изменили набор данных DOM-элементов в строке properties.emptyIndexAction = button.dataset.trackingIdentifier;.
Свойство одной кнопки было передано другой кнопке, что приводило к смешиванию отслеживаемых событий. Для исправления этой ситуации мы убрали ответственность за назначение свойства emptyIndexAction из binding loop в подходящую функцию путем создания метода trackAction() в ее области действия.
Добавив эти дополнительные строки мы усовершенствовали наш код, улучшив отделение каждого действия.
Наконец, завершаем и записываем
- Если хотите проектировать и писать прекрасный код, вы должны быть готовы к дальнейшим исследованиям и выходу за рамки правильного и современного синтаксиса.
- Даже если первая версия вашего кода проста и читабельна, это не обязательно означает, что система хорошо спроектирована или что соблюден хотя бы один из принципов SOLID.
- Обязательно принимайте конструктивную критику кода и позволяйте другим разработчикам подсказывать вам, что можно улучшить.
- Чтобы сделать код проще, думать придется больше.
Если у вас есть другие подходящие примеры рефакторинга или уроков по обзорам кода, поделитесь ими в комментариях.
[customscript]techrocks_custom_after_post_html[/customscript]
[customscript]techrocks_custom_script[/customscript]