Принятие минимализма в разработке пользовательского интерфейса
DX означает опыт разработчика.
Некоторые функции языка JavaScript лучше оставить неиспользованными или использовать умеренно в современных приложениях React, Дуглас Крокфорд однажды написал книгу в том же духе. Когда я говорю современные, я имею в виду приложения, которые используют хуки для управления состоянием компонентов и жизненным циклом.
ИМО, вы напишете более чистый, выразительный и простой код, следуя этим советам. Недавно мы начали новый проект React, большое корпоративное приложение с множеством функций и большой командой, и пока это путешествие было довольно приятным.
Прежде чем делать предварительные выводы для этой статьи, поймите, что основная причина упрощения набора инструментов заключается в следующем:
Итак, вот список:
класс, новый, расширяет, instanceof, конструктор, супер
Для тех, кто в восторге от TypeScript, позволяющего писать ООП-код на основе классов, например Java, это шокирует. Класс - это синтаксический сахар ES6 над прототипным наследованием JavaScripts.
typeof class C {} === 'function'
Используя хуки, вы можете избежать написания компонентов на основе классов (кроме границ ошибок). Если вы стремитесь к наследованию, вы все равно можете добиться этого без классов.
Теперь вы также можете думать о решении проблем вне 23 паттернов проектирования. Я пишу тонну кода React, это может показаться безумием, но я не могу вспомнить, что мне приходилось сознательно думать об этом в последнее время. Вместо этого я сосредотачиваюсь на применении таких принципов, как композиция и инверсия управления, возможно, такова природа кода пользовательского интерфейса.
Еще один побочный эффект отказа от классов заключается в том, что вы можете сразу же игнорировать большой кусок TypeScript. TypeScript отлично подходит для больших проектов, где команды должны сотрудничать и разрабатывать / делиться кодом, но синтаксический шум - это то, о чем я всегда беспокоюсь. Кроме того, время, потраченное на выяснение того, как набирать определенные конструкции, может быть очень непродуктивным. Применение статической типизации к динамическим конструкциям очень сложно, и IMO - пустая трата времени. Если ваша цель - уменьшить количество ошибок, я рекомендую иметь хорошее покрытие для модульного тестирования.
extends позволяет создавать наследование с классами. Держитесь подальше от наследования и примите композицию.
instanceof - ключевое слово, связанное с конструкторами классов, имеющее несколько причуд.
супер и новый сочетается с классом. Используйте литералы объекта / массива и оператор распространения для создания новых.
╔═══════════╦════════════════════╗ ║ use ║ instead of ║ ╠═══════════╬════════════════════╣ ║ {} ║ new Object() ║ ║ [] ║ new Array() ║ ╚═══════════╩════════════════════╝
Большинство сторонних библиотек, которые я использую, отошли от использования new. Но иногда у вас нет выбора, когда вы имеете дело со многими встроенными объектами JavaScript. Опять же, у меня здесь только список запахов кода. Это не список неиспользованных.
это
this представляет собой запутанную конструкцию, как объясняется здесь:
Само собой разумеется, что избегание этого создает менее запутанный код. Использование функциональных компонентов поможет вам избежать этого при разработке приложений React.
позволять
К нашему удивлению, мы обнаружили, что использовали let только внутри тестов. Другое исключение было внутри компонентов, которые управляли своим поведением с помощью флагов. В другом месте всегда было const. Используйте eslint / tslint. Он предупредит вас о «let», где это применимо.
функция 😱
Вместо этого используйте стрелочные функции. Нам не нужны два разных способа выражения одной и той же конструкции. Стрелочные функции по-прежнему остаются функциями ...
typeof (() => 0) === "function"
… Но без багажа new, this и аргументов .
По моему опыту, есть два случая, когда вам нужно будет использовать ключевое слово function:
- генераторы функций, function *. На данный момент нет возможности выразить генератор функций в виде стрелочной функции.
- Использование дженериков с TypeScript. Синтаксис стрелочной функции недоступен.
аргументы
Еще один запутанный… объект? множество? Переменная?
function add(a, b) { console.log(arguments[0]); //a console.log(arguments[1]); //b }
Это сбивает с толку, потому что аргументы - это массив, подобный объекту, и переменная со специальным именем. Вместо этого используйте оператор распространения:
const add = (...args) => { console.log(args[0]); console.log(args[2]); }
if / else возвращают выражения
Тройка намного лучше. Даже вложенные блоки предпочтительнее вложенного блока if / else. Prettier красиво его отформатирует.
Используйте экономно
удалять
delete напрямую изменяет объект, удаляя из него определенное свойство. Если вам нужна неизменяемость, рассмотрите возможность использования функции пропуска в ramda или lodash. Или вы можете сделать это:
const apiResult = { id: 1, name: "Joe", city: "San Jose" }; const { id, ...cleanResult } = apiResult; // cleanResult is now void of the id property
for, for in, for, while, do while, continue, break
Циклы поощряют императивный стиль с изменением состояния и побочными эффектами внутри цикла. Даже в локальном масштабе и в меньшем масштабе это риск ошибок. Таким образом, эти ключевые слова должны быть тщательно изучены во время проверки кода. map / filter / reduce предлагают лучший декларативный стиль, чем циклы. У нас огромная база кода React (1000 плюс файлы js), и в ней нет циклов for / while.
Для итерации по объекту в большинстве случаев будет достаточно Object.keys () и Object.entries ().
для каждого
forEach по-прежнему является обязательным, его функция-итератор будет содержать побочные эффекты, поскольку вы ничего не возвращаете из выражения forEach. В большинстве случаев я гарантирую, что вы сможете переписать цикл forEach () с помощью reduce.
выключатель
Аргумент в том, что переключатель нарушает принцип Открыто / Закрыто. Я согласен. switch также имеет тенденцию создавать длинные функции. дело проваливается, когда вы забываете вернуться или сломаться - это риск.
Однако я все еще использую switch в таком случае, как редюсер Redux. Причина - знакомство, и он лучше передает намерение. В документации Redux и в большинстве онлайн-примеров используется переключатель, отход от знакомых шаблонов приводит к путанице и плохому DX. Я видел реализации редуктора без оператора switch, но с использованием объектных литералов. Тем, кто знаком с обычным шаблоном Редуктор, он выглядит чуждым и требует времени, чтобы разобраться.
Болеть за то, как реализован редуктор, не стоит. Мне нравится относиться к ней как к чистой функции, пусть она делает свое обязательное дело, только обязательно добавьте модульные тесты; редукторы очень легко протестировать.
Никогда не использовать
вар
var имеет только область функционального уровня. Это также приводит к странным проблемам с подъемом. Всегда используйте const. Если вам нужно изменить, используйте let. Опять же, используйте хороший линтер, который посоветует избегать рискованного использования.
с участием
Что он вообще делает? Я больше не могу вспомнить.
оценка
Eval позволяет анализировать строку и выполнять ее в глобальной области видимости. Для этого он вызовет интерпретатор JavaScript. Это кандидат на злонамеренные взломы, и вам никогда не следует его использовать. Обратитесь к документации для альтернативного использования с функцией ()
Принять функциональные шаблоны
Это приведет к лучшему, выразительному, декларативному стилю кода. Это ведет к:
- меньшая поверхность кода.
- построение вашей логики с использованием проверенных временем конструкций, таких как map / reduce / compose и т. д.
И то, и другое снижает вероятность появления ошибок.
С годами я стал сторонником минимализма во всем, что делаю. JavaScript - несовершенный язык, но он управляет крупнейшей в мире вычислительной платформой. Когда вы приучаете себя использовать урезанную версию, писать код пользовательского интерфейса - это удовольствие.