Skip to content

Latest commit

 

History

History
110 lines (67 loc) · 19.6 KB

notes.md

File metadata and controls

110 lines (67 loc) · 19.6 KB

Артхитектура

Абстракции в нашем коде должны строиться вокруг бизнес-задач, а не технологий, потому что мы делаем бизнес-ориентированные продукты и это является конечной целью. Наши технологии не должны влиять на наш продукт, всегда должна быть простая возможность заменить технологию, если этого потребует продукт (для расширения или лучшей подстройки под функционал). В нормальной ситуации не бывает такого, что мы продукт делаем для использования технологии. Классический (не традиционный) ООП говорил нам это еще десятки лет назад. Сейчас нам это же говорит компонентный подход. Нам нужны технологические модули, которые будут индивидуально решать небольшие пользовательские сценарии, для построения их в итоговый продукт. Примером может служить обычная кнопка на сайте. Принято, почему-то, разделять эту кнопку на HTML (каркас), CSS (стилистика) и JS (реакция), но нашему продукты не нужны эти элементы индивидуально, ему нужна кнопка - единый модуль, который может быть построен из любых технологий (а вдруг, SVG, GIF, Canvas, Dart).

Любая программа - это конечный автомат (FSM) в том или ином виде, в любом случае имеющий тот или иной набор ключевых состояний - выраженных бизнес-сущностей или этапов бизнес-процессов. При этом состояние отображения (view) программы - это динамическая модель, сериализуемая структура описания состояния. Можно увидеть тонкую черту между состоянием отображением и состояниями конечного автомата [бизнес-задач] - первое зависит от второго, но не наоборот. Модель данных - это более низкоуровневая абстракция, служащая для манипуляции приложением в технической реализации. Если подстраивать архитектуру приложения под структуры и возможные состояния бизнес-процессов, а не модель данных для представления, то манипуляции (добавление, редактирование, исправление) с бизнес-сущностями приложения будут проще, а значит продукт будет дешевле.

Декларативное и императивное программирование

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

Императивное программирование предполагает описывать инструкции и их последовательные связи с использованием низкоуровневых (в рамках языка программирования) выражений.

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

Компоненты web-приложения

  1. Для логирования ошибок (через window.onerror, что используют системы мониторинга) с релевантным стак-трейсом можно использовать следующую конструкцию: setTimeout((e) => { throw e; }, new Error()); - это позволит не прерывать выполнение программы.
  2. Обращение к апи сервера должно происходить через промежуточный сервис, который сам устанавливает пути к серверу и имеет соответствующие методы. Это необходимо для логирования, мокирования и контроля авторизации.

Линтинг

Lint или линтер - это статический анализатор кода, который изначально был продуктом для языка Си, но в последствии стал нарицательным словом для обозначения подобных инструментов общего класса. Линтер - это инструмент отслеживания "не правильного" использования конструкций языка, в результате которых повышается вероятность возникновения ошибки. Он позволяет находить ошибки в коде еще до его компиляции (у JS это происходит в рантайме), чем, в итоге, упрощает и ускоряет разработку. Примеры ошибок, которые может отследить линтер: неиспользуемые переменные (предупреждение), отсутствие default в switch (логическая ошибка), повторное объявление переменных (ошибка) или свойств объекта, ошибка в конструкциях языка (пропущенный catch после try). Есть возможность отсеживания и более сложных контекстно-логических ошибок, например использование индекса элемента массива, для указания key компоненту, при мапинге по списку в JSX.

Так же одной из возможностей линтеров является проверка стилистики форматирования кода (отступы, переносы строк и т.п.) определенному шаблону, но это лишь побочная функция. Например, инструмент Prettier занимается только форматированием стилистики кода (его текста) и не производит анализ уместности конструкций языка, написанных разработчиком. Поэтому не верно утверждать, что prettier может заменить линтер или наоборот - это разные инструменты. Это же касается и систем типизации, вроде TypeScript или Flow - они осуществляют проверку совместимости операторов и выражений для разных типов данных, но не проверяют как эти операторы или выражения записаны.

Использование линтера является стандартом и необходимостью в современной разработке. Для JavaScript самым популярным линтером является ESLintвот самый популярный конфиг для него), хотя у него есть альтернатива - JSHint. Так же линтеры есть и для CSS.

Циклические импорты

Своими словами.

Переменная в которую импорт осуществляется let, а не const. Импорт - это [синхронный] процесс (инициализация кода в импортируемом файле, а потом присвоение к указанным переменным). Когда какой-то модуль 1 осуществляет импорт другого модуля 2 - т.е. ожидает инициализации кода в файле 2, он (1) помечается как "в работе". Если обратиться к модулю "в работе", т.е. из модуля 2 попытаться заимпортировать модуль 1 (циклические импорты), что бы не создавать бесконечный цикл создается переменная, но в нее ничего не кладется (undefined), но при этом остается пометка, что при окончании импорта модуля 1, положить результат в переменную (которая в модуле 2). Таким образом можно делать рекурсивные ссылки и при этом не вешать сборщик (это по спеке, кстати).

По идее обращаться к переменной из циклического импорта можно уже на следующий тик Promise.resolve().then(() => importedModule)

UX

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

"unvalidated input" - осуществленный ввод не прошедший валидацию. Должен сопровождаться уведомлением пользователю в стиле ошибки (обычно, красного цвета), что бы дать ему понять почему форма не может быть отправлена.

UI

Палитра

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

Обычно выбирается набор "сочитающихся" цветов и ими закрашиваются разные компоненты. При этом в наборе два десятка цветов (классический вариант: primary и accent) + разнообразные тени и фоны (например). И какой и куда цвет применить - совершенно не ясно. Вдобавок всего два тона не всегда хватает и возникают новые проблемы с поиском нужной гаммы.

Но можно использовать следующий подход:

  1. Не цвета пытаться впихнуть в компоненты, а к компонентам искать подходящие цвета. Т.е. для каждого компонента должна отдельно определяться цветовая гамма: полностью индивидуальная, или отнаследованная от родителя. Важно понять цель дизайна не раскидать цвета по интерфейсу, а выделить интерфейс, используя цвета.
  2. Брать за основу 3 цвета: background (фон), basic (основной цвет выделения частей интерфейса), accent (для привлечения взаимодействия - интерактивности пользователя). Плюс от каждого цвета могут быть производные (калькулируются автоматически) цвета: text, shadow, disabled (но они, в большинстве своем, будут стандартными и не будут "напрягать" необходимостью их конфигурировать). И здесь важно понимать, что каждая часть интерфейса может быть отдельным компонентом с собственной цветовой гаммой: список товаров, карточка товара, шапка карточки, кнопки. Например, у карточки товара есть фон из background и бордеры из basic. А у выпадающего списка фон из background, текущий вариант из basic, а вариант с focus \ hover из accent. Так же данные три цвета являются фундаментальными, но не единственными. У кнопки при hover - цвет accent, но при focus бордер из полупрозрачного accent - т.е. мы модифицируем фундаментальный цвет компонента при необходимости расширения гаммы.

Конечный смысл в том, что бы стилизовать интерфейс от фич (бизнес-задач), а не от формальной потребности в дизайне и всегда иметь фундаментальную, гибкую и при этом не избыточную палитру.

Security

CORS

в заголовке Access-Control-Allow-Origin перечисленны доверенные ресурсы, на которые браузер будет разрешать запросы из кода страницы. Этот заголовок указывает сервер с которого хостится статика. Параметр * - означает доверять ВСЕМ, что является серьёзной потенциальной дырой в безопасности. Если API лежит на одном адресе, а страница хоститься на другом, то нужно либо в настройках веб=сервера [хостинга] указать в заголовке Access-Control-Allow-Origin API сервер, либо (что предпочтительнее) сделай на хостинге проксю к API и запрашивать данные по локальному пути.

Подробнее

Отличие cookie от localStorage.

(!) Данный раздел будет вынесен в отдельную статью, когда будет доделан

Каждая технология под заголовком в таблице ниже - это сумма ее использования в JS

cookie localStorage
максимальный объем ~4 KB ~5 MB
привязка к домену да да
привязка к поддомену да да
привязка к поддоменам да нет
привязка к пути да нет
управление временем жизни да нет
доступ из JS да да
удобство доступа из JS нет да
запрет доступа из JS да да
XSS нет да
CSRF да нет
частичное применение нет да
загрузка больших файлов да нет
SSR да нет
запрет пользователем да нет
можно управлять с сервера да нет
данные зашифрованы на диске да нет

Фундаментальным плюсом у cookie является невозможность доступа из JS при использовании флага HttpOnly, что избавляет от атак типа XSS, но при этом все равно остается уязвимость CSRF, которой, как бы, не подвержен localStorage. Так же важно учитывать, что у пользователя могут быть просто отключены cookie, но у них есть и неоспоримые преимущества: это загрузка [больших] файлов с помощью Content-Disposition и возможность персонализированного server side rendering, а так же возможность установки время действия и контроля со стороны сервера.

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

[WIP]

  1. При запросе статики в исходные коды исполняемого JS файла на место определенной переменной подставляется ключ
  2. Перетираем window.fetch и т.п.

... вообще главная цель не выпускать токен из реалма

Важно отметить, что при использовании cookie стоит помнить о: 1) малом возможном обёме (не стоит в них хранить ничего, кроме токена авторизации); 2) необходимости получение подтверждения пользователя при их использовании.