Сегодня в свободное время решил немного поработать над своим HTTP-клиентом и добавить возможность задавать конфигурацию.
Сначала я пошёл, казалось бы, очевидным путём — хотел вынести настройки в `config.json`.
Но когда начал это реализовывать, столкнулся с противоречиями.
Откуда библиотека должна брать этот файл? Зависеть от директории проекта? А где вообще эта директория в конкретном приложении? Насколько удобно пользователю каждый раз думать, где должен лежать `config.json`? А как всё это нормально поддерживать внутри Composer-пакета?
В какой-то момент пришёл к мысли, что для библиотеки такой подход вообще не нужен.
Ценность пакета как раз в том, чтобы получить готовый функционал с минимальным количеством дополнительных действий. А если после установки нужно ещё разбираться с каким-то конфигурационным файлом, который библиотека должна самостоятельно искать, то получается лишняя сложность.
Поэтому от `config.json` отказался.
Следующая идея — обычные getter и setter.
Реализовал их и уже собирался на этом остановиться, как вдруг IDE подсказала одну интересную вещь: раз пакет требует PHP 8.5, зачем вообще писать весь этот boilerplate?
Я вспомнил про `get` / `set` property hooks, которые появились в PHP 8.4.
Честно говоря, я просто забыл про эту возможность. Когда читал описание PHP 8.4, видел про property hooks, но на практике ни разу их не использовал.
В итоге вместо набора `getTimeout()`, `setTimeout()`, `getConnectTimeout()` и так далее получилась гораздо более компактная конструкция:
$config->timeout = 60;
$config->connectTimeout = 10;
При этом в `set` hook можно оставить необходимую валидацию.
Получилось красиво, минимально и, на мой взгляд, гораздо удобнее в поддержке.
Но на этом мозговой штурм не закончился.
Появилась вторая задача: я хотел, чтобы `User-Agent` всегда содержал идентификатор моего клиента. Его можно получить, но я не хочу, чтобы пользователь библиотеки мог его изменить.
И тут на помощь пришло ещё одно «чудо» из PHP 8.4 — асимметричная видимость.
В итоге можно сделать свойство публичным для чтения, но закрыть запись:
public private(set) string $userAgent = 'alf89/http-client/0.2.1';
И вот в результате обычная задача «добавить конфигурацию» привела меня сразу к двум современным возможностям PHP, которыми я раньше практически не пользовался.
В очередной раз убедился, что иногда полезно не сразу писать код, а немного остановиться и подумать: а точно ли старый привычный подход здесь лучший?
Так что `property hooks` и асимметричную видимость я точно беру себе на вооружение. Думаю, и дальше буду искать им применение там, где они действительно упрощают код.
Сначала я пошёл, казалось бы, очевидным путём — хотел вынести настройки в `config.json`.
Но когда начал это реализовывать, столкнулся с противоречиями.
Откуда библиотека должна брать этот файл? Зависеть от директории проекта? А где вообще эта директория в конкретном приложении? Насколько удобно пользователю каждый раз думать, где должен лежать `config.json`? А как всё это нормально поддерживать внутри Composer-пакета?
В какой-то момент пришёл к мысли, что для библиотеки такой подход вообще не нужен.
Ценность пакета как раз в том, чтобы получить готовый функционал с минимальным количеством дополнительных действий. А если после установки нужно ещё разбираться с каким-то конфигурационным файлом, который библиотека должна самостоятельно искать, то получается лишняя сложность.
Поэтому от `config.json` отказался.
Следующая идея — обычные getter и setter.
Реализовал их и уже собирался на этом остановиться, как вдруг IDE подсказала одну интересную вещь: раз пакет требует PHP 8.5, зачем вообще писать весь этот boilerplate?
Я вспомнил про `get` / `set` property hooks, которые появились в PHP 8.4.
Честно говоря, я просто забыл про эту возможность. Когда читал описание PHP 8.4, видел про property hooks, но на практике ни разу их не использовал.
В итоге вместо набора `getTimeout()`, `setTimeout()`, `getConnectTimeout()` и так далее получилась гораздо более компактная конструкция:
$config->timeout = 60;
$config->connectTimeout = 10;
При этом в `set` hook можно оставить необходимую валидацию.
Получилось красиво, минимально и, на мой взгляд, гораздо удобнее в поддержке.
Но на этом мозговой штурм не закончился.
Появилась вторая задача: я хотел, чтобы `User-Agent` всегда содержал идентификатор моего клиента. Его можно получить, но я не хочу, чтобы пользователь библиотеки мог его изменить.
И тут на помощь пришло ещё одно «чудо» из PHP 8.4 — асимметричная видимость.
В итоге можно сделать свойство публичным для чтения, но закрыть запись:
public private(set) string $userAgent = 'alf89/http-client/0.2.1';
И вот в результате обычная задача «добавить конфигурацию» привела меня сразу к двум современным возможностям PHP, которыми я раньше практически не пользовался.
В очередной раз убедился, что иногда полезно не сразу писать код, а немного остановиться и подумать: а точно ли старый привычный подход здесь лучший?
Так что `property hooks` и асимметричную видимость я точно беру себе на вооружение. Думаю, и дальше буду искать им применение там, где они действительно упрощают код.
Просмотры: 23