@Krolik:
@EgonOlsen:
Krolik napisał(a)
Żądanie dowodów w dziedzinie, która nie jest dziedziną ścisłą (jak inżynieria oprogramowania), to tak jak żądanie dowodów teorii ekonomicznych albo socjologicznych
Ale dodajmy: to nie znaczy, że żądanie dowodów w potocznym znaczeniu tego słowa jest tu bezcelowe. Bo nie musi chodzić o dowody formalne. Potocznie, dowodem może być zwykłe wyjaśnienie. Choćby takie jakie przedstawiłeś w dalszej części posta. Dowodem mogą być wyniki jakichś badań.
Nie będą to formalne dowody pokazujące, że coś działa na 100% w 100% przypadków. Niemniej jednak takie wyjaśnienia, wskazówki, argumenty są bardzo przydatne.
Tutaj wystarczy chyba powiedzieć, że dobry kod jest skalowalny, łatwo poddaje się zmianom. Łatwość oznacza tutaj, że dodanie nowego elementu (metody, klasy) wymaga zmian w możliwie najmniejszej liczbie fragmentów kodu.
Można mieć nadzieję, że doświadczeni programiści rozumieją powyższe stwierdzenia i zgadzają się z nimi. A jeśli ktoś powie, że nie, to można mu któreś z tych stwierdzeń rozwinąć.
Zakładając więc prawdziwość powyższych stwierdzeń możemy powiedzieć, że użycie dziedziczenia powoduje, że łatwe jest dodawanie nowych typów, bo większość kodu operuje na abstrakcjach (nadklasach/interfejsach) i jest niezależna od konkretnego typu. Za to dodawanie nowych metod jest trudne, bo trzeba zmienić interfejs abstrakcji, a to wymaga zmian w wielu klasach konkretnych.
Po drugiej stronie mamy kod proceduralny, korzystający z klas bardziej jak ze struktur danych. Taki kod nie korzysta z możliwości, jakie daje OO. Bardziej zorientowany jest na wywoływanie funkcji. Być może metod, ale bez polegania na polimorfizmie. Zamiast tego kod taki polega bardziej na programowaniu strukturalnym -- przynajmniej w tym sensie, że dość często widzimy tam switche (które w programowaniu OO byłoby zastąpione dziedziczeniem, polimorfizmem).
W takim kodzie proceduralnym dodanie nowej funkcji jest łatwe. Trzeba dodać funkcję. W niej walnąć switcha, żeby wykonywała różną operację w zależności od tego, jaki obiekt dostała (można użyć instanceof zamiast switcha -- to to samo). I tyle.
Ale za to dodanie nowej struktury to prawdziwy ból. Trzeba zmienić wszystkie switche (ciągi instanceof) we wszystkich "procedurach"!
W kodzie polimorficznym, OO, jest odwrotnie. Dodaj nową funkcję, a musisz zmienić wszystkie klasy. Ale dodawanie nowego typu polega na napisaniu jednej podklasy i ew. podpięcie jej do jakiejś fabryki. I tyle. Nie trzeba skakać po procedurach, by dodać do każdego switcha nowy typ.
Także coś za coś. Kod OO nie jest idealny i trzeba to mieć na uwadze.
Co do samego problemu, jaki miał @koru, to czasem da się tych instanceofów jednak uniknąć. Trzeba by jednak przeanalizować sporą część systemu. Ustalić skąd pochodzą te klasy, które trzeba sprawdzać instanceofem. Dowiedzieć się, jakie dane są niezbędne do przetworzenia żądania i od jakich obiektów one pochodzą. Nieraz można w podobnych wypadkach użyć wzorca Odwiedzający (Visitor). Tutaj jednak, z tego co widzę, może on być zupełnie nieadekwatny.