Ответ
Да, был случай на проекте, где технический лидер настаивал на использовании глобального массива для хранения конфигурации приложения. Я считал, что это создаст проблемы с тестируемостью и может привести к трудноуловимым багам при параллельных запросах.
Я подготовил аргументы и альтернативное решение:
- Проблемы глобального состояния: сложность тестирования, 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');
В результате обсуждения мы пришли к компромиссу: использовали 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 контейнеру, который в нашем фреймворке уже был. Компромисс, бля, идеальный. И проблемы глобального состояния решили, и стандарты проекта не нарушили.
Руководство потом на ретроспективе отметило, что аргументация была железной. Главное — не просто сказать «это хуйня», а объяснить почему и предложить работающую альтернативу. А то некоторые только «да похуй» говорить умеют, а когда всё ебнется — виноватых ищут.