Чистые и грязные функции, эффекты и обработка сигналов, сайдэффекты: чистые функции
АлексейПривет!
Обращаю ваше внимание, что топик расширился - помимо анонсированных вчера грязных функций, вчера же я ещё "открыл" сигналы.
Заголовок конечно длинноват, но пока так:)
Но обо всём по порядку и сегодня у нас чистые функции.
Чистая функция - это функция без эффектов, сайдэффектов и обработки сигналов:)
Или функция в математическом смысле - её результат определяется исключительно параметрами и у неё только один результат - возвращаемое значение.
Признаки не чистоты функций:
- У неё нет результата (возвращает void/Unit).
Теоретически можно сделать такую чистую функцию, но пользы от неё будет очень мало - её можно будет использовать только в качестве затычки для какого-то вывода.
Типичный пример - printf/println. - У неё нет аргументов.
Опять же, теоретически можно сделать такую функцию, но пользы от неё будет очень мало - её можно будет использовать только в качестве затычки для какого-то ввода.
Типичный пример - currentTime - Будучи вызванной с одними параметрами в разное время, она может вернуть разные результаты.
Тут уже без вариантов, по определению все такие функции не являются чистыми
Типичный пример - Files.readString(Path.of("/tmp/test")) - Будучи детерминированной, она обладает наблюдаемым эффектом, помимо возврата значения.
Опять же без вариантов, все такие функции не чистые по определению.
Типичные примеры: кэширование детерминированных функций и логгирование в детерминированных функциях.
Что же такого особого в чистых функциях, что они заслужили отдельное название?
Чистые функции обладают свойством ссылочной прозрачности.
Это свойство означает, что вызов функции можно заменить на результат её вычисления и при этом поведение программы не изменится.
И уже из этого свойства вытекает ряд других, практически значимых и делающих чистые функции идеальным строительным блоком.
Модульность чтения
При чтении кода, вы можете сэкономить "стэк" и "кучу" своего мозга, за счёт игнорирования деталей реализации вспомогательных чистых функций.
Это достигается за счёт того, что эффект вызова чистой функции очевиден, и вам нет необходимости досконально изучать реализацию функции на предмет неизвестных неизвестных - глобального состояния, которое влияет на поведение функции, или которое меняет сама функция и которое влияет на поведение интересующего вас кода.
Если вам надо поменять какое-то другое место и вы понимаете какой будет результат вызова чистой функции, вам не важно, как этот результат будет получен, т.к. по определению, место которое вы собираетесь править ни как не связано с реализациями чистых функций.
Безопасность рефакторинга
Вызовы чистых функций можно свободно переупорядочивать, перемещать между методами, инлайнить, кэшировать и т.п. и никто (опять же по определению) этого не заметит.
Ну ток что компилятор откажется компилировать.
Тестирование
Чистые функции тестируются тривиально - готовите параметры, вызываете, проверяете результат вызова.
Не надо делать медленный ввод-вывод, поднимать внешние сервисы или приколачивать тест к реализации моками, заморачиваться на проверку в многопоточной среде, симулировать ошибки ввода-вывода и заниматься прочим адом сопровождающем тестирование не чистых функций.
Композиция/переиспользование
Из чистых функций легко строить более сложные функции, не беспокоясь о неожиданных эффектов.
Например, функцию валидации, которая кроме возврата результата валидации ещё и сохраняет запрос на валидацию в БД, врядли удастся использовать в каком-то новом контексте.
Параллельное исполнение
И снова по определению, чистые функции можно безопасно выполнять параллельно и/или отдавать их на исполнение другим потокам.
Кэширование
С чистыми функциями инвалидация кэша больше не является проблемой.
Оптимизация
Пруфы что это реально используется искать лень, но теоретически компиляторы могут оптимизировать чистые функции намного более агрессивно за счёт безопасности рефакторинга.
И раз чистые функции столь прекрасны, почему все не пишут только чистые прекрасные функции?
Потому что мы создаём программы ради их эффектов на наш физический мир.
Продолжение следует:)