Рубрики
Без рубрики

Представление в компании

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

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

Примечание: По состоянию на январь 2021 года я больше не работаю в Stoplight И я не контролирую текущее состояние кода. Есть Вилка На моей учетной записи GitHub, который представляет состояние проекта, когда я покинул компанию.

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

Поиск точки введения

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

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

По этим причинам я решил, что есть несколько моментов, которые я не хотел идти на компромисс, пробуя FP-TS.

  • Хотя у нас не было точного срока, я знал, что стабильный релиз Prism был близок. По этой причине, независимо от состояния FP-TS в Призме, я поставил себе цель, которую Мастер ветвь должен Всегда Будьте готовы к выпуску в качестве новой крупной версии.
  • Поскольку у нас уже было много пользователей, я установил трудное правило, которое Мы бы никогда не сломали пространство пользователя
  • Поскольку я знал, что это было новое, даже для меня, и никто в команде действительно не занимался функциональным программированием, я установил цель ввести это в относительно низкую часть программного обеспечения, чтобы: что:
    • Было бы относительно легко вернуть изменения в случае, если мы поймем, что FP-TS на самом деле не соответствует варианту использования или в любом случае не будет хорошо играть вместе с остальной частью кодовой базы
    • В случае, если мы бы неправильно поняли некоторые части библиотеки или что -то испортили, оно не должно каким -либо образом изменять программное обеспечение. Предпочтительно, основные особенности призмы все еще должны функционировать правильно

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

В конце концов, случай, который я ждал, появился.

Ведение в призме

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

Более того, регистратор принес нам большую ценность для нас. Если по какой -то причине Призма ответит неправильно, из -за того, что регистратор был настолько условным, мы всегда смогли быстро определить, какой компонент плохо себя ведет (переговорщик, валидатор, сервер HTTP)

Думая о регистрации в призме, я понял это:

  • Не будет никакого способа, которым журналирование не будет сломать пространство пользователя, поскольку не было никакого влияния, ни в CLI, ни API клиента HTTP Prism, ни HTTP -сервер
  • Худшее, что произойдет в случае, если журнал будет неправильным (из-за неправильного использования/недопонимания FP-TS) было бы неправильным журналом; Издешефицированная функциональность не была бы затронута за сеанс
  • Во время введения журнала была запланирована только для переговорщика, что сделало возможным идеальный «возвратный пиар» и возвращается туда, где мы были.

По этим причинам я думал, что журнал был хорошим введением, и я рискнул попробовать это FP-TS.

Объединить пиар

Я решил пойти с Pino в качестве решения для ведения журнала. Решение было Не На основе претензий с низкой накладной/высокой производительностью, которые находятся на документации веб -сайта/проекта, но больше, потому что Pino не включает в себя какого -либо способа обработки/предупреждения/реагирования на журналы; Он просто выводит операторы журнала в качестве JSON на Stdout (или любой поток, который вы предоставляете ему). Это означает, что, по дизайну, кто -то не может сделать беспорядок с журналами и делать какие -либо действия, которые зависит от журнала. Вы не можете сломать то, что даже не включено.

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

Хаскелл действительно рассматривает это как действие, которое можно запустить только в Главный программа

putStrLn :: String -> IO ()

Точно так же FP-TS обеспечивает тот же механизм:

export function log(s: unknown): IO {
  return () => console.log(s)
}

Более того, печать на экране не считается чем -то, что может потерпеть неудачу – поэтому Либо Абстракция (которая я действительно ценил в Призме и хотел бы принять) не будет полезна в этом конкретном случае.

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

  • Я бы не Рассмотрим Консоль.log как побочный эффект; Поэтому действия были бы считаются чистыми в то время. Я прекрасно осознавал, что это неправильно, но уважать правила, которые я дал себе (и перечислил выше) Мне пришлось пойти с минимальным вторжением кодовой базы
  • Поскольку ведение журнала не считается неудачным действием, и я бы не стал считать, что он имеет побочный эффект, я решил вместо этого начать с Читатель монада

Идея состояла в том, чтобы использовать читателя Monad для внедрения регистратора в Prism http package без необходимости передавать его явно как параметр повсюду.

Это имело большой смысл, так как мы хотели иметь разные регистраторы в соответствии с контекстом (CLI, размещенная призма).

У меня был очень краткий разговор о моих намерениях с одним из моих коллег (который по сути кивнул), и я сделал это:

Хорошо, будьте готовы.

TL; Доктор

  1. Призма теперь может регистрировать вещи из переговоров.
  2. Процесс переговоров и регистрации не может больше разбиться с призмой по какой -либо причине.

Длинная версия

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

Были некоторые основные принципы, которые я имел в виду, когда писал код для этого:

  1. Призма не должна обрабатывать/формат/реагировать на журналы. Кто -то еще должен сделать это; Делать вещи в журналах, как правило, медленно, и вместо этого призма должна отвечать на все запросы как можно быстрее.
  2. Процесс переговоров в Призме в настоящее время состоит из многочисленных и вложенных функциональных вызовов, и последнее, что я хотел сделать, это перенести это регистратор параметр во всей функции и необходимость иметь дело с ней везде
  3. Регистрация не может быть где -то определено в Синглтоне – потому что экземпляр журнала будет предоставлен извне (в данном случае PRISM HTTP -сервер)
  4. Процесс ведения журнала и процесс переговоров никогда не должны делать призму. При любых обстоятельствах. Я повторяю, в Любой обстоятельства.

Давайте посмотрим, как я их приручил.

  1. Используйте Pino Анкет Если вы зайдете на их веб -сайт, напишите, что «это самый быстрый регистратор в мире», но вы можете игнорировать это, это не было причиной, по которой я пошел с этим. Основными моментами были:

    • Это включено с Фастификация – И поэтому мы не представляем новую зависимость. Мы отправляли его с вечности.
    • Pino не включает в себя никакого способа обработки/оповещения/реагирования на журналы; Он просто выводит операторы журнала в качестве JSON на Stdout (или любой поток, который вы предоставляете ему). Это означает, что вся обработка должна быть вне процесса, и я думаю, что это здорово. Это означает, что, по дизайну, кто -то не может сделать беспорядок с журналами и делать какие -либо действия, которые зависит от журнала. Вы не можете сломать то, что даже не включено.

Так где же в нашем случае происходит обработка журнала? В CLI. Из кода вы можете видеть, что всякий раз, когда обнаруживается производственная среда (или флаг -m CLI будет эффективно использовать модуль кластера, чтобы разразиться процесс Запустите Prism Server и направляйте его журналы STDOUT обратно в CLI, где Signale будет красивой печатать их. Когда призма будет где -то размещена, мы, вероятно, сделаем то же самое.

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

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

Примечание: если Node_env === Производство По умолчанию подразделяется по умолчанию, так что если вы используете CLI в среде Docker, вы получаете то, что является производственным поведением.

  1. Введите регистратор через карри. Благодаря частичному применению я могу в основном написать функцию, которая принимает обычный Аргументы, которые возвращают функцию, нуждающуюся в дополнительной зависимости для запуска. const turniate = (arg1, arg2, arg3) => logger => {//реальное тело} Анкет Для этого я использовал fp-ts Реализация читателя, которая позволяет мне делать именно это: написать код, который имеет регулярные аргументы и возвращает что -то, что потребуется для выполнения регистратора. Используя цепь и карта Метод, промежуточные функции могут легко интоцировать и изменить результат в середине, не беспокоясь о присутствии регистрации. Это будет представлено как последний шаг. Более того, если однажды мы захотим сделать маршрутизатор и начать вывод журналов – это действительно легко. Все, что нам нужно сделать, это заставить маршрутизатор плюнуть читателя и подготовить его следующим образом в Moker. Все хорошо, прибыль.

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

  3. Это произошло как эффект читателя. Поскольку регистратор внедряется в конце, традиционная попытка поймать в середине кода для украшения ошибок больше не работает. Я мог бы сделать обходной путь Но вместо этого я решил изменить подход и убедиться, что переговоры и процесс ведения журнала никогда не выбрасывают исключения. Поэтому код был изменен, чтобы использовать Либо реализация, которая включена в FP-TS , что не так сложно понять. Если вы проверите DurniatorHelper.ts Вы можете видеть, что в настоящее время не так много изменений и, что более важно, вложенные исключения сплющены – что хорошо. Очевидно, что есть 1-2 вещи, которых нет это Круто Но я на всех них. Особенно:

    • Шутка должна поддерживать обернутых помощников, чтобы я мог удалить своих домашних помощников https://github.com/facebook/jest/issues/8540
    • Встроенный Readereither мог позволить мне удалить немного Вложенные карты . Я совершенно уверен @gcanti Скоро сделает это

Выдающиеся очки

  • [x] Refactor макет выглядеть немного больше человека
  • [x] Установите ноль регистратор составная часть
  • [x] понять, достаточно ли мы или слишком много
  • [x] CLI Readme обновление
  • [x] дедупликации помощников тестирования
  • [x] Общий обзор и очистка

SO-231

PR довольно большой, и хотя я бы посоветовал вам проверить это, я почти уверен, что никто не будет. Поэтому вот TL; DR:

  • Я решил поставить свой --вербоз Флаг до 9000 и переоценить мои намерения, как я их выполнил, каковы были последствия, ограничения и как мы будем двигаться вперед с этим.
  • Некоторые коллеги были смущены терминологией; Люди, не знакомые с функцией в целом, подумают, что карта это только вещь для массивов и составлять носы, когда они видят, что он применяется где -то еще
  • Коллегия была взволнована этой работой, и, поскольку он фактически был немного более знаком с этим, он помог обзор и подтвердил преимущества, которые я пытался принести
  • Различные библиотеки и языки имеют разные имена для одной и той же «операции». В конкретном случае у нас были люди, смущенные цепь Функция, потому что где -то еще обычно называют плоская карта или связывать
  • У нас были некоторые люди, обеспокоенные общей читаемостью кода (это забавно для меня Но я знал, что мозг людей должен быть переплетен) и расширение барьера вклада

Я потратил все необходимое время, чтобы рассмотреть комментарии; Большинство из них были на самом деле больше вопросов и разъяснения, а не запросов на изменения. Большинство из них были легко разрешимы, как только я кратко объяснил концепцию, которая стоит за этой (например, , карта , склад ) Я воспринял это как хороший знак.

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

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

Введение FP-TS в Призме заставляет меня думать, что мы наконец сделаем что-то другое здесь.

В следующей статье мы увидим, как, продолжая расширять использование FP-TS в Prism, мы начали получать первые победы и возврат инвестиций, которые мы сделали.

Оригинал: “https://dev.to/vncz/introducing-in-the-company-4hg4”