Вот нашёл я библиотеку, неплохая вроде библиотека, позволяет делать, условно говоря, кофе. Описываешь рецепты, вызываешь $coffeeManager→makeCoffee('espresso')
, и все работает. Но вот незадача — в библиотеке все рецепты кофе хранятся и загружаются из конфиг-файлов (типа .env
). А мне вот хочется, чтобы пользователи могли добавлять свои рецепты, чтобы их было много, чтобы раф с бананом на молоке единорогов, и это вот всё. А хранить их тогда надо в базе данных.
Казалось бы, можно унаследовать класс CoffeeManager
и перегрузить метод загрузки рецептов, чтоб вместо Config::get()
там было обращение к БД. Но вот разработчик хрен пойми зачем объявил класс как final CoffeeManager { …
Зачем? А хер его знает. Прочитал наверное где-то про страшные длинные цепочки наследований и подумал, что это к его библиотеке как-то относится. А до конца не дочитал, подумал — поставлю final и черт с ним, пусть пользуются как я задумал.
И теперь ни перегрузить не получится, ни класс замокать, если мы его интеграцию протестировать захотим.
А всего-то надо было, если душа требует final
, сделать интерфейс, который этот класс реализует, и нормальную вставку зависимостей через этот интерфейс:
final CoffeeManager implements CoffeeManagerInterface {
// ...
}
и тогда я мог бы просто свою реализацию интерфейса написать и в контейнере сервисов подменить.
А без интерфейса — либо свой форк делать, либо другую библиотеку использовать. Не надо так.