Чистый и масштабируемый синтаксис в поисках чистоты

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

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

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

Установка стандарта с помощью V8 - вот как впоследствии был создан Node.js. Будучи полноценным языком программирования с поддержкой выполнения на стороне сервера, JavaScript теперь поддерживает современные веб-приложения и масштабируется по всему технологическому стеку.

Подход

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

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

Большая часть нашей работы в Accord Project выполняется на JavaScript с добавлением некоторого предметно-ориентированного языка. Для создания надежного технологического стека, обеспечивающего стабильность и эффективность смарт-контрактов, Accord Project использует JavaScript, а также OCaml. и Ergo. JavaScript предоставляет лучший набор инструментов для решения этой проблемы в широком спектре сценариев использования и сред. Мы выбрали JavaScript из-за его применимости, разнообразия библиотек и простоты использования. Синтаксис в этом языке выразительный, но простой.

Базовый код Accord Project содержит более 250 тыс. Строк кода. Наряду с нашей библиотекой шаблонов и компонентами пользовательского интерфейса их около миллиона.

Контур:

Подход
Основы
Рабочий процесс
Операции
Функции
Асинхронный
Функциональное программирование
Заключение
Ресурсы

Основы

Понятный

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

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

Глобалы

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

Переменные

Прекратите использовать var. Поведение в области видимости непоследовательно и сбивает с толку, что может привести к ошибкам. ES6 принес const и let. Стремитесь использовать строго const и используйте let только в том случае, если это невозможно. Существует больше ограничений, и const нельзя переназначить, но не совсем неизменяемо. Переменная будет иметь неизменяемую ссылку на тот же объект или примитивное значение, но значение, удерживаемое переменной, не является неизменным. Тем не менее, это будет лучшая практика в будущем.

Именование

Небольшое отступление, но программисты могут тратить в 10 раз больше энергии на соглашения об именах, но при этом изо всех сил стараются быть инклюзивными в своем языке.

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

Это особенно важно для тех, кто хочет обучать других; имена переменных должны помочь объяснить и дать контекст тому, что происходит в коде. Кто-то, кто плохо знаком с этим кодом, должен иметь общее представление о том, что происходит. Используйте глаголы. Пример логической переменной может начинаться с is…, а примерами функций могут быть глаголы действия.

Хорошие справочные материалы можно найти здесь: Соглашение об именах на основе грамматики

Рабочий процесс

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

Заказ на импорт

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

Модуляризация

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

Если размер файла превышает 300–400 строк кода, есть веские основания считать, что он слишком загроможден и его невозможно поддерживать. На этом этапе можно получить много преимуществ от создания новых модулей и папок для разделения процессов. Думайте о проекте как о дереве с множеством ветвей, а не о горе нагроможденного кода.

ESLint - отличный помощник в этом. Старайтесь, чтобы файлы были меньше четырех или пяти углублений. Это делает код специализированным и способствует очистке мертвого кода. Несколько функций, выполняющих один небольшой процесс, будут более полезными, чем одна функция, выполняющая несколько задач. Большая функция может использоваться только одним способом, тогда как более мелкие функции могут использоваться в нескольких процессах в рамках проекта. Предоставление этих небольших вспомогательных функций создает надежную базу API в проекте.

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

Код изолятора

Функция должна иметь одну цель и не выполнять несколько действий. Эта цель должна быть чем-то другим, а не побочным эффектом, но мы вернемся к этому в разделе функционального программирования.

Надуманный пример этого - инкапсуляция условных выражений:

Охранные оговорки

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

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

Красивее и пух

Тема моей статьи заключается в том, что код должен быть легким для чтения и понимания. С этим приходит последовательный стиль и структурирование. Очень пригодится линтер - любой линтер. ESLint - это линтер, который выявляет проблемы с правильностью кода, такие как предупреждение об использовании var. Prettier - это средство форматирования, которое, например, выявляет проблемы с единообразием и согласованностью и автоматически выравнивает скобки. Приветствуется использование обоих вместе.

StandardJS и предопределенная конфигурация ESLint являются хорошими источниками правил линтинга, если вам нужна хорошая отправная точка.

Операции

Деструктуризация

Деструктуризация может помочь сэкономить много текста и строк кода за счет того, что переменные должны быть короткими и извлекаться из объекта на ранней стадии. Представленный в ECMAScript 6, он позволяет получить доступ к определенным полям из любого объекта или модуля и сразу же присваивает его переменной.

Объекты:

Массивы (пропускаемые элементы состоят из , ,):

Функции (аналогично объектам):

Значения по умолчанию

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

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

Тернарный

Этот оператор работает аналогично логическим операторам и операторам if…else и состоит из трех разделов:

1. Логическое условное
2. Возвращаемое значение в случае правдивости
3. Возвращаемое значение в случае фальсификации

Старайтесь держаться подальше от отрицательных условных выражений - проверьте, существует ли что-то действительно, а не не существует.

Распространять

Другая форма деструктуризации объекта, оператор распространения, позволяет извлекать значение из данных без явного перебора данных. Это обычное дело в Redux и функциональном программировании, так как это короткий способ добавить к объекту без его изменения - скопировать старый объект, расширив его и добавив к нему новое значение.

Литералы шаблона

Эта функция позволяет встраивать динамический контент в строки и писать строки, соединяющие несколько строк. Они обозначаются обратными кавычками (``) и фрагментами шаблонных литералов (${}).

Функции

Ограничить объем

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

Стрелка

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

Ранее функция могла быть записана как:
function someFunction(input) { /* ...code */ }

Теперь мы определяем то же самое, что и:
const someFunction = input => { /* ...code */ }

Если функция возвращает только что-то простое, мы можем записать это в одной строке с помощью неявного оператора return:
const add = (a, b) => a + b;

const createObject = (a, b) => ({ a, b });

Параметры

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

Цепочка

Источником текущего разочарования является невозможность легко получить доступ к вложенному значению в объекте. В настоящее время можно использовать что-то вроде этого:

Отвратительный.

Причина этого в том, что если вы перейдете прямо к последней строке, вы можете столкнуться с такой ошибкой:
TypeError: Cannot read property ‘fourthProp’ of undefined

TC39 (технический комитет, который определяет, какие функции должны стать частью стандарта JavaScript) перенес предложение по необязательной цепочке на более поздние этапы принятия.

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

Если какое-либо свойство не существует, копание завершается и возвращает undefined.

Другим текущим решением этой проблемы является Ramda, которая использует функцию под названием path для безопасного выполнения кода во время выполнения и не вызывает undefined ошибок в консоли.

Асинхронный

Я ранее писал Асинхронно с Redux Sagas, но я сосредоточусь больше на _23 _ / _ 24_ и обещаниях для этого.

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

Однако JavaScript был разработан, чтобы реагировать на действия пользователя, которые являются асинхронными по своей природе. Браузер, в котором живет JavaScript, предоставляет набор API, которые обрабатывают эту функцию. Более того, Node.js представляет среду неблокирующего ввода-вывода, чтобы распространить эту концепцию на файлы, сетевые вызовы и т. Д.

Когда эта побочная функция передается отдельному потоку, например вызову API, она возвращается как обратный вызов, который является функцией, переданной в другую функцию в качестве аргумента. Затем он вызывается внутри внешней функции для завершения действия.

Асинхронный и ожидающий

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

Функции, которые его используют, требуют перед ним ключевого слова async, а await можно использовать только в функциях, которые имеют это ключевое слово. Эта async функция неявно возвращает обещание, которое будет преобразовано в значение, возвращаемое внутри функции.

Преимущества:
+ Четкость: меньше кода и удобнее для чтения.
+ Обработка ошибок: _28 _ / _ 29_ может обрабатывать как синхронный, так и асинхронный код
+ Условные выражения: более прямолинейный- прямая обработка динамических результатов
+ Отладка: трассировку стека ошибок намного легче отслеживать
+ Ждать чего угодно

Функциональное программирование

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

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

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

Чистые функции

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

Чистая функция - это функция, которая следует некоторым рекомендациям функционального программирования; а именно, он возвращает тот же результат при тех же аргументах (идемпотентный) и не вызывает наблюдаемых побочных эффектов. Это делает его ссылочно прозрачным, и преимуществом этого является то, что этот код намного легче тестировать. Благодаря этой концепции мы можем запомнить эти функции.

Побочные эффекты

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

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

В JavaScript примитивные типы данных передаются по значению, тогда как объекты передаются по ссылке. Поэтому, если функция вносит изменения в массив, это повлияет на любую другую функцию, которая ссылается на этот массив. Это огромная опасность, которой стремится избежать функциональное программирование; если две отдельные и несвязанные функции принимают один и тот же ввод, но одна из функций изменяет этот ввод, другая функция становится некорректной. Постоянное клонирование больших объектов может стать утомительным для производительности, но есть отличные библиотеки, которые достаточно производительны, такие как Ramda.

Рамда

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

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

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

Трубопровод

В то время как Ramda отлично подходит для объединения функций в конвейер, JavaScript - это постоянно развивающийся язык, и вскоре он будет иметь это изначально. У TC39 в настоящее время есть предложение по p оператору ipeline. А пока попробуйте Ramda и найдите действительно мощные инструменты.

Заключение

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

Помимо контроля доступа и токсичности в этой области, возможность доступа к такому множеству различных секторов обеспечивает более активное сотрудничество и более опытное население в сообществе. У этого языка столько силы. Кросс-платформенные настольные приложения можно создавать с помощью JavaScript в Electron, мобильных приложений с React Native и серверных решений с помощью Node.js.

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

Не стесняйтесь обращаться ко мне с любыми вопросами или отзывами.

Ресурсы

Сообщество

DEV #javascript
Javascript Weekly

Образование

FreeCodeCamp
Компьютерное программирование Академии Хана
Повторное введение в JavaScript
Учебник по современному JavaScript

Книги

Вы не знаете JavaScript
Красочный Javascript

Блоги

Эрик Эллиотт

Подкасты

Javascript Jabber
JS Part y
Syntax.fm
Full Stack Radio
Подкаст Ladybug
Javascript to Elm
Город Вязов

Разное

JavaScript: понимание странных частей
30 дней испытаний JavaScript с соответствующими видео от Уэса Боса
Fun Fun Function
Switch Case vs Object Literal:
Switch case, if else, или карта цикла от Мэй Шавин
Переписывание Javascript: замена оператора Switch от Криса Бургина
Статический ввод
TypeScript
Начните работу с TypeScript в 2019 году
Нежное введение в TypeScript
Понимание нотации типов в TypeScript
Функциональный интерфейс
Elm
→« Elm Руководство"