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

То же самое и с компилируемыми языками программирования. Компилятор действует как заботливый взрослый, который не дает нашим приложениям делать глупых ошибок. Компилятор переводит наш высокоуровневый код на некоторый язык программирования низкого уровня (ассемблер, байтовый код и т. Д.), И для этого один должен быть действительным, чтобы быть сопоставленным с другим. Мы полагаем, что компилятор сообщит нам, когда мы попытаемся получить доступ к переменной, которую мы никогда не объявляли, присвоить значение типа MyHelloworldClass1 логической переменной или пропустить точку с запятой 😖. Мы уверены, что наш код никогда не будет выполнен, если мы облажались. Это если мы не используем JavaScript. Или PHP, или Ruby, или любой другой язык, которому не повезло с временем компиляции, но позвольте мне сосредоточиться здесь на JS (пожалуйста).

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

Отказ от ответственности: иногда я собираюсь использовать термин «скомпилированный язык» в его почти ортодоксальном значении, имея в виду языки программирования, имеющие время компиляции, в отличие от языков, имеющих возможность компиляции только точно в срок (JIT).

Вариант 1: инструмент статического анализа кода

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

Если некоторые из вас, мои возлюбленные читатели, не знают, что такое линтеры (я буду использовать этот термин вместо более длинного статического анализа кода) и чем они занимаются, то вот очень краткий обзор. ЛИНТЕР - это своего рода программа, которая принимает ваш код и некоторые инструкции о том, что считается плохим кодированием, в качестве входных данных, и после анализа первого на основе более поздних создает список ваших проблем. Как с вашим кодом, а не в целом (для этого вам нужно что-то получше, чем простое приложение). Обычно, в зависимости от вашей конфигурации, линтер может указывать на синтаксические ошибки (например, необъявленные переменные), запахи кода (например, неиспользуемые переменные), нарушение соглашений о стиле кода (например, длинные строки) или устаревание. Хотя эти инструменты могут использоваться как автономные приложения, они имеют больше смысла при интеграции с вашей IDE, и в этом случае они могут анализировать ваш код и предоставлять вам список проблем в режиме реального времени. Например, я использую линтер под названием ESLint, интегрированный с Visual Studio Code. Когда вы инициализируете ESLint для своего проекта, вы можете выбрать, хотите ли вы сгенерировать новую конфигурацию линтера на основе вашего стиля кода или просто взять одну из популярных конфигураций, используемых такими громкими именами, как AirBnb или Google. Я лично предпочитаю AirBnb с небольшими изменениями, и я бы посоветовал сначала попробовать его, чтобы понять, на что он на самом деле способен. В любом случае, через некоторое время большинство команд разработчиков придумывают свои собственные конфигурации линтеров, которые лучше всего соответствуют их потребностям. Потому что в нашем волшебном и очень разнообразном мире ИТ ни одна команда разработчиков не похожа на другую.

Так да. Инструменты статического анализа кода AKA linters. Используйте их, если вы еще этого не сделали. На самом деле нет никаких оправданий, чтобы не делать этого.

Вариант 2: транспиляторы и языковые надстройки

Это будет непросто, потому что я буду говорить о двух связанных, но не совсем идентичных вещах. Потерпи меня, ладно?

Самый простой способ выжить в JS из-за отсутствия строгой типизации и проверки ошибок во время компиляции - это добавить их. Что возможно с небольшими хитростями использования надмножеств языка JavaScript, таких как TypeScript, ResonML, Flow (который называется проверка статического типа) или CoffeeScript (который никого не интересует в 2018 году), которые затем Перекомпилирован обратно в ванильный JS. Почти справедливо будет сказать, что использование одного из этих языков равносильно использованию скомпилированного языка, такого как Java. По крайней мере, с точки зрения анализа кода . В отличие от линтера, который может указывать на очевидные ошибки, но никогда не мешает вам делать опасные вещи, компилятор может вызвать ошибку компиляции, которая помешает запуску вашего кода. , по крайней мере, пока вы не исправите все проблемы, обнаруженные компилятором. Это хорошо, потому что лучше не иметь приложения, чем сломанное.

Хотя вам нужно использовать транспилятор для генерации JS из его расширенного набора, вы также можете использовать его для генерации кода JS, скажем, из более продвинутого кода JS. Хорошим примером такого инструмента может быть Вавилон. Для тех из вас, кто не знаком с этим инструментом, Babel - это транспилятор JS, который преобразует код, написанный с использованием последней и лучшей версии ES2015 +, в более старую версию ES5 для лучшей совместимости со слегка устаревшими браузерами. Итак, для пуристов и маловероятных поклонников языков со слабой типизацией - у вас все еще может быть инструмент, похожий на компилятор, для вашего 100% чистого JS-кода.

Итак, в качестве резюме этого раздела я хочу сказать следующее: если вы начинаете новый проект или делаете первые шаги с Node.js, пожалуйста, внимательно посмотрите на TypeScript или, возможно, даже на ReasonML, поскольку это отличные языки программирования, помогающие избежать много подводных камней, вызванных не очень логичным подходом JS к типам. Также, если вы фронтенд-разработчик, у которого есть веские причины не использовать ничего, кроме EcmaScript, тогда, пожалуйста, хотя бы используйте Babel. JS становится лучше с каждой итерацией ES, и вы действительно хотите получить доступ ко всем новым API как можно скорее, не говоря уже о том, что у вас будет зоркий глаз транспилятора, который будет искать для вас неприятности в вашем коде.

Вариант 3: автоматизация тестов

* Вздох *, в 2018 году я расстраиваюсь каждый раз, когда мне приходится спорить о значении модульного тестирования с, казалось бы, нормальными разработчиками, работающими над довольно большими проектами с множеством зависимостей. Более того, ситуация становится все более напряженной, если я предлагаю разработчикам также написать некоторые автоматические интеграционные и / или функциональные тесты. И дело не только в ситуации, когда у вас нет специальной группы тестирования. Скажем, в большой сложной системе могут быть некоторые сложные части, которые интегрируются друг с другом на уровне, который все еще может претендовать на тестирование методом белого ящика, которое не является модульным тестированием. Например, вы можете захотеть протестировать свой веб-API, у которого есть несколько функций промежуточного программного обеспечения, вызываемых в разных условиях (подумайте о Koa). В определенных сценариях вы можете организовать свой код таким образом, чтобы вы могли имитировать базовую инфраструктуру и вызывать конечные точки вашего API, не развертывая его в тестовой среде.

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

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

Вариант 4 (спорный): повышайте свои навыки программирования

Потому что всегда можно добиться большего успеха. Даже если ты Илон.

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

Во-первых, сделайте свой код максимально простым, читабельным и очевидным. Я уже писал о хорошем подходе, который я стараюсь применять всякий раз, когда логика занятости определенного модуля становится слишком сложной. JavaScript позволяет нам использовать некоторые концепции из мира функционального программирования, и я предлагаю вам принять их, чтобы улучшить три качества вашего кода, которые я упомянул в первом предложении этого абзаца. Тем не менее, я хочу упомянуть одну концепцию программирования, которую я научился использовать не так давно, и я сожалею, что мне потребовалось так много времени, чтобы добраться до нее. Это чистая функция - функция, которая не вызывает побочных эффектов и возвращает тот же результат для тех же аргументов. Вы можете написать их на любом языке программирования, но возможность составлять, частично применять и каррировать функции делает их особенно простыми и эффективными в JS.

Во-вторых, и это связано с вариантом 3, напишите свой код таким образом, чтобы допускать внедрение зависимостей. Но не переусердствуйте. Это должно помочь вам писать более содержательные модульные тесты, которые помогут вам понять, что с вашим кодом что-то не так, а не сбивать вас с толку, ломая без причины каждый раз, когда вы вносите небольшие изменения.



Вариант 5: единственный хороший

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

Используйте TS / Flow / ReasonML, чтобы написать чистый, серьезный код, в котором массив никогда не будет разделен на строку. Добавьте линтер в свою среду IDE, чтобы отслеживать неиспользуемые переменные и другие неприятности в режиме реального времени. Скомпилируйте свой код с помощью Babel, чтобы отловить те глупые ошибки, которые не видит линтер. Запустите автоматические тесты белого ящика перед фиксацией кода, чтобы убедиться, что ваша система не взорвется в момент развертывания (надеюсь, в вашей тестовой среде). Это не гарантирует, что вы никогда не проведете бессонную ночь, восстанавливая свое созданное вами приложение после критического сбоя, но это наверняка поможет вам свести количество таких ночей к минимуму.

Или используйте вместо этого Java / C # / Go.

Это все. Большое спасибо, и до следующего раза.