HTML Diff
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>