Myślę, że jest kilka czynników, o których jeszcze nie wspomniano.
Przede wszystkim, przynajmniej w „czystym OOP” (np. Smalltalk), gdzie wszystko jest przedmiotem, musisz przekręcić swój umysł w raczej nienaturalną konfigurację, aby myśleć o liczbie (tylko dla jednego przykładu) jako inteligentnym obiekcie zamiast tylko wartość - ponieważ w rzeczywistości 21
(na przykład) naprawdę jest tylko wartością. Staje się to szczególnie problematyczne, gdy z jednej strony dowiesz się, że dużą zaletą OOP jest dokładniejsze modelowanie rzeczywistości, ale zaczynasz od spojrzenia na coś, co wygląda okropnie jak inspirowany LSD widok nawet najbardziej podstawowych i oczywistych części rzeczywistość.
Po drugie, dziedziczenie w OOP nie bardzo ściśle podąża za modelami umysłowymi większości ludzi. Dla większości ludzi klasyfikowanie rzeczy w szczególności nie ma żadnych zasad absolutnych niezbędnych do stworzenia działającej hierarchii klas. W szczególności, tworzenie class D
dziedziczącego z innego class B
oznacza, że obiekty class D
dzielą się absolutnie, pozytywnie, wszystkimi cechami class B
. class D
może dodawać nowe i różne własne cechy, ale wszystkie cechy class B
muszą pozostać nienaruszone.
Z drugiej strony, kiedy ludzie klasyfikują rzeczy mentalnie, zwykle postępują według znacznie luźniejszego modelu. Na przykład, jeśli dana osoba ustanawia pewne reguły dotyczące tego, co stanowi klasę obiektów, dość typowe jest, że prawie każda reguła może zostać złamana, o ile przestrzegane są wystarczające inne reguły. Nawet te kilka zasad, których tak naprawdę nie można złamać, prawie zawsze można trochę „rozciągnąć”.
Na przykład rozważ „samochód” jako klasę. Łatwo zauważyć, że zdecydowana większość tego, co większość ludzi uważa za „samochody”, ma cztery koła. Jednak większość ludzi widziała (przynajmniej zdjęcie) samochód z tylko trzema kołami. Kilku z nas w odpowiednim wieku pamięta również samochód wyścigowy lub dwa z wczesnych lat 80. (lub mniej więcej), który miał sześć kół - i tak dalej. To daje nam zasadniczo trzy możliwości:
- Nie twierdzę nic o tym, ile kół ma samochód - ale prowadzi to do domniemanego założenia, że zawsze będzie to 4, i kodu, który prawdopodobnie złamie inną liczbę.
- Zapewnij, że wszystkie samochody mają cztery koła, i po prostu sklasyfikuj te inne jako „nie samochody”, chociaż wiemy, że tak naprawdę są.
- Zaprojektuj klasę, aby umożliwić zmianę liczby kół, na wszelki wypadek, nawet jeśli istnieje duża szansa, że ta zdolność nigdy nie będzie potrzebna, używana ani odpowiednio testowana.
Nauczanie o OOP często koncentruje się na budowaniu ogromnych taksonomii - np. Fragmentów czegoś, co byłoby gigantyczną hierarchią całego znanego życia na ziemi lub czegoś w tym porządku. Rodzi to dwa problemy: po pierwsze, prowadzi wielu ludzi do skupienia się na ogromnych ilościach informacji, które są całkowicie nieistotne dla danego pytania. W pewnym momencie widziałem dość długą dyskusję o tym, jak modelować rasy psów i czy (na przykład) „miniaturowy pudel” powinien odziedziczyć po „pełnowymiarowym pudle” lub odwrotnie, czy też powinna istnieć abstrakcyjna baza „Pudel” „klasa, z„ pełnowymiarowym pudlem ”i„ miniaturowym pudlem ”, które dziedziczą po nim. Wszyscy zdawali się ignorować to, że aplikacja miała zajmować się śledzeniem licencji dla psów,
Po drugie, i prawie co ważne, prowadzi to do skupienia się na charakterystyce przedmiotów, zamiast skupiać się na cechach, które są ważne dla danego zadania. Prowadzi to do modelowania rzeczy takimi, jakie są, gdzie (przez większość czasu) naprawdę potrzebna jest budowa najprostszego modelu, który zaspokoi nasze potrzeby, i użycie abstrakcji, aby dopasować niezbędne podklasy, aby dopasować abstrakcję, którą zbudowaliśmy.
Na koniec powiem jeszcze raz: przez lata powoli podążamy tą samą ścieżką baz danych. Wczesne bazy danych były zgodne z modelem hierarchicznym. Poza skupieniem się wyłącznie na danych, jest to pojedyncze dziedziczenie. Przez krótki czas kilka baz danych działało zgodnie z modelem sieci - zasadniczo identycznym jak wielokrotne dziedziczenie (i patrząc pod tym kątem, wiele interfejsów nie różni się wystarczająco od wielu klas bazowych, aby zauważyć lub o to dbać).
Jednak dawno temu bazy danych były w dużej mierze zbieżne na modelu relacyjnym (i chociaż nie są one SQLem, na tym poziomie abstrakcji obecne bazy danych „NoSQL” również są relacyjne). Zalety modelu relacyjnego są na tyle dobrze znane, że nie zawracam sobie głowy ich powtarzaniem. Po prostu zauważę, że najbliższym analogiem modelu relacyjnego, który mamy w programowaniu, jest programowanie ogólne (i przykro nam, ale pomimo nazwy, generyczne Java, na przykład, tak naprawdę nie kwalifikują się, chociaż są niewielkim krokiem w dobry kierunek).