0 added
0 removed
Original
2026-01-01
Modified
2026-02-26
1
<p>Функции в программировании обладают рядом важных характеристик. Зная их, мы можем точнее определять, как лучше разбивать код на функции и когда вообще их стоит выделять.</p>
1
<p>Функции в программировании обладают рядом важных характеристик. Зная их, мы можем точнее определять, как лучше разбивать код на функции и когда вообще их стоит выделять.</p>
2
<h2>Детерминированность</h2>
2
<h2>Детерминированность</h2>
3
<p>Встроенная в JavaScript функция<a>Math.random()</a>возвращает случайное число от<em>0</em>до<em>1</em>:</p>
3
<p>Встроенная в JavaScript функция<a>Math.random()</a>возвращает случайное число от<em>0</em>до<em>1</em>:</p>
4
<p>Функция нужная и полезная, но неудобная в отладке и тестировании. Это связано с тем, что для одних и тех же входных аргументов (отсутствие аргументов также попадает под это понятие), она может возвращать разные значения. Функции с таким поведением называются недетерминированными.</p>
4
<p>Функция нужная и полезная, но неудобная в отладке и тестировании. Это связано с тем, что для одних и тех же входных аргументов (отсутствие аргументов также попадает под это понятие), она может возвращать разные значения. Функции с таким поведением называются недетерминированными.</p>
5
<p>Например, недетерминированными являются функции, оперирующие системным временем. Так, функция<a>Date.now()</a>каждый раз возвращает новое значение:</p>
5
<p>Например, недетерминированными являются функции, оперирующие системным временем. Так, функция<a>Date.now()</a>каждый раз возвращает новое значение:</p>
6
<p>А вот пример с аргументами. Представьте функцию getAge(), которая принимает на вход год рождения и возвращает возраст:</p>
6
<p>А вот пример с аргументами. Представьте функцию getAge(), которая принимает на вход год рождения и возвращает возраст:</p>
7
<p>Хотя прямо сейчас повторный запуск вернёт точно такое же значение, через год оно уже будет другим. То есть функция считается недетерминированной, если она ведёт себя так хотя бы единожды.</p>
7
<p>Хотя прямо сейчас повторный запуск вернёт точно такое же значение, через год оно уже будет другим. То есть функция считается недетерминированной, если она ведёт себя так хотя бы единожды.</p>
8
<p>Детерминированные функции, напротив, ведут себя предсказуемо. Для одних и тех же входных данных они всегда выдают один и тот же результат. Именно такими являются функции в математике.</p>
8
<p>Детерминированные функции, напротив, ведут себя предсказуемо. Для одних и тех же входных данных они всегда выдают один и тот же результат. Именно такими являются функции в математике.</p>
9
<p>Интересно что, например, функция console.log() - детерминированная. Дело в том, что она всегда возвращает одно и то же значение для любых входных данных. Это значение undefined, а не то, что печатается на экран, как можно было бы подумать. Печать на экран - побочный эффект, о нём мы поговорим чуть позже.</p>
9
<p>Интересно что, например, функция console.log() - детерминированная. Дело в том, что она всегда возвращает одно и то же значение для любых входных данных. Это значение undefined, а не то, что печатается на экран, как можно было бы подумать. Печать на экран - побочный эффект, о нём мы поговорим чуть позже.</p>
10
<p>Вызов console.log('Hexlet - Big Bang') выполнил два действия:</p>
10
<p>Вызов console.log('Hexlet - Big Bang') выполнил два действия:</p>
11
<ul><li>Вывел сообщение<em>Hexlet - Big Bang</em>в терминал (или консоль браузера, в зависимости от среды выполнения)</li>
11
<ul><li>Вывел сообщение<em>Hexlet - Big Bang</em>в терминал (или консоль браузера, в зависимости от среды выполнения)</li>
12
<li>Вернул значение undefined. Какое сообщение бы мы ни печатали, возвращаемое значение всегда будет одно - undefined</li>
12
<li>Вернул значение undefined. Какое сообщение бы мы ни печатали, возвращаемое значение всегда будет одно - undefined</li>
13
</ul><p>Функция становится недетерминированной и в том случае, если она обращается не только к своим аргументам, но и некоторым внешним данным, например глобальным переменным, переменным окружения и так далее. Так происходит потому, что внешние данные могут измениться, и функция начнёт выдавать другой результат, даже если в неё передаются одни и те же аргументы.</p>
13
</ul><p>Функция становится недетерминированной и в том случае, если она обращается не только к своим аргументам, но и некоторым внешним данным, например глобальным переменным, переменным окружения и так далее. Так происходит потому, что внешние данные могут измениться, и функция начнёт выдавать другой результат, даже если в неё передаются одни и те же аргументы.</p>
14
<p>Функция getCurrentShell() обращается к переменной окружения SHELL. Но в разные моменты времени и в разных окружениях значение этой переменной может быть различным.</p>
14
<p>Функция getCurrentShell() обращается к переменной окружения SHELL. Но в разные моменты времени и в разных окружениях значение этой переменной может быть различным.</p>
15
<p>В общем случае нельзя сказать, что отсутствие детерминированности - абсолютное зло. Для работы многих программ и сайтов нужна функция, возвращающая случайное число или вычисляющая текущую дату. С другой стороны, в нашей власти разделить код так, чтобы в нем было как можно больше детерминированных частей. Общая рекомендация при работе с детерминированностью звучит следующим образом: если есть возможность написать функцию так, что она будет детерминированной, то так и делайте. Не используйте глобальных переменных, создавайте функции, зависящие только от своих собственных аргументов.</p>
15
<p>В общем случае нельзя сказать, что отсутствие детерминированности - абсолютное зло. Для работы многих программ и сайтов нужна функция, возвращающая случайное число или вычисляющая текущую дату. С другой стороны, в нашей власти разделить код так, чтобы в нем было как можно больше детерминированных частей. Общая рекомендация при работе с детерминированностью звучит следующим образом: если есть возможность написать функцию так, что она будет детерминированной, то так и делайте. Не используйте глобальных переменных, создавайте функции, зависящие только от своих собственных аргументов.</p>
16
<p>Понятие "Детерминированность" не ограничивается программированием или математикой. Сквозь него можно рассматривать практически любой процесс. Например, подбрасывание монетки - недетерминированный процесс, его результат случаен.</p>
16
<p>Понятие "Детерминированность" не ограничивается программированием или математикой. Сквозь него можно рассматривать практически любой процесс. Например, подбрасывание монетки - недетерминированный процесс, его результат случаен.</p>
17
<h2>Побочные эффекты (side effects)</h2>
17
<h2>Побочные эффекты (side effects)</h2>
18
<p>Вторая ключевая характеристика функций - наличие побочных эффектов. Побочными эффектами называют любые взаимодействия с внешней средой. К ним относятся файловые операции, такие как запись в файл, чтение файла, отправка или приём данных по сети и даже вывод в консоль.</p>
18
<p>Вторая ключевая характеристика функций - наличие побочных эффектов. Побочными эффектами называют любые взаимодействия с внешней средой. К ним относятся файловые операции, такие как запись в файл, чтение файла, отправка или приём данных по сети и даже вывод в консоль.</p>
19
<p>Кроме того, побочными эффектами считаются изменения внешних переменных (например, глобальных) и входных параметров в случае, когда они передаются по ссылке.</p>
19
<p>Кроме того, побочными эффектами считаются изменения внешних переменных (например, глобальных) и входных параметров в случае, когда они передаются по ссылке.</p>
20
<p>А вот вычисления (логика), напротив, не содержат побочных эффектов. Например, функция, суммирующая два переданных аргументами числа.</p>
20
<p>А вот вычисления (логика), напротив, не содержат побочных эффектов. Например, функция, суммирующая два переданных аргументами числа.</p>
21
<p>Побочные эффекты составляют одну из самых больших сложностей при разработке. Их наличие значительно затрудняет логику кода и тестирование. Приводит к возникновению огромного числа ошибок. Только при работе с файлами количество возможных ошибок измеряется сотней: начиная с того, что закончилось место на диске, заканчивая попыткой читать данные из несуществующего файла. Для их предотвращения код обрастает большим числом проверок и защитных механизмов.</p>
21
<p>Побочные эффекты составляют одну из самых больших сложностей при разработке. Их наличие значительно затрудняет логику кода и тестирование. Приводит к возникновению огромного числа ошибок. Только при работе с файлами количество возможных ошибок измеряется сотней: начиная с того, что закончилось место на диске, заканчивая попыткой читать данные из несуществующего файла. Для их предотвращения код обрастает большим числом проверок и защитных механизмов.</p>
22
<p>Без побочных эффектов невозможно написать ни одной полезной программы. Какие бы важные вычисления она ни делала, их результат должен быть как-то продемонстрирован. В самом простом случае его нужно вывести на экран, что автоматически приводит нас к побочным эффектам:</p>
22
<p>Без побочных эффектов невозможно написать ни одной полезной программы. Какие бы важные вычисления она ни делала, их результат должен быть как-то продемонстрирован. В самом простом случае его нужно вывести на экран, что автоматически приводит нас к побочным эффектам:</p>
23
<p>В реальных же приложениях, обычно, все сводится к взаимодействию с базой данных или отправкой запросов по сети.</p>
23
<p>В реальных же приложениях, обычно, все сводится к взаимодействию с базой данных или отправкой запросов по сети.</p>
24
<p>Не существует способа избавиться от побочных эффектов совсем, но их влияние на программу можно минимизировать. Как правило, в типичной программе побочных эффектов не так много по отношению к остальному коду, и происходят они лишь в самом начале и в конце. Например, программа, которая конвертирует файл из текстового формата в PDF, в идеале выполняет ровно два побочных эффекта:</p>
24
<p>Не существует способа избавиться от побочных эффектов совсем, но их влияние на программу можно минимизировать. Как правило, в типичной программе побочных эффектов не так много по отношению к остальному коду, и происходят они лишь в самом начале и в конце. Например, программа, которая конвертирует файл из текстового формата в PDF, в идеале выполняет ровно два побочных эффекта:</p>
25
<ol><li>Читает файл в самом начале работы программы.</li>
25
<ol><li>Читает файл в самом начале работы программы.</li>
26
<li>Записывает результат работы программы в новый файл.</li>
26
<li>Записывает результат работы программы в новый файл.</li>
27
</ol><p>Между этими двумя пунктами и происходит основная работа, которая содержит чистую алгоритмическую часть. Побочные эффекты в таком случае будут находиться только в верхнем слое приложения, а ядро, выполняющее основную работу, останется чистым от них.</p>
27
</ol><p>Между этими двумя пунктами и происходит основная работа, которая содержит чистую алгоритмическую часть. Побочные эффекты в таком случае будут находиться только в верхнем слое приложения, а ядро, выполняющее основную работу, останется чистым от них.</p>
28
<p><em>Инкремент и декремент - единственные базовые арифметические операции в JS, которые обладают побочными эффектами (изменяют само значение в переменной). Именно поэтому с ними сложно работать в составных выражениях. Они могут приводить к таким сложноотлавливаемым ошибкам, что во многих языках вообще отказались от их введения (в Ruby и Python их нет). В JS<a>стандарты кодирования</a>предписывают их не использовать.</em></p>
28
<p><em>Инкремент и декремент - единственные базовые арифметические операции в JS, которые обладают побочными эффектами (изменяют само значение в переменной). Именно поэтому с ними сложно работать в составных выражениях. Они могут приводить к таким сложноотлавливаемым ошибкам, что во многих языках вообще отказались от их введения (в Ruby и Python их нет). В JS<a>стандарты кодирования</a>предписывают их не использовать.</em></p>
29
<h2>Чистые функции</h2>
29
<h2>Чистые функции</h2>
30
<p>Идеальная функция с точки зрения удобства работы с ней называется чистой (pure). Чистая функция - это детерминированная функция, которая не производит побочных эффектов. Такая функция зависит только от своих входных аргументов и всегда ведёт себя предсказуемо.</p>
30
<p>Идеальная функция с точки зрения удобства работы с ней называется чистой (pure). Чистая функция - это детерминированная функция, которая не производит побочных эффектов. Такая функция зависит только от своих входных аргументов и всегда ведёт себя предсказуемо.</p>
31
<p>Чистые функции обладают рядом ключевых достоинств:</p>
31
<p>Чистые функции обладают рядом ключевых достоинств:</p>
32
<ul><li>Их просто тестировать. Достаточно передать на вход функции нужные параметры и посмотреть ожидаемый выход.</li>
32
<ul><li>Их просто тестировать. Достаточно передать на вход функции нужные параметры и посмотреть ожидаемый выход.</li>
33
<li>Их безопасно запускать повторно, что особенно актуально в асинхронном коде или в случае многопоточного кода.</li>
33
<li>Их безопасно запускать повторно, что особенно актуально в асинхронном коде или в случае многопоточного кода.</li>
34
<li>Их легко комбинировать, получая новое поведение без необходимости переписывать программу (подробнее далее по курсу).</li>
34
<li>Их легко комбинировать, получая новое поведение без необходимости переписывать программу (подробнее далее по курсу).</li>
35
</ul><p>В хорошо спроектированных программах побочные эффекты стараются изолировать в небольшой части приложения так, чтобы большая часть кода была чистой.</p>
35
</ul><p>В хорошо спроектированных программах побочные эффекты стараются изолировать в небольшой части приложения так, чтобы большая часть кода была чистой.</p>
36
<p>Прямо сейчас сказанное выше может звучать довольно абстрактно. Осознание этой темы требует не только общего понимания прочитанного, но и набитых шишек, связанных со сложностью работы в мешанине побочных эффектов. Тему чистоты мы будем поднимать регулярно. Особенно сильно она прорабатывается в проектах, на живом коде.</p>
36
<p>Прямо сейчас сказанное выше может звучать довольно абстрактно. Осознание этой темы требует не только общего понимания прочитанного, но и набитых шишек, связанных со сложностью работы в мешанине побочных эффектов. Тему чистоты мы будем поднимать регулярно. Особенно сильно она прорабатывается в проектах, на живом коде.</p>