Świetnie że jesteś całą branżą i że podajesz przykłady. Ja tam z powodzeniem okazjonalnie zamieniam dziedziczenie na kompozycję i nie widzę problemu. Niedawno nawet zrobiłem dość ekstremalną wersję takiego refaktoru tutaj: https://github.com/tarsa/SortAlgoBox/commit/34ff7f432c6338200c9755815ee7463a62348ecd (to jest projekt hobbystyczny, więc dlatego pozwoliłem sobie załatwić wiele rzeczy jednym commitem). Miałem gotowy kod z lekką eksplozją hierarchii dziedziczenia ("zawrotne" 10 prostych klas w problematycznej hierarchii - tutaj: https://github.com/tarsa/SortAlgoBox/tree/623a8eb3e8877d047fe52f6a4ae52a4c68d5033c/core/main_scala/pl/tarsa/sortalgobox/core/common/agents ), miałem gotowych klientów do tych klas, miałem testy itd, więc miałem co analizować. Po przerobieniu na kompozycję aktualnie kod stał się bardziej skomplikowany niż wcześniej, ale bardziej elastyczny. Dorabianie kolejnych klientów rzadziej będzie wymagać rozbudowywania hierarchii klas. Mimo wszystko gdybym od razu pchał się w kompozycję to kod mógłby się stać niepotrzebnie skomplikowany, bo sposobów na uogólnianie hierarchii dziedziczenia czy kompozycji jest wiele.
Wolę podejście jak w TDD, gdzie logikę tworzy się na bieżąco, bez głębszego zastanawiania się jak kod powinien wyglądać za X-dziesiąt iteracji red-green-refactor, bo im bardziej wybiegamy w przyszłość tym mniej nasze przewidywania się pokrywają z rzeczywistością. U mnie po prostu tworzenie kodu w głowie się nie sprawdza, tak samo u większości innych ludzi i stąd mamy metodyki zwinne, zorientowane na klepanie kodu aktualnie potrzebnego, a nie potrzebnego kiedyś tam. Nie wiem jak u ciebie. Kiedyś miałeś stronkę z własnymi programami, ale chyba się ich wstydzisz. Przykładów też nie podajesz. Co ja mam niby wyciągnąć z twojego biadolenia? Widzisz gdzieś problem, a nie potrafisz go konkretnie opisać.
Reorganizację kodu po jego napisaniu stosuje się też w przypadku mikroserwisów. Najpierw rozbudowuje się istniejący mikroserwis, a potem wydziela z niego osobny, przenosząc do niego już napisany kod (przed wydzieleniem jednak przerabia się kod tak, by zminimalizować złożoność przyszłego API). No chyba, że interfejs mikroserwisu tak czy siak będzie banalny i oczywisty, to wtedy można zacząć od postawienia pustego mikroserwisu.