Обычно я сталкиваюсь с гораздо большими проблемами обслуживания, связанными с чистыми интерфейсами, чем с ABC, даже с ABC, использующими множественное наследование. YMMV - не знаю, может быть, наша команда просто использовала их неадекватно.
Тем не менее, если мы используем реальную аналогию, насколько полезны чистые интерфейсы, полностью лишенные функциональности и состояния? Если в качестве примера я использую USB, то это достаточно стабильный интерфейс (я думаю, что мы сейчас находимся на USB 3.2, но он также поддерживает обратную совместимость).
Тем не менее, это не интерфейс без состояния. Это не лишено функциональности. Это больше похоже на абстрактный базовый класс, чем на чистый интерфейс. Это на самом деле ближе к конкретному классу с очень конкретными функциональными требованиями и требованиями к состоянию, с единственной абстракцией, которая подключается к порту и является единственной заменяемой частью.
В противном случае это была бы просто «дыра» в вашем компьютере со стандартизированным форм-фактором и гораздо более слабыми функциональными требованиями, которые ничего бы не сделали сами по себе, пока каждый производитель не придумал свое собственное оборудование, чтобы заставить эту дыру что-то делать, и в этот момент он становится гораздо более слабым стандартом и не более чем «дырой» и спецификацией того, что он должен делать, но не является центральным условием того, как это сделать. Между тем у нас может оказаться 200 различных способов сделать это после того, как все производители оборудования попытаются придумать свои собственные способы прикрепления функциональности и состояния к этой «дыре».
И в этот момент у нас могут быть определенные производители, которые создают другие проблемы по сравнению с другими. Если нам нужно обновить спецификацию, у нас может быть 200 различных конкретных реализаций USB-портов с совершенно разными способами решения спецификации, требующей обновления и тестирования. Некоторые производители могут разрабатывать фактические стандартные реализации, которые они разделяют между собой (ваш аналогичный базовый класс, реализующий этот интерфейс), но не все. Некоторые версии могут быть медленнее, чем другие. Некоторые могут иметь лучшую пропускную способность, но худшую задержку или наоборот. Некоторые могут использовать больше энергии аккумулятора, чем другие. Некоторые могут отключиться и не работать со всем оборудованием, которое должно работать с USB-портами. Некоторые могут потребовать подключения к работе ядерного реактора, который имеет тенденцию вызывать радиационное отравление.
И это то, что я нашел лично с чистыми интерфейсами. Могут быть случаи, когда они имеют смысл, например, просто смоделировать форм-фактор материнской платы по сравнению с корпусом процессора. Аналогии форм-фактора, действительно, в значительной степени не содержат состояний и лишены функциональности, как в случае аналогичной «дыры». Но я часто считаю огромной ошибкой для команд считать, что это как-то лучше во всех случаях, даже не близко.
Наоборот, я думаю, что гораздо больше случаев будет решаться лучше с помощью ABC, чем интерфейсов, если это два варианта, если ваша команда не настолько гигантская, что на самом деле желательно иметь аналог, эквивалентный 200 конкурирующим реализациям USB, а не один центральный стандарт для поддерживать. В бывшей команде я был, я на самом деле должен был бороться трудно просто ослабить на стандарт кодирования, чтобы азбуке и множественное наследование, и, главным образом, в ответ на эти проблемы технического обслуживания, описанных выше.