0 added
0 removed
Original
2026-01-01
Modified
2026-02-26
1
<p>Многие объекты в ООП не являются абстракцией данных, а используются как способ сохранить конфигурацию для выполнения повторяющихся действий, таких как генерация HTML из Markdown или определение города по IP. Конфигурация осуществляется через передачу опций в конструктор объекта, а сами опции хранятся внутри и используются для всех последующих вызовов.</p>
1
<p>Многие объекты в ООП не являются абстракцией данных, а используются как способ сохранить конфигурацию для выполнения повторяющихся действий, таких как генерация HTML из Markdown или определение города по IP. Конфигурация осуществляется через передачу опций в конструктор объекта, а сами опции хранятся внутри и используются для всех последующих вызовов.</p>
2
<p>Но что, если для конкретного запроса нужно временно установить опции, отличные от тех, что были переданы в конструктор? В этом уроке мы рассмотрим способы временно изменять эту конфигурацию для конкретного вызова.</p>
2
<p>Но что, если для конкретного запроса нужно временно установить опции, отличные от тех, что были переданы в конструктор? В этом уроке мы рассмотрим способы временно изменять эту конфигурацию для конкретного вызова.</p>
3
<h2>Создание нового объекта</h2>
3
<h2>Создание нового объекта</h2>
4
<p>Мы можем создать новый объект с нужной нам конфигурацией там, где это требуется:</p>
4
<p>Мы можем создать новый объект с нужной нам конфигурацией там, где это требуется:</p>
5
<p>Здесь мы создаем новый объект Request с новым параметром таймаута. Затем выполняется HTTP GET-запрос на http://example.com с использованием этого объекта.</p>
5
<p>Здесь мы создаем новый объект Request с новым параметром таймаута. Затем выполняется HTTP GET-запрос на http://example.com с использованием этого объекта.</p>
6
<p>Это простое решение. Но у него есть ряд недостатков. Главный недостаток - невозможно подменить реализацию, так как объект создается не на этапе конфигурирования системы, а в том месте, где происходит вызов. Из-за этого придется дублировать общие опции, а тестирование станет затруднительным или невозможным.</p>
6
<p>Это простое решение. Но у него есть ряд недостатков. Главный недостаток - невозможно подменить реализацию, так как объект создается не на этапе конфигурирования системы, а в том месте, где происходит вызов. Из-за этого придется дублировать общие опции, а тестирование станет затруднительным или невозможным.</p>
7
<p>Здесь речь идет про тот самый полиморфизм, о котором мы будем говорить в будущем.</p>
7
<p>Здесь речь идет про тот самый полиморфизм, о котором мы будем говорить в будущем.</p>
8
<p>Теперь рассмотрим следующий способ.</p>
8
<p>Теперь рассмотрим следующий способ.</p>
9
<h2>Использование сеттеров</h2>
9
<h2>Использование сеттеров</h2>
10
<p>Следующий подход включает использование сеттеров, что позволяет изменять опции уже существующего объекта:</p>
10
<p>Следующий подход включает использование сеттеров, что позволяет изменять опции уже существующего объекта:</p>
11
<p>В данном случае мы начинаем с того же объекта Request, что и в предыдущем примере. Но теперь мы используем сеттер set_timeout(), чтобы изменить таймаут с одной до десяти секунд для этого объекта. Затем мы снова выполняем GET-запрос, и этот запрос теперь будет использовать новое значение таймаута.</p>
11
<p>В данном случае мы начинаем с того же объекта Request, что и в предыдущем примере. Но теперь мы используем сеттер set_timeout(), чтобы изменить таймаут с одной до десяти секунд для этого объекта. Затем мы снова выполняем GET-запрос, и этот запрос теперь будет использовать новое значение таймаута.</p>
12
<p>Изменяемое состояние - это одна из самых сложных концепций в программировании. Именно оно может привести к большинству проблем, с которыми сталкиваются программисты. Оно может создать трудноуловимые и опасные баги.</p>
12
<p>Изменяемое состояние - это одна из самых сложных концепций в программировании. Именно оно может привести к большинству проблем, с которыми сталкиваются программисты. Оно может создать трудноуловимые и опасные баги.</p>
13
<p>Объект request используется совместно всеми частями системы. Это означает, что его изменение в одном месте повлияет на все последующие вызовы.</p>
13
<p>Объект request используется совместно всеми частями системы. Это означает, что его изменение в одном месте повлияет на все последующие вызовы.</p>
14
<p>В реальной жизни такие вещи могут приводить к еще более серьезным последствиям. Допустим, мы работаем с классом MarkdownRenderer, который отвечает за рендеринг markdown в HTML. Этот класс имеет опцию sanitize, которая отвечает за включение или отключение безопасного рендеринга.</p>
14
<p>В реальной жизни такие вещи могут приводить к еще более серьезным последствиям. Допустим, мы работаем с классом MarkdownRenderer, который отвечает за рендеринг markdown в HTML. Этот класс имеет опцию sanitize, которая отвечает за включение или отключение безопасного рендеринга.</p>
15
<p>Если мы случайно отключим эту опцию, то теги <script>, вставленные в Markdown, отобразятся как есть. Это может быть допустимо для текста, который мы контролируем, например, для уроков на нашем сайте. Но это недопустимо для текста, введенного пользователями. Изменение опции sanitize в объекте MarkdownRenderer может создать уязвимость для<a>межсайтового скриптинга (XSS)</a>.</p>
15
<p>Если мы случайно отключим эту опцию, то теги <script>, вставленные в Markdown, отобразятся как есть. Это может быть допустимо для текста, который мы контролируем, например, для уроков на нашем сайте. Но это недопустимо для текста, введенного пользователями. Изменение опции sanitize в объекте MarkdownRenderer может создать уязвимость для<a>межсайтового скриптинга (XSS)</a>.</p>
16
<p>Чтобы избежать этого, мы можем попытаться вернуть опцию обратно после того, как мы ее изменили:</p>
16
<p>Чтобы избежать этого, мы можем попытаться вернуть опцию обратно после того, как мы ее изменили:</p>
17
<p>При этом программист может забыть это сделать. Код, в котором сначала что-то меняется в одну сторону, а затем возвращается обратно, почти всегда указывает на проблемы архитектуры. И существуют способы переписать его более безопасным образом.</p>
17
<p>При этом программист может забыть это сделать. Код, в котором сначала что-то меняется в одну сторону, а затем возвращается обратно, почти всегда указывает на проблемы архитектуры. И существуют способы переписать его более безопасным образом.</p>
18
<h2>Передача опций при каждом вызове</h2>
18
<h2>Передача опций при каждом вызове</h2>
19
<p>Лучшим решением данной проблемы может быть передача дополнительных параметров при каждом вызове метода:</p>
19
<p>Лучшим решением данной проблемы может быть передача дополнительных параметров при каждом вызове метода:</p>
20
<p>В данном случае во втором вызове метода get мы передаем дополнительный параметр timeout со значением 10. Это изменение затрагивает только данный вызов, а не весь объект request.</p>
20
<p>В данном случае во втором вызове метода get мы передаем дополнительный параметр timeout со значением 10. Это изменение затрагивает только данный вызов, а не весь объект request.</p>
21
<p>Таким образом, когда мы возвращаемся к третьему вызову метода get, первоначальное значение timeout (1) остается неизменным. Это предотвращает возможные проблемы, связанные с изменением состояния объекта. Еще это позволяет гибко управлять настройками для каждого вызова.</p>
21
<p>Таким образом, когда мы возвращаемся к третьему вызову метода get, первоначальное значение timeout (1) остается неизменным. Это предотвращает возможные проблемы, связанные с изменением состояния объекта. Еще это позволяет гибко управлять настройками для каждого вызова.</p>
22
<h2>Выводы</h2>
22
<h2>Выводы</h2>
23
<p>В этом уроке мы обсудили различные подходы к управлению настройками объекта: от создания нового объекта до использования сеттеров и передачи дополнительных параметров при каждом вызове метода. Передача опций при каждом вызове - наиболее предпочтительный подход, так как он избегает проблем, связанных с изменяемым состоянием, и позволяет сохранять гибкость кода.</p>
23
<p>В этом уроке мы обсудили различные подходы к управлению настройками объекта: от создания нового объекта до использования сеттеров и передачи дополнительных параметров при каждом вызове метода. Передача опций при каждом вызове - наиболее предпочтительный подход, так как он избегает проблем, связанных с изменяемым состоянием, и позволяет сохранять гибкость кода.</p>