PHP: Полиморфизм

Теория: Диспетчеризация по ключу (данные)

В связке с полиморфизмом постоянно возникает выражение "динамическая диспетчеризация". С самим понятием мы познакомимся позже, а сейчас поговорим про диспетчеризацию в принципе.

Диспетчеризация (от английского dispatch - отсылать, отправлять) - процесс координации каких-либо действий. Например, диспетчер в аэропорту разводит самолёты, диспетчер в службе такси связывает доступного водителя и клиента.

Рассмотрим условный код, в котором выбор ветки исполнения идёт по конкретному значению переменной:

<?php

if ($env === 'development') {
    $databaseConfiguration = [
        'adapter' => 'sqlite',
    ];
} elseif ($env === 'production') {
    $databaseConfiguration = [
        'adapter' => 'postgresql',
    ];
}

Во всех проектах существует понятие "среда", это то окружение, в котором происходит запуск проекта. Во время разработки код запускают в среде разработчика, её традиционно называют development. Среда, в которой приложение работает по-настоящему, называется production. В зависимости от среды, приложения по-разному стартуют, конфигурируются и даже работают, например в разных средах могут использоваться разные базы данных.

Код выше как раз типичный пример того, как меняется конфигурация в зависимости от среды. Процесс выбора можно назвать процессом диспетчеризации.

Статичная условная конструкция, в которой диспетчеризация идёт по строкам, легко заменяется на свитч. Так код становится понятнее и проще:

<?php

switch ($env) {
    case 'development':
        $databaseConfiguration = [
            'adapter' => 'sqlite',
        ];
        break;
    case 'production':
        $databaseConfiguration = [
            'adapter' => 'postgresql',
        ];
        break;
}

Хотя кода и стало чуть больше, switch сам по себе более явно описывает процесс диспетчеризации. Но можно пойти ещё дальше и сделать диспетчеризацию по ключу ассоциативного массива:

<?php

$databaseSettingsByEnv = [
    'development' => [
        'adapter' => 'sqlite',
    ],
    'production' => [
        'adapter' => 'postgresql',
    ],
];

$databaseConfiguration = $databaseSettingsByEnv[$env];

Значение по умолчанию легко добавить через оператор ??:

<?php

$databaseConfiguration = $databaseSettingsByEnv[$env] ?? [ 'adapter' => 'memory' ];

Этот вариант лучше предыдущих двух сразу по нескольким причинам. Во-первых, он короче, во-вторых, он гибче. Условные конструкции это статичный код, который нельзя поменять без переписывания самой программы в отличие от последнего варианта. А вот данные это совсем другое дело. Для удобства их часто кладут в файлы конфигурации, которые используют формат JSON или YAML, например:

---

development:
  adapter: sqlite

production:
  adapter: postgresql

При таком подходе легко добавить новое поведение без изменения самого кода приложения. Его мощь особенно чувствуется в ситуациях, когда обработкой занимается не наш код, а код библиотеки или фреймворка. Ведь мы не можем просто взять, открыть исходники и поправить их.