Firebase изменила свой Javascript API на версию v9. Ранее методы были объединены в цепочки, что делало их более читабельными:

Теперь Firebase 9 использует более модульный подход, ориентированный на функциональное программирование:

Это несет в себе некоторые преимущества:

  • Команде Firebase проще тестировать функции
  • Облегчает встряхивание дерева (уменьшает размер пакета — неиспользуемые модули/функции выбрасываются при компиляции)

Однако все становится запутанным, когда пользователь API (разработчик) пробует что-то более реалистичное (и люди жалуются):

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

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

Чтобы упростить это:

  • pipe() возвращает функцию, которую мы можем вызвать. Любые аргументы будут переданы первому элементу в списке, и мы получим результат последнего элемента.
  • curry() возвращает ту же предоставленную функцию, которую мы можем частично завершить для последующего выполнения (когда предоставлены все аргументы). Из ref docs: если мы const refC = curry(ref) , мы можем вызвать const refDb = refC(database) и позже refDb('users') .

API Firebase обычно принимает контекст (ссылка, база данных) в качестве первого аргумента и информацию о функции (путь, полезная нагрузка) в качестве второго аргумента (последние данные). Поэтому мы делаем это справа. Например, в ref() сначала указывается путь, а ссылка получается позже, когда у нас есть база данных.

ramda — отличная библиотека FP, но она не предоставляет прямого метода обратного каррирования. Поэтому мы используем curryRight lodash. Если вы используете ESM, установите вместо него lodash-es.

Изначально получаем:

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

Как минимум мы должны экспортировать каррированный API в отдельный файл:

Теперь нам не нужно различать ref и refC.

Ваш выбор между двумя вариантами зависит от вашей ситуации. Мне пришлось реорганизовать существующее приложение Vue.js, и второй подход был более простым, поскольку каждый компонент Vue использовал Firebase напрямую без каких-либо сервисных функций (например, /services/users/getUser). Пример из реального мира:

Здесь я не стремлюсь к чистым функциям, поэтому вставка внешних переменных (состояние формы, идентификатор пользователя) тривиальна.

С другой стороны, при создании нового приложения вы должны перенести действия в служебные файлы.

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

К сожалению, обычное каррирование не подходит для Typescript. Интерпретатор не может понять, что получается, когда вы каррируете функцию. В этом случае вы можете полностью отказаться от lodash и выполнить функции вручную:

В заключение давайте проведем чистое сравнение:

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

Для пользователей Docker я сделал демо для обеих версий API (инструкции внутри).

Примечание №1. Новый Firebase v9 SDK предлагает API compat, который позволяет связывать методы и снижает потребность в рефакторинге — это выходит за рамки этой статьи.

Примечание №2: в этой статье используется база данных реального времени. Другие модули не тестировались.

Повышение уровня кодирования

Спасибо, что являетесь частью нашего сообщества! Перед тем, как ты уйдешь:

  • 👏 Хлопайте за историю и подписывайтесь на автора 👉
  • 📰 Смотрите больше контента в публикации Level Up Coding
  • 🔔 Подписывайтесь на нас: Twitter | ЛинкедИн | "Новостная рассылка"

🚀👉 Присоединяйтесь к коллективу талантов Level Up и найдите прекрасную работу