Этим летом я занимался проектом, который изменил мое отношение к final-классам.
Суть в том, что в продуктовом проекте N сотен junior-кодеров, и никто не знал значения "dependency injection", не то что SOLID. Коллективно считалось, что DI - это контейнер, потому что пакет Symfony так называется, пришлось workshop со слайдами сделать.
У меня, конечно, порвало шаблон - нафига задирать ФОТ в несколько раз и кормить несколько офисов народа, но бизнес живет.
Мне надо было отпилить кусок от монолита - показать как это, в принципе, делается без переписывания всего кода.
И вот тут я начал называть классы final. Папка Contracts с интерфейсами, рядом папка Api с классами, которые их реализуют, написал у них в phpdoc @api, а во всех остальных - final с пометкой @internal. Чтобы те, кто захочет расширить реализацию, шли #$% сразу, а если надо менять поведение - правьте код.
Кстати, заметил интересный момент - народ до ужаса боится скопировать код. Даже 10 строк, даже когда разный execution flow и разные типы данных. Причины не знают - суеверный страх, как черных кошек. Говорю, в DRY нет ни слова про код, там про execution flow - стеклянный религиозный взгляд.