HTML Diff
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 <p>Сумма страховки зависит от большого числа факторов. Некоторые из факторов могут влиять на сам процесс подсчета стоимости, то есть они изменяют не значения в формуле подсчета, а саму формулу.</p>
3 <p>Сумма страховки зависит от большого числа факторов. Некоторые из факторов могут влиять на сам процесс подсчета стоимости, то есть они изменяют не значения в формуле подсчета, а саму формулу.</p>
4 <p><em>Конкретно в случае страховок, скорее всего есть одна большая формула, куда подставляются значения и вычисление происходит за один заход. Для нас сейчас главное сама концепция, а не точное знание внутренностей страхового бизнеса.</em></p>
4 <p><em>Конкретно в случае страховок, скорее всего есть одна большая формула, куда подставляются значения и вычисление происходит за один заход. Для нас сейчас главное сама концепция, а не точное знание внутренностей страхового бизнеса.</em></p>
5 <p>Если решать эту задачу в лоб, то она будет выглядеть как большое месиво вычислений со множеством условных конструкций. Со временем такой код становится крайне тяжелым для восприятия из-за большого числа состояний, которые надо удерживать в голове.</p>
5 <p>Если решать эту задачу в лоб, то она будет выглядеть как большое месиво вычислений со множеством условных конструкций. Со временем такой код становится крайне тяжелым для восприятия из-за большого числа состояний, которые надо удерживать в голове.</p>
6 <p>Можно ли как-то сделать код понятнее и проще для восприятия? Иногда да. Из всех факторов, участвующих в расчете, нужно попытаться найти те, которые влияют на вычисление глобально. Они проявляются как глобальный if на верхнем уровне. Предположим, что в случае страховки это возраст. То есть считаем, что возраст определяет формулу расчета стоимости страховки. Следующим шагом смотрим на ветки в этой условной конструкции и то, какие диапазоны там указаны. Допустим такую картину:</p>
6 <p>Можно ли как-то сделать код понятнее и проще для восприятия? Иногда да. Из всех факторов, участвующих в расчете, нужно попытаться найти те, которые влияют на вычисление глобально. Они проявляются как глобальный if на верхнем уровне. Предположим, что в случае страховки это возраст. То есть считаем, что возраст определяет формулу расчета стоимости страховки. Следующим шагом смотрим на ветки в этой условной конструкции и то, какие диапазоны там указаны. Допустим такую картину:</p>
7 <ul><li>До 18</li>
7 <ul><li>До 18</li>
8 <li>От 18 до 24</li>
8 <li>От 18 до 24</li>
9 <li>От 24 до 65</li>
9 <li>От 24 до 65</li>
10 <li>Старше 65</li>
10 <li>Старше 65</li>
11 </ul><p>Обратите внимание на важную деталь. Выше мы договорились, что каждая возрастная группа определяет алгоритм расчета стоимости страховки. То есть они между собой независимы, хотя и сам процесс вычисления местами может быть схож (и будет скорее всего).</p>
11 </ul><p>Обратите внимание на важную деталь. Выше мы договорились, что каждая возрастная группа определяет алгоритм расчета стоимости страховки. То есть они между собой независимы, хотя и сам процесс вычисления местами может быть схож (и будет скорее всего).</p>
12 <p>Теперь делаем переход от логической структуры к коду. Каждая возрастная группа - класс, отвечающий за вычисления стоимости для этой группы:</p>
12 <p>Теперь делаем переход от логической структуры к коду. Каждая возрастная группа - класс, отвечающий за вычисления стоимости для этой группы:</p>
13 <p>Главное, что мы получили - разделили процесс вычисления на независимые блоки кода, которые проще для восприятия. Каждый такой класс называется стратегией (вычисления). Очень важно то, что стратегия не является абстракцией, объектом с состоянием и временем жизни объекта. Поэтому данные передаются не в конструктор, а в сам метод. По сути, это обычная функция (вычисление), которая упакована в класс только с одной целью - получить полиморфизм подтипов. Все то же самое можно сделать, используя диспетчеризацию функций по ключам, при этом код будет проще.</p>
13 <p>Главное, что мы получили - разделили процесс вычисления на независимые блоки кода, которые проще для восприятия. Каждый такой класс называется стратегией (вычисления). Очень важно то, что стратегия не является абстракцией, объектом с состоянием и временем жизни объекта. Поэтому данные передаются не в конструктор, а в сам метод. По сути, это обычная функция (вычисление), которая упакована в класс только с одной целью - получить полиморфизм подтипов. Все то же самое можно сделать, используя диспетчеризацию функций по ключам, при этом код будет проще.</p>
14 <p>Дальше возникает вопрос, а каким образом и где выбрать правильную реализацию, с которой нужно работать? Вариантов здесь несколько. Выбор реализации может быть делегирован внешнему коду, то есть если мы применяем инверсию зависимостей, то работаем уже с готовой стратегией:</p>
14 <p>Дальше возникает вопрос, а каким образом и где выбрать правильную реализацию, с которой нужно работать? Вариантов здесь несколько. Выбор реализации может быть делегирован внешнему коду, то есть если мы применяем инверсию зависимостей, то работаем уже с готовой стратегией:</p>
15 <p>Пока мы только ушли от проблемы, но не решили ее. В любом случае, где-то будет код, который содержит либо условную конструкцию, либо реализует один из способов диспетчеризации, которые мы разобрали в предыдущих уроках. В самом простом случае этот код будет выглядеть так:</p>
15 <p>Пока мы только ушли от проблемы, но не решили ее. В любом случае, где-то будет код, который содержит либо условную конструкцию, либо реализует один из способов диспетчеризации, которые мы разобрали в предыдущих уроках. В самом простом случае этот код будет выглядеть так:</p>
16 <p>Как видно по примерам выше, кода с использованием стратегии будет больше, но не так много, если используется диспетчеризация функций по ключам в ассоциативном массиве. Это касается фактически всех ситуаций, в которых задействован полиморфизм подтипов в JavaScript. Это цена, которую придется заплатить за разделение, упрощающее расширение кода и уменьшающее его сложность. С другой стороны, очень легко попасть в ловушку и, наоборот, сделать сложность кода выше, чем она была до внедрения полиморфизма подтипов. Этот полиморфизм делает код многословным и излишне абстрактным, если применять его налево и направо. А расширение нужно не так часто, как об этом говорят. Более того, инвертировать зависимости можно по ходу действия, когда в этом появляется необходимость.</p>
16 <p>Как видно по примерам выше, кода с использованием стратегии будет больше, но не так много, если используется диспетчеризация функций по ключам в ассоциативном массиве. Это касается фактически всех ситуаций, в которых задействован полиморфизм подтипов в JavaScript. Это цена, которую придется заплатить за разделение, упрощающее расширение кода и уменьшающее его сложность. С другой стороны, очень легко попасть в ловушку и, наоборот, сделать сложность кода выше, чем она была до внедрения полиморфизма подтипов. Этот полиморфизм делает код многословным и излишне абстрактным, если применять его налево и направо. А расширение нужно не так часто, как об этом говорят. Более того, инвертировать зависимости можно по ходу действия, когда в этом появляется необходимость.</p>