50 оттенков геморроя: константы и переменные в PHP

Я ненавижу константы в PHP. Когда мне случайно попадается файлик конфигурации проекта, в котором на три страницы перечислены константы с параметрами, мне хочется оторвать руки автору и пришить их в правильное место. Но давайте разберёмся, почему я их так не люблю.

Константы несут зло даже в самом своём названии: constantem (лат.) – постоянный. Однако мы с вами знаем, что единственное бывает постоянным в любом проекте:

Изменения.

Проект умрёт, если не будет готов к изменениям. Изменения – это главное, что движет вас вперёд. Неизменные проекты существуют где-то там же, где и абсолютно точная постановка задач и всеобъемлющие технические задания – где-то в юношеских фантазиях начинающих разработчиков.

Поэтому каждый раз, когда вы пишете конфигурационный файлик с константами, вы забиваете гвоздь в крышку гроба проекта. Потребовалось организовать девелоперскую копию в ином окружении? У вас будет геморрой. Потребовалось реорганизовать пути к расположению файлов? Геморрой. Сделать разные пароли к dev-stage-prod базам данных? Геморрой Запустить тесты, подменив обращение к внешним сервисам – на внутренние заглушки? Геморрой. Вместо одного элемента теперь требуется хранить список, массив? Геморрой. Расширить конфигурационные файлы, добавив что-то уникальное независимо для каждого окружения? Технически невозможно.

Мировая общественность в своё время допёрла до очевидного факта, что глобалсы – зло. А вот сделать следующий шаг и выкинуть константы на%уй – пока никто даже не пикнул.

Хорошо, но причём здесь переменные? – спросите Вы. А вот сейчас объясню, но прежде этого – убедитесь, что вы прониклись предыдущими абзацами: упоминание в коде константы – можно представить как вставку прямой ссылки на значение, которое хранится где-то в памяти. Запомните на минуту фразу, выделенную курсивом, и едем дальше.

Итак, почему переменные – тоже зло. Речь, конечно же, не о глобальных переменных. Я говорю про простые и безобидные переменные классов, которые вовсе даже не статические и не публичые. Короче, нормальные такие переменные.

И тут вы пишете:

class myClass {
protected $parameter;
// ...
function doSomething() {
  // бла-бла, какой-то код до того как
  $a = ucfirst($this->parameter) . " some text";
  // бла-бла, какой-то код после того как
}

Внимательно вглядитесь в этот $this->parameter, а затем переведите взгляд выше, на фразу которая была выделена курсивом. Нужно ли ещё что-то объяснять?

Каждый раз, когда вы используете в своём коде прямые ссылки на значение (неважно, константы или переменные), это так же smells bad, как если бы вы хардкодили строки, урлы, емайлы и другие значения прямо в исполняемом коде. Вы ведь скорее отрубите себе пальцы, чем сделаете так, верно? Но в то же время, вы радостно заменяете что-то вроде строки “[email protected]” на $this->support_email и радостно идёте пить пиво. А зря.

Как надо делать:

Во-первых, боже упаси, никаких констант в конфигурации. Некоторые делают конфигурационные массивы (как в Yii), их вроде как можно перехватить и дописать/переопределить значения, но неочевидно и имеет явный привкус проблем.

Во-вторых, познакомьтесь с тем что делает Symfony с конфигурационными файлами в формате YML. Они очень изящно “из коробки” расширяются, накладывая уникальные значения поверх дефолтных. Вполне годное решение для работы проекта в разных окружениях.

В-третьих, если вас так прёт писать $this->parameter, объявите такие переменные с подчёркиванием ($_parameter) и добавьте универсальный геттер и сеттер. Теперь любое обращение к ним вы сможете легко перехватить.

Кроме того, очень хорошо вправляет мозги изучение основ Ruby, JavaScript и Erlang. Например на Ruby, если с самого начала использовать его правильно, каждая “переменная” – это функция, код которой исполняется в момент обращения к этой переменной. То есть – как сказано выше – его всегда можно перехватить, переопределить, расширить, поставить в зависимость от внешних условий и так далее.

А в Erlang буквально на первых страницах документации, где-то на уровне “как посчитать 2+2”, так прямо и написано: все проблемы от того, что значения переменных неконтролируемо меняются где-то в коде программы, и работа программиста при дебаге на 99% состоит в том, чтобы определить где и какое. Вспомните эту мысль, когда в очередной раз будете расставлять вардампы на продакшене )