Комментарии 7
Спасибо ! Утащил в закладки.
Да, сходу вопрос. Вы не планируете делать раздел посвящённый chisel https://www.chisel-lang.org/ ??? Если планируете, возможно в будущем смогу помочь. Я как раз сейчас это изучаю.
Спасибо за обратную связь и за ссылку на chisel - добавил себе в закладки!
Сейчас по планам в ближайшие полгода - это добить раздел по ФП https://scalabook.ru/fp/, а затем сконцентрироваться на библиотеках https://typelevel.org/cats-effect/ и https://fs2.io/#/, т.к. они активно используются в нашей компании и нам требуется актуализировать базу знаний по этим библиотекам. А после этих разделов тогда можно будет подумать о chisel
Спасибо, автор! Заберу в закладки. Буду пользоваться. Да прибудет с тобой сила и печеньки!
Всегда в преимущества ФП заносят чистоту функций. Но ведь реальный мир далеко не чист. И абсолютно любой проект, кроме чистой математики, взаимодействует с этим миром. Есть ли в Scala способы с этим жить на уровне самого языка?
Да, все верно: в продуктовой разработке и в реальном мире без побочных эффектов работать нельзя!
Есть несколько способов работы с побочными эффектами в Scala:
Работа с внешними эффектами. Подробно концепция работы с внешними эффектами разобрана тут: Внешние эффекты и ввод/вывод. Там можно изучить концепцию, которая применяется в ФП языках. В Scala есть библиотеки для работы с внешними эффектами: Cats Effect, ZIO и другие.
Работа с внешними эффектами - Кратко. Если же кратко, то рекомендуется из функций с внешними эффектами выделять чистые функции. Таким образом внешние эффекты постепенно вытесняются на первоначальный этап запуска сервиса и самый конечный этап выдачи выходных данных клиенту. Внутренняя часть программы - это чистые функции. Из основных плюсов: они более понятные, поддерживаемые и тестируемые. Для функций с побочными эффектами - например, взаимодействие с базой данных - требуется трудоемкое тестирование: надо поднимать testcontainers, прогонять миграцию, накатывать тестовые данные и т.д. Как показывает практика продуктовой разработки в этом случае количество тестов начинает разрастаться в геометрической прогрессии, что в конечном итоге приводит к тому, что разработчики "забивают" на тесты, игнорируют их и проверка кода в лучшем случае переносится на плечи QA, а в худшем случае и чаще всего - на плечи клиента, что крайне негативно влияет на мнение клиента о качестве продукта. В функциональном же подходе, при выносе чистых функций мы разделяем логику от реализации. Мы можем тестировать чистые функции с помощью юнит-тестов - это гораздо быстрее, чем поднимать инфраструктуру. К тому же тесты растут линейно. Если мы выделим N-чистых функций, то нам часто достаточно 2*N юнит-тестов для проверки позитивного и негативного случаев. А для проверки логики мы можем использовать моканную реализацию БД, что позволяет нам отдельно тестировать логику сервиса, что опять же быстрее, чем поднимать контейнеры и прогонять миграцию. В результате на тестирование самого внешнего эффекта чаще всего достаточно только одного позитивного и одного негативного теста с использованием реальной БД и тестовых данных. Причем эти тесты будут простыми и проверять только взаимодействие с БД. Их легко поддерживать, потому что логику и чистые функции мы будем тестить и дорабатывать в рамках юнит-тестов. Соответственно большая часть ошибок и проблем перехватывается на этапе разработки, т.к. разработчикам легче поддерживать код и покрывать его тестами, а не на стороне QA и уж тем более на стороне клиента. Подробнее о подходе тут - Внешние эффекты и ввод/вывод.
Локальные эффекты и изменяемое состояние можно инкапсулировать: подробнее тут - Локальные эффекты и изменяемое состояние. Причем можно переложить на плечи компилятора проверку того, что никто вовне не имеет доступ к изменяемому состоянию, что повышает безопасность сервиса и исключает большинство проблем при распараллеливании, когда из нескольких потоков пытаются обновить один элемент.
Отдельно стоит упомянуть о работе с потоками, когда нам надо, например, обрабатывать файлы. Подход в функциональном программировании инкапсулирует работу с ресурсами, что избавляет от ошибок, когда разработчик забыл закрыть ресурс, или когда надо обработать ресурс с "почти бесконечным" потоком. В Scala используется библиотека для потоковой обработки FS2. Подробнее о принципах работы с потоковой обработкой в функциональном программировании вот тут - Потоковая обработка и инкрементный ввод-вывод
Понятно, что многое зависит от текущей ситуации и текущего клиента, подходов к разработке ПО довольно много, но, уверен, ознакомиться с подходами в функциональном программировании все же стоит. И попробовать, конечно, для общего развития!
Хотел написать кратко, но получилось "как всегда" :)
Scalabook: пополняемая база знаний о Scala на русском языке