0 added
0 removed
Original
2026-01-01
Modified
2026-02-26
1
<p>Часто в программировании возникает проблема с неявными зависимостями и побочными эффектами. Они могут привести к неожиданным результатам или ошибкам в программе. Обычно с такими проблемами борются с помощью чистых функций.</p>
1
<p>Часто в программировании возникает проблема с неявными зависимостями и побочными эффектами. Они могут привести к неожиданным результатам или ошибкам в программе. Обычно с такими проблемами борются с помощью чистых функций.</p>
2
<p>В этом уроке мы изучим важные свойства функций. С их помощью можно более точно определять, как лучше разбивать код на функции и когда вообще их стоит выделять.</p>
2
<p>В этом уроке мы изучим важные свойства функций. С их помощью можно более точно определять, как лучше разбивать код на функции и когда вообще их стоит выделять.</p>
3
<h2>Что такое детерминированность</h2>
3
<h2>Что такое детерминированность</h2>
4
<p><strong>Детерминированность функций</strong>- это свойство, при котором функция всегда возвращает один и тот же результат для одних и тех же входных данных без побочных эффектов, связанных с состоянием программы. Детерминированная функция не зависит от контекста и внешних факторов. Она гарантированно возвращает предсказуемый результат.</p>
4
<p><strong>Детерминированность функций</strong>- это свойство, при котором функция всегда возвращает один и тот же результат для одних и тех же входных данных без побочных эффектов, связанных с состоянием программы. Детерминированная функция не зависит от контекста и внешних факторов. Она гарантированно возвращает предсказуемый результат.</p>
5
<p>Рассмотрим пример функции, которая не является детерминированной:</p>
5
<p>Рассмотрим пример функции, которая не является детерминированной:</p>
6
<p>Эта функция возвращает случайное число от 1 до 10 при каждом вызове. Если мы вызываем функцию несколько раз, то получим разные результаты:</p>
6
<p>Эта функция возвращает случайное число от 1 до 10 при каждом вызове. Если мы вызываем функцию несколько раз, то получим разные результаты:</p>
7
<p>Теперь рассмотрим пример детерминированной функции:</p>
7
<p>Теперь рассмотрим пример детерминированной функции:</p>
8
<p>Функция multiply() всегда возвращает результат умножения двух переданных ей аргументов. Если мы передадим одни и те же значения, то получим один и тот же результат:</p>
8
<p>Функция multiply() всегда возвращает результат умножения двух переданных ей аргументов. Если мы передадим одни и те же значения, то получим один и тот же результат:</p>
9
<p>Это делает функцию multiply() детерминированной, так как она всегда возвращает один и тот же результат для одного и того же набора входных данных.</p>
9
<p>Это делает функцию multiply() детерминированной, так как она всегда возвращает один и тот же результат для одного и того же набора входных данных.</p>
10
<p>Нельзя однозначно сказать, что отсутствие детерминированности - это плохо. Для работы многих программ и сайтов нужна функция, которая будет возвращать случайное число или вычислять текущую дату. Но мы можем разделить код так, чтобы в нем было как можно больше детерминированных частей.</p>
10
<p>Нельзя однозначно сказать, что отсутствие детерминированности - это плохо. Для работы многих программ и сайтов нужна функция, которая будет возвращать случайное число или вычислять текущую дату. Но мы можем разделить код так, чтобы в нем было как можно больше детерминированных частей.</p>
11
<p>Если есть возможность написать функцию так, что она будет детерминированной, то так и нужно делать. При этом не стоит использовать глобальные переменные. Необходимо создавать функции, которые зависят только от своих аргументов.</p>
11
<p>Если есть возможность написать функцию так, что она будет детерминированной, то так и нужно делать. При этом не стоит использовать глобальные переменные. Необходимо создавать функции, которые зависят только от своих аргументов.</p>
12
<h2>Что такое побочные эффекты</h2>
12
<h2>Что такое побочные эффекты</h2>
13
<p><strong>Побочные эффекты</strong>или<strong>side effects</strong>- это любые взаимодействия с внешней средой. К ним относятся файловые операции, такие как запись в файл, чтение файла, отправка или приём данных по сети и даже вывод в консоль.</p>
13
<p><strong>Побочные эффекты</strong>или<strong>side effects</strong>- это любые взаимодействия с внешней средой. К ним относятся файловые операции, такие как запись в файл, чтение файла, отправка или приём данных по сети и даже вывод в консоль.</p>
14
<p>Рассмотрим пример функции, которая имеет побочный эффект:</p>
14
<p>Рассмотрим пример функции, которая имеет побочный эффект:</p>
15
<p>Эта функция выводит сообщение в консоль, значит, она имеет побочный эффект. Если мы вызываем функцию print_hello, то она изменяет состояние программы путем вывода сообщения в консоль. Но она не возвращает никакого значения:</p>
15
<p>Эта функция выводит сообщение в консоль, значит, она имеет побочный эффект. Если мы вызываем функцию print_hello, то она изменяет состояние программы путем вывода сообщения в консоль. Но она не возвращает никакого значения:</p>
16
<p>Кроме того, побочными эффектами считаются изменения внешних переменных (например, глобальных) и входных параметров в случае изменяемых типов (списки, словари и прочие).</p>
16
<p>Кроме того, побочными эффектами считаются изменения внешних переменных (например, глобальных) и входных параметров в случае изменяемых типов (списки, словари и прочие).</p>
17
<p>Побочные эффекты составляют одну из самых больших сложностей при разработке. Они затрудняют логику кода и тестирование. Это приводит к большому числу ошибок. Например, только при работе с файлами количество возможных ошибок измеряется сотней. В этом случае может не хватить места на диске или будет попытка прочитать данные из несуществующего файла. Для предотвращения ошибок код обрастает большим числом проверок и защитных механизмов.</p>
17
<p>Побочные эффекты составляют одну из самых больших сложностей при разработке. Они затрудняют логику кода и тестирование. Это приводит к большому числу ошибок. Например, только при работе с файлами количество возможных ошибок измеряется сотней. В этом случае может не хватить места на диске или будет попытка прочитать данные из несуществующего файла. Для предотвращения ошибок код обрастает большим числом проверок и защитных механизмов.</p>
18
<p>Но без побочных эффектов невозможно написать ни одной программы. Какие бы вычисления она ни делала, их результат должен быть как-то продемонстрирован. Даже у простой программы сложения двух чисел нам нужно увидеть результат, что автоматически приводит к побочным эффектам. В реальных же приложениях, обычно, все сводится к взаимодействию с базой данных или отправкой запросов по сети. Не существует способа избавиться от побочных эффектов совсем, но их влияние на программу можно минимизировать.</p>
18
<p>Но без побочных эффектов невозможно написать ни одной программы. Какие бы вычисления она ни делала, их результат должен быть как-то продемонстрирован. Даже у простой программы сложения двух чисел нам нужно увидеть результат, что автоматически приводит к побочным эффектам. В реальных же приложениях, обычно, все сводится к взаимодействию с базой данных или отправкой запросов по сети. Не существует способа избавиться от побочных эффектов совсем, но их влияние на программу можно минимизировать.</p>
19
<p>Как правило, в типичной программе побочных эффектов не так много по отношению к остальному коду, и происходят они лишь в самом начале и в конце. Например, программа, которая конвертирует файл из текстового формата в PDF, в идеале выполняет ровно два побочных эффекта:</p>
19
<p>Как правило, в типичной программе побочных эффектов не так много по отношению к остальному коду, и происходят они лишь в самом начале и в конце. Например, программа, которая конвертирует файл из текстового формата в PDF, в идеале выполняет ровно два побочных эффекта:</p>
20
<ol><li>Читает файл в самом начале работы программы.</li>
20
<ol><li>Читает файл в самом начале работы программы.</li>
21
<li>Записывает результат работы программы в новый файл.</li>
21
<li>Записывает результат работы программы в новый файл.</li>
22
</ol><p>Между этими двумя пунктами и происходит основная работа, которая содержит чистую алгоритмическую часть. Побочные эффекты в таком случае будут находиться только в верхнем слое приложения, а ядро, выполняющее основную работу, останется чистым от них.</p>
22
</ol><p>Между этими двумя пунктами и происходит основная работа, которая содержит чистую алгоритмическую часть. Побочные эффекты в таком случае будут находиться только в верхнем слое приложения, а ядро, выполняющее основную работу, останется чистым от них.</p>
23
<h2>Чистые функции</h2>
23
<h2>Чистые функции</h2>
24
<p><strong>Чистые функции</strong>или<strong>pure functions</strong>- это функции, которые при вызове не влияют на состояние программы и не имеют побочных эффектов. Они возвращают значения только на основе входных аргументов и не изменяют их.</p>
24
<p><strong>Чистые функции</strong>или<strong>pure functions</strong>- это функции, которые при вызове не влияют на состояние программы и не имеют побочных эффектов. Они возвращают значения только на основе входных аргументов и не изменяют их.</p>
25
<p>Признаки чистых функций:</p>
25
<p>Признаки чистых функций:</p>
26
<ul><li>Всегда возвращают одинаковые значения для одинаковых аргументов.</li>
26
<ul><li>Всегда возвращают одинаковые значения для одинаковых аргументов.</li>
27
<li>Не имеют побочных эффектов - не изменяют состояние программы за пределами своей области видимости. Таким образом они не модифицируют глобальные переменные, не изменяют содержимое файлов, не выводят на экран и не изменяют содержимое баз данных.</li>
27
<li>Не имеют побочных эффектов - не изменяют состояние программы за пределами своей области видимости. Таким образом они не модифицируют глобальные переменные, не изменяют содержимое файлов, не выводят на экран и не изменяют содержимое баз данных.</li>
28
<li>Не имеют побочных эффектов на аргументы, которые переданы им по ссылке - не изменяют их содержимое.</li>
28
<li>Не имеют побочных эффектов на аргументы, которые переданы им по ссылке - не изменяют их содержимое.</li>
29
<li>Не зависят от состояния программы, поэтому не используют глобальные переменные или переменные, которые могут изменяться во время выполнения программы.</li>
29
<li>Не зависят от состояния программы, поэтому не используют глобальные переменные или переменные, которые могут изменяться во время выполнения программы.</li>
30
</ul><p>Примеры чистых функций:</p>
30
</ul><p>Примеры чистых функций:</p>
31
<p>Эти функции возвращают значение только на основе переданных им аргументов и не влияют на другие переменные в программе.</p>
31
<p>Эти функции возвращают значение только на основе переданных им аргументов и не влияют на другие переменные в программе.</p>
32
<p>У чистых функций есть несколько преимуществ:</p>
32
<p>У чистых функций есть несколько преимуществ:</p>
33
<ul><li>Их просто тестировать. Достаточно передать на вход функции нужные параметры и посмотреть ожидаемый выход.</li>
33
<ul><li>Их просто тестировать. Достаточно передать на вход функции нужные параметры и посмотреть ожидаемый выход.</li>
34
<li>Их безопасно запускать повторно, что особенно актуально в асинхронном коде или в случае многопоточного кода.</li>
34
<li>Их безопасно запускать повторно, что особенно актуально в асинхронном коде или в случае многопоточного кода.</li>
35
<li>Их легко комбинировать, получая новое поведение без необходимости переписывать программу.</li>
35
<li>Их легко комбинировать, получая новое поведение без необходимости переписывать программу.</li>
36
</ul><h2>Грязные функции</h2>
36
</ul><h2>Грязные функции</h2>
37
<p>Не все функции могут быть чистыми, особенно, когда программы часто взаимодействуют с внешними ресурсами. В таких случаях функции могут изменять состояние программы или взаимодействовать с внешними системами, такими как базы данных или веб-сервисы. Такие функции называют грязными.</p>
37
<p>Не все функции могут быть чистыми, особенно, когда программы часто взаимодействуют с внешними ресурсами. В таких случаях функции могут изменять состояние программы или взаимодействовать с внешними системами, такими как базы данных или веб-сервисы. Такие функции называют грязными.</p>
38
<p>Один из интересных примеров это замыкание. Само по себе замыкание не делает функцию ни чистой, ни грязной. Все зависит от того, возможно ли изменять замкнутую переменную.</p>
38
<p>Один из интересных примеров это замыкание. Само по себе замыкание не делает функцию ни чистой, ни грязной. Все зависит от того, возможно ли изменять замкнутую переменную.</p>
39
<p>Если замыкание только читает замкнутые переменные, не изменяя их, функция остается чистой:</p>
39
<p>Если замыкание только читает замкнутые переменные, не изменяя их, функция остается чистой:</p>
40
<p>Если замыкание изменяет замкнутые переменные, функция становится грязной - нарушается требование детерминированности:</p>
40
<p>Если замыкание изменяет замкнутые переменные, функция становится грязной - нарушается требование детерминированности:</p>
41
<p>Если замыкание использует изменяемые объекты, функция тоже может быть грязной - возникает побочный эффект:</p>
41
<p>Если замыкание использует изменяемые объекты, функция тоже может быть грязной - возникает побочный эффект:</p>
42
<h2>Выводы</h2>
42
<h2>Выводы</h2>
43
<p>Чистые и грязные функции имеют разные особенности и применения.</p>
43
<p>Чистые и грязные функции имеют разные особенности и применения.</p>
44
<p>Чистые функции являются более предпочтительными. Они проще для понимания и тестирования, а также могут быть использованы в многопоточных приложениях без каких-либо проблем.</p>
44
<p>Чистые функции являются более предпочтительными. Они проще для понимания и тестирования, а также могут быть использованы в многопоточных приложениях без каких-либо проблем.</p>
45
<p>Грязные функции могут быть полезными в некоторых случаях, например, когда нужно изменить состояние программы или выполнить ввод-вывод. Но такие функции могут усложнить отладку и тестирование приложения.</p>
45
<p>Грязные функции могут быть полезными в некоторых случаях, например, когда нужно изменить состояние программы или выполнить ввод-вывод. Но такие функции могут усложнить отладку и тестирование приложения.</p>
46
<p>Рекомендуем использовать чистые функции, когда это возможно. А использование грязных функций лучше ограничить. Их стоит применять только для тех случаев, когда это действительно необходимо.</p>
46
<p>Рекомендуем использовать чистые функции, когда это возможно. А использование грязных функций лучше ограничить. Их стоит применять только для тех случаев, когда это действительно необходимо.</p>