Tagless Final подход остаётся горячей темой в ФП-комьюнити. До сих пор практически не существовало инструментов, способных облегчить жизнь TF-адепту. Библиотека Tofu пытается решить эту проблему, предоставляя удобные абстракции для создания простого, честного и тестируемого ФП-кода.
2. О чём поговорим
• Что такое Tofu
• Зачем оно нужно?
• Из чего состоит Tofu
• Немного о его ингридиентах
• Немного (много) об Env
3. О чём не поговорим
• Что такое тайпклассы
• Что такое Cats/Cats-Effect
• Что такое Tagless-Final
4. Что такое Tofu?
• Набор инструментов для удобного ФП
• Множество удобных абстракций
• Родился из внутренних fputils
• Отлично сочетается с Tagless-Final стилем
• https://github.com/TinkoffCreditSystems/tofu/
• Production-ready, чистое value!
5. Зачем нужно Tofu
• Несовершенство текущей иерархии тайпклассов Cats/Cats-Effect
• Есть вопросы к расположению тайпклассов в иерархии
• Многие тайпклассы слишком «сильны»
• Более точный контроль над кодом/эффектами
8. Что включает в себя Tofu?
• env-monad
• optics
• memoization
• config
• logging
• атомарные тайпклассы (Context, Timeout, Raise, etc.)
9. Tofu-core
• Ядро tofu
• Содержит множество полезных тайпклассов и абстракций
• Абстрагировано от конкретных монад
• Предоставляет инстансы либо способы создания
10. Tofu-core: Fire/Race/Start
Позволяют:
• запускать вычисления в фоне с игнорированием результата
• запускать вычисления в фоне с возможностью получения
результат
• запускать несколько параллельных вычислений, возвращая
первое
13. Tofu-core: обработка ошибок
Raise:
• Позволяет прерывать цепочку вычислений (monadic fail-fast)
• Можно создать инстанс для любого ApplicativeError
17. Tofu-core: Timeout
• Позволяет прерывать вычисление после заданного интервала
• Есть инстанс для cats.effect.IO
• Можно создать инстанс для любого cats.effect.Concurrent
18. Tofu-core: Context
• Легковесная версия ApplicativeAsk
• Описывает вычисление, имеющее неизменяемый контекст
• Широко используется в tofu-logging и Env
20. Tofu-core
А также множество других полезных тайпклассов для F:
• GenUUID для генерации случайных UUID
• Lift/Unlift как аналог FunctionK[F, G] и замена cats.effect.Effect
• Тайпклассы для работы с HKT
• Аналоги Alternative из Cats
• и многое другое!
21. Tofu-logging
• Реализация логирования на тайпклассах
• Операции представлены в виде алгебры
• Логирование – это эффект!
• Структурное логирование
• Синтаксис со строковой интерполяцией
• Логирование контекста
26. Tofu-logging: Loggable
• Тайпкласс
• Описывает, как значение должно быть записано в log message
• Описывает, как значение должно быть записано в «контекст»
• «Контекст» – слабая форма построения JSON (addString, addInt,
etc.)
• Контекст может быть использован для чего угодно – ELK layout,
JSON, GELF, etc.
• Неявно конвертируется в LoggedValue
29. Tofu-logging: Loggable - syntax
• вы тоже устали от logger.{info|error|etc.}?
• мы идём к вам!
• просто добавь воды сахарка синтаксиса
• сам подхватит Logging из скоупа
• сам попросит Loggable для всех параметров
• сделает всё не всё за вас
33. Env-монада
• Монада для передачи «окружения» произвольному вычислению
• Доступ к контексту в любое время вычисления
• Прозрачная передача
• Вычислительный примитив – Monix Task
• Умеет всё, что умеет Task
34. Env-монада — зачем?
• Зачастую необходимо передавать вычислению контекст
• Логирование
• Использование в вычислениях
35. Env-монада — зачем?
• Можно передавать через implicit параметр
• Не очень удобно везде прокидывать параметр
• Можно забыть про него
36. Env-монада — зачем?
• Можно передавать через ThreadLocal/TaskLocal/etc.
• Для Future — написать свой ExecutionContext
• Плюсы для Future:
• boilerplate отсутствует
• Минусы для Future:
• Писать свой ExecutionContext
• Следить за context propagation на границе между Future и не-Future
(например, Akka) и прокидывать руками
• Сложно контролировать, контекст появляется «из воздуха»
37. Env-монада — зачем?
• Можно передавать через ThreadLocal/TaskLocal/etc.
• Для Monix Task — использовать TaskLocal
• Плюсы для Task:
• boilerplate меньше
• более приемлемый контроль над тем, где контекст есть, а где - нет
• Минусы для Task:
• boilerplate с параметрами всё равно есть - TaskLocal нужно передавать
параметром по коду
• отслеживание на границах с другими моделями исполнения всё равно есть
38. Env-монада — что предлагает?
l Прозрачная передача контекста
l Все функции «знают», что работают в некотором контексте
l Функции композируются
l Возможно переопределить контекст для локального скоупа
l Никаких сюрпризов с «потерянным» контекстом
40. Env-монада — что умеет?
l Работа с сайд-эффектами
l Работа с чистыми значениями
l Создание из других типов (Try/Either/Future/IO)
l Наличие tailRecM
42. Env-монада — что умеет?
l Обработка ошибок
l Повторы в случае ошибок
l Обработка с учётом контекста
43. Env-монада — что умеет?
l Доступ к контексту in a monadic way
l Возможность переопределить контекст для локального скоупа
l Контроль над параллелизмом «из коробки»
l Мемоизация
l Таймауты
45. Env дружит с tofu-logging!
l Один раз определить имплисит
l Показать, как контекст может быть вытащен и использован
l …
l Контекст автоматически вытаскивается и записывается в лог
l PROFIT!
l Документация с примерами интеграции coming soon!
46. Итоги
• Если вы пишете в Tagless-Final стиле – обязательно попробуйте
Tofu
• Если вы не пишете в Tagless-Final стиле, но вам нужны вычисления
с контекстом – попробуйте Tofu
• Если вы пишете код на Future – обязательно попробуйте Tofu и
Env/Task
• Если вы пишете код на акторах - Бог вам судья!