Комментарии 10
Если я могу представить более одного способа, но сейчас будет ровно один, то незачем создавать интерфейс, достаточно класса (или метода класса). Его всегда можно отрефакторить в интерфейс, если появится новый способ.
Моё личное правило гласит, что если вы считаете весьма вероятным возникновение более одного способа реализации — используйте интерфейс. Если вы не считаете, что в будущем будете использовать другие способы — не используйте интерфейс.
В большинстве случаев более или менее опытный разработчик заранее знает, где действительно возможны различные реализации.
Поясню свою мысль: я не знаток PHP и не знаю, как там это происходит, однако во многих других языках рефакторинг класса с вынесением методов в интерфейс потребует правки зависимых классов. Это может быть множество изменений в мерж реквесте, которые на самом деле не несут смысловой нагрузки. В случае, если реализация изначально под интерфейсом, все изменения произойдут лишь в двух местах — место внедрения зависимостей и место создания новой реализации. Никакой из пользовательских классов вообще не будет изменен / затронут. Это сильно облегчает ревью и изучение истории проекта.
Вторая реализация может потребоваться буквально сразу для тестирования. DbProductPricer => InMemMockProductPricer.
— Все классы должны быть final
— Если удается достичь 100% покрытия этого и всех зависимых классов несмотря на final — интерфейс не нужен.
Обычно, увы, такого не получается, поэтому интерфейсы нужны чуть менее, чем всегда.
Чтобы жизнь была проще, в PhpStorm есть Ctrl+T по имени классу и Extract Interface, с галочкой «заменить все использования». Это позволяет ОЧЕНЬ легко проводить рефакторинг старого кода.
Все классы final — значит вообще не используете наследование? Или которые не final — те abstract?
100% покрытие — это так себе цель, как по мне. Кроме красивой цифры практического смысла в ней нет, а времени и сил нужно много.
Тоже недоумеваю, зачем мне знать, что EntityManagerInterface — это именно интерфейс. Это вроде как противоречит самой идее интерфейсов, что мы завязываемся на контракт, а не на конкретную реализацию. Жаль, что в php, да и в ряде других языков, принято это указывать в имени.
А ещё есть pIMPL. Когда реализация ровно одна (и вроде как интерфейс поэтому — лишний). Но при этом детали хочется скрыть.
Правда, ничего не скажу, существует ли это как-то в интерпретируемых языках.
Осмысленные интерфейсы