Привет, сегодня мы поговорим про чистые функции. Итак, что же такое «чистая функция»? По определению это функция, которая отвечает двум условиям.
Первое условие эта функция зависит только от своих входных аргументов, то есть эта функция всегда возвращает одно и то же значение для одних и тех же переданных аргументов.
Второе условие у этой функции не должно быть побочных эффектов. Это означает что эта функция не изменяет входные аргументы, и не изменяет окружающую среду, в которой она вызывается. Что это значит? Первое, функция не изменяет аргументы, которые вы ей передали. В некоторых языках можно указать явно как вы передаете аргумент в функцию, либо по значению, либо по ссылке. Такими языками являются С, PHP, RUBY и другие. В этом случае вы передаете не само значение, например число 3, а передаете адрес в памяти и где это число 3 записано. Таким образом функция может перезаписать это число каким-либо другим значением по этому адресу, и в итоге это повлияет на всю вашу программу. Если функция ведет себя таким образом, то эта функция нечистая. В JavaScript всё немножко интереснее, некоторые типы данных неявно передаются не по значению, а по ссылке. То есть вы можете не подозревать, что вы меняете тип данных, а вы на самом деле его изменили для всей программы, на это нужно обращать внимание. Второй момент, это побочные эффекты, то есть таким побочным эффектом может быть запись в файл. Например предположим что у нас есть функция которая вычисляет сумму двух аргументов возвращает её, но при этом она ещё записывает результат вычисления в файл, эта функция чистой быть не может, потому, что она противоречит условию 2.
Для того чтобы закрепить полученные знания у меня есть несколько примеров написанные на JavaScript, но я думаю, что это будет интересно всем. Первый пример:
Функция sum которая принимает аргументы a и b, и возвращает сумму этих двух аргументов. Эта функция чистая, она зависит только от входных аргументов a и b она их не изменяет, и она не создает дополнительных побочных эффектов.
Второй пример:
Функция удваивает координаты точки, то есть мы ей предаём точку, а она удваивает координаты, и возвращает эту точку. Является ли эта функция чистой? Нет, эта функция чистой не является, потому что в JavaScript объекты передаются не по значению, а по ссылке и тем самым изменив координаты точки, мы изменили это для всей системы, а не только для возвращаемого значения. Чтобы этого не произошло нам точку нужно скопировать, перед тем как мы её изменим.
Третий пример:
Функция, которая умножает переданное значение на какое-то случайное число, эта функция не является чистой, она зависит от случайного числа который не передается аргументом в эту функцию. Мы можем эту функцию вызвать много раз с одним и тем же параметрам X и всегда мы будем получать разные значения, которые будут зависеть от вызова функции Math.random().
Четвёртый пример:
Эта функция, которая сообщает нам текущую дату. Эта функция не является чистой, потому что она зависит от времени, если мы её запустим сегодня она нам скажет одно, если завтра, другое.
Ещё один пример:
Функция, которая зависит от какой-то внешний константы или внешние переменной. Эта функция тоже не является чистой, потому что мы можем поменять эту константу где-то наверху, потом вызвать функцию и результат работы функции будет другой.
Последняя:
Это функция записи в файл. Передаем ей данные, которые хотим записать, передаем ей имя файла, и она эти данные записывает в файл. Эта функция не является чистой, потому что она создает так называемые побочные эффекты, запись в файл. То есть перед тем, как мы эту функцию запустили у нас в файле ничего, не было, после того как мы эту функцию запустили у нас в файле что-то появилось.
Почему чистые функции хорошо, а грязные функции плохо? Всё очень просто, чистые функции очень легко тестировать. Вы знаете, что вам нужно протестировать только набор каких-то входных аргументов, и протестировать заданное количество выходных аргументов. Вам не нужно создавать никакого дополнительного состояния, чтобы протестировать какой-то из методов этого объекта. С чистыми функциями всё просто, вы падали результат на вход, проверили что результат на выходе соответствует вашим ожиданиям и всё, больше делать нечего не нужно. Тестирование — это первое преимущество.
Второе преимущество. Когда вы видите эту функцию у себя в программе вы четко знаете, что управляет этой функцией, вы видите аргументы, которые в эту функцию были переданы и вы знаете, что это тот набор аргументов, который управляет этой функцией. Получается, что если где-то после вызова этой функции вы используете эти аргументы, вы можете быть уверены, что они не были изменены, если функция что-то и сделала с этими аргументами, то она скорее всего вернула копию этих аргументов, то есть значения, которые лежат в памяти вашей программы не изменились. Это на самом деле очень сильно упрощает анализ программы, её понимание и отладку. Вот по большому счёту всё что я хотел вам рассказать про чистые функции. Если вам есть что добавить, то оставляйте комментарии. На сегодня у меня всё, спасибо что читаете, пока.