Были ли случаи, когда вы не соглашались с решением руководства?

Ответ

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

Я подготовил аргументы и альтернативное решение:

  1. Проблемы глобального состояния: сложность тестирования, race conditions в многопоточных средах
  2. Предложил решение: паттерн Registry или простой класс-обертку с статическим доступом
  3. Привел пример кода, показывающий обе реализации

Исходный подход:

// Глобальная переменная
$GLOBALS['config'] = ['db_host' => 'localhost'];

Мое предложение:

class ConfigRegistry {
    private static array $config = [];

    public static function set(string $key, $value): void {
        self::$config[$key] = $value;
    }

    public static function get(string $key) {
        return self::$config[$key] ?? null;
    }
}
// Использование: ConfigRegistry::get('db_host');

В результате обсуждения мы пришли к компромиссу: использовали Dependency Injection контейнер, который решал те же проблемы, но был более стандартным для нашего фреймворка. Руководство оценило техническую аргументацию, и мы внедрили более надежное решение.

Ответ 18+ 🔞

Вот тебе история, от которой волосы дыбом встают, если они ещё остались. Сидим мы, значит, на созвоне, пьём кофе, обсуждаем архитектуру нового сервиса. И тут наш техлидер, чувак в целом адекватный, выдает с таким видом, будто гениальную мысль озвучивает: «А давайте конфиг приложения в глобальный массив засунем! Удобно же!».

Я сижу, слышу это, и у меня в голове, ёпта, тихий ужас начинается. Прямо подозрение ебать чувствую — щас начнётся пиздец. Ну, думаю, бля, сейчас я ему всё объясню, а он мне — «да похуй, работает и ладно».

Собрался, вздохнул и начал вещать, почему это — хуй с горы, а не решение.

Первое, что я вмандюрил: глобальное состояние — это пиздопроебибна для тестов. Представь, один тест подменил конфиг, второй уже на подставных данных работает — и пошла пизда рулю. Искать потом, почему в продакшене всё падает, а в тестах зелёные галочки — это ж на месяц работы.

Второе: race conditions, ёб твою мать. У нас же не сайт-визитка, запросы параллельно летят. Один поток читает, другой в это же время перезаписывает — и привет, хитрая жопа с неконсистентными данными. Доверия к такому коду — ноль ебать.

Ну а чтобы не быть тем пидарасом шерстяным, который только критикует, я сразу альтернативу нарисовал. Говорю: «Слушай, есть же паттерн Registry, или хотя бы класс-обёрточку сделаем. Тот же статический доступ, но уже не всемирная помойка, а контролируемая».

И тут же в чат код кидаю. Смотри, мол, как было:

// Глобальная переменная
$GLOBALS['config'] = ['db_host' => 'localhost'];

А как можно, чтобы и волки были сыты, и овцы целы:

class ConfigRegistry {
    private static array $config = [];

    public static function set(string $key, $value): void {
        self::$config[$key] = $value;
    }

    public static function get(string $key) {
        return self::$config[$key] ?? null;
    }
}
// Использование: ConfigRegistry::get('db_host');

Объясняю: инкапсуляция, чёрт побери! Всё в одном месте, тесты изолировать можно, и ни один левый скрипт не наложит в наш конфиг.

Дискуссия, конечно, была жаркой. Чувак сначала упирался, мол, «работает же, зачем усложнять». Но когда я на живых примерах показал, как это может накрыться медным тазом в проде, он задумался. Видно было — э бошка думай заработала.

В итоге, кстати, пришли не к моему Registry, а к Dependency Injection контейнеру, который в нашем фреймворке уже был. Компромисс, бля, идеальный. И проблемы глобального состояния решили, и стандарты проекта не нарушили.

Руководство потом на ретроспективе отметило, что аргументация была железной. Главное — не просто сказать «это хуйня», а объяснить почему и предложить работающую альтернативу. А то некоторые только «да похуй» говорить умеют, а когда всё ебнется — виноватых ищут.