Dlaczego nie ma spójnej definicji podstawowych pojęć dotyczących OOP?

12

Jestem bardzo nowy w programowaniu i trochę zdezorientowany czytaniem \ słyszenia różnych konwencji z różnych źródeł:

Czy programowanie obiektowe ma 4 lub 5 pojęć?

Jako nowicjusz rozumiem, że są to 5 pojęć:

  • Abstrakcja
  • Dziedzictwo
  • Kapsułkowanie
  • Wielopostaciowość
  • Modułowość

Dlaczego więc nie znajduję bardziej „ścisłej” definicji i wydaje się, że istnieje kilka układów tych pojęć?


źródło
7
Może dlatego, że to nie jest matematyka (niektóre pojęcia w CS są, ale myślę, że OOP nie należy do tej kategorii), więc nie ma na początku ścisłych definicji. Na przykład, jak ważna jest „modułowość”? Czy to naprawdę tak wyjątkowe dla OOP, że musimy o tym wspomnieć, czy byłoby to po prostu coś, co zdarzy się samo, jeśli zastosujemy pozostałe cztery poprawnie? Niektóre listy dodają „hierarchię”, ale czy to naprawdę coś dodatkowego, czy tylko wynika z dziedziczenia i polimorfizmu?
thorsten müller,
6
Słowo rady: Jako bardzo nowy programista nie powinieneś się tak odrywać od rozumienia terminologii i teorii. Najpierw zbierz trochę praktycznego doświadczenia w programowaniu, a stanie się o wiele bardziej oczywiste, o czym mówią ci ludzie.
Philipp
9
Inną rzeczą jest to, że OOP zmienia się z czasem. We wczesnych dniach C ++ wiele uwagi (wiem, że OOP sięga jeszcze dalej) skupiało się na dziedziczeniu i polimorfizmie. Dzisiejszy nacisk skupia się bardziej na abstrakcji i enkapsulacji.
Wygięty
3
Interesującą dyskusję na temat braku precyzji w definicji OO można znaleźć tutaj: c2.com/cgi/wiki?NobodyAgreesOnWhatOoIs
MichelHenrich

Odpowiedzi:

26

Różne wyjaśnienia tego, co oznacza programowanie obiektowe, są spowodowane tym, że nie ma jednej osoby lub organizacji, która byłaby uprawniona do sformułowania ścisłej, uniwersalnej definicji.

Programowanie obiektowe nie jest normą ISO ani prawem naukowym. To jest filozofia. Podobnie jak w przypadku wszystkich filozofii, istnieją różne rodzaje interpretacji i żadna interpretacja nie ma uniwersalnego zastosowania. Kiedy czytasz tekst, który mówi ci, jakie koncepcje powinieneś stosować przy projektowaniu architektury oprogramowania, powinieneś postrzegać to jako wskazówkę opartą na opiniach autora wypracowanych podczas ich doświadczenia zawodowego, a nie jako uniwersalną prawdę.

Philipp
źródło
12

Czy programowanie obiektowe ma 5 lub 4 elementy?

Jak wspomnieli inni, „OO” tak naprawdę nie ma żadnych komponentów , ponieważ jest to sposób myślenia o modelowaniu rozwiązań problemów, a nie zestaw narzędzi ani zestaw jasno zdefiniowanych procesów.

Jako nowicjusz rozumiem, że są to 5 składników:

Abstrakcja, dziedziczenie, enkapsulacja, polimorfizm i modułowość?

Dziedziczenie i polimorfizm to cechy języka programowania. Dobrze, że je rozumiesz, ale pamiętaj, że są to narzędzia (co oznacza, że ​​podobnie jak w przypadku innych narzędzi, powinny być używane tylko do rozwiązywania konkretnych problemów, a nie traktowane jako cel lub coś, do czego należy dążyć). Możesz (i często powinieneś) pisać kod „OO” bez użycia żadnego z nich. Niektóre z najlepszych kodów „OO”, jakie kiedykolwiek widziałem, w niewielkim stopniu wykorzystują dziedziczenie lub polimorfizm.

Abstrakcja, enkapsulacja i modułowość mają mniej wspólnego z kodem, a bardziej z tym, jak patrzysz na problem, sposób, w jaki próbujesz zrozumieć ten problem, a także sposób projektowania i strukturyzowania rozwiązania w kodzie.

Te pomysły projektowe nie dotyczą wyłącznie „OO”. Są szanse, że prawdopodobnie rozumiesz je teraz na podstawowym poziomie, co może obejmować umiejętność wyjaśnienia idealnej instrukcji i zastosowania ich do nieco nieistotnych problemów; chociaż coraz głębszy test zrozumienia ma bardzo duży złożony problem i stopień złożoności, z którym można sobie poradzić.

Kolejnym sprawdzianem zrozumienia jest podejście stosowane w celu rozwiązania problemu; i nowicjusze „OO”, którzy często uczą się o OO w zakresie modelowania danych (ponieważ tak właśnie większość ludzi rozumiała to w latach 90.) i często koncentrują się na niewłaściwych aspektach problemu - tj. koncentrują się za dużo na dane i nie koncentrują się wystarczająco na zachowaniu.

Na przykład, klasyczne przykłady często odnoszą się do podmiotów, takich jak Dog, Cat, Elephant, Seagull, Shark, itd. Nowi do „oo” często wyglądają na takich przykładów i natychmiast pomyśleć : „Och, muszę jednostkę bazową o nazwie Animal , a może nawet skończyć się z innymi jednostki pośredniej, takiej jak Mammali Amphibianw czystej spadku heirarchy, różne cechy w każdym z nich.

Podczas gdy ten sposób myślenia pokazuje bardzo podstawowe zrozumienie kilku koncepcji OO, doświadczony programista OO nigdy nie podejdzie do tego w ten sposób ani nie wyciągnie pochopnych wniosków (I faktycznie narzeka, że ​​nie ma wystarczającej ilości informacji), ponieważ takie podejście pokazuje Entity modelowanie, a nie modelowanie OO, a ponieważ wymyślony przykład nie mówi nic o zachowaniu tych zwierząt (I wielu ludzi twierdzi obecnie, że istotą OO jest zachowanie i funkcjonalność).

Ścieżka do nauki o „OO” tradycyjnie wymaga spędzania czasu na budowaniu niewłaściwych abstrakcji, gdy albo nie wiesz nic (lub za mało) na temat zachowania, które modelujesz, albo gdy popełnisz błąd, skupiając uwagę na bytach, a nie funkcjonalność, choć częściowo dlatego, że tak wiele książek, kursów i samouczków online napisanych na przestrzeni lat (źle) prowadziło uczniów na tej ścieżce przez długi czas (choć fala się zmienia).

Ogólnie rzecz biorąc, wiele twojego zrozumienia sprowadza się do doświadczenia. Pojęcia, których się nauczyłeś, są dobrym początkiem, po drodze musisz nauczyć się więcej pojęć (na przykład zasady „SOLID” i „DRY”) i musisz poświęcić dużo czasu na stawianie teorii w praktyce z bardzo złożonymi problemami, zanim wszystkie z nich „zatrzasną się” na swoim miejscu.

Ben Cottrell
źródło
2
Rekin i żaba pływają, ale jedna to ryba, druga to płaz. Myślę, że ten przykład dobrze opisuje twój punkt widzenia.
RubberDuck,
10

Termin „orientacja obiektowa” został ukuty przez dr Alana Kay, więc jest on autorytatywnym źródłem tego, co to znaczy, i definiuje to w ten sposób :

OOP oznacza dla mnie tylko wysyłanie wiadomości, lokalne przechowywanie, ochronę i ukrywanie procesów państwowych oraz ekstremalne późne wiązanie wszystkich rzeczy.

Rozbijmy to:

  • przesyłanie wiadomości („metoda wirtualnej wysyłki”, jeśli nie znasz Smalltalk)
  • proces stanu powinien być
    • zachowane lokalnie
    • chroniony
    • ukryty
  • ekstremalne późne wiązanie wszystkich rzeczy

Jeśli chodzi o implementację, przesyłanie komunikatów jest opóźnionym wywołaniem procedury, a jeśli wywołania procedury są opóźnione, to w czasie projektowania nie można wiedzieć, co wywołać, więc nie można przyjmować żadnych założeń dotyczących konkretnej reprezentacji stanu. Tak naprawdę tak naprawdę chodzi o przesyłanie wiadomości, późne wiązanie jest implementacją przesyłania wiadomości, a konsekwencją tego jest enkapsulacja.

Później wyjaśnił, że „ główną ideą jest„ przesyłanie wiadomości ” ” i żałuje, że nazwał to „obiektowym” zamiast „zorientowanym na wiadomości”, ponieważ termin „zorientowany obiektowo” kładzie nacisk na nieistotne rzeczy (obiekty ) i odwraca uwagę od tego, co jest naprawdę ważne (wiadomości):

Tylko delikatne przypomnienie, że na ostatnim OOPSLA zadałem sobie trud, aby przypomnieć wszystkim, że Smalltalk nie jest NIE tylko składnią ani biblioteką klas, nie dotyczy nawet klas. Przykro mi, że już dawno wymyśliłem termin „obiekty” w tym temacie, ponieważ wielu ludzi skupia się na mniejszym pomyśle.

Wielkim pomysłem jest „przesyłanie wiadomości” - na tym właśnie polega jądro Smalltalk / Squeak (i ​​jest to coś, czego nigdy nie ukończono w fazie Xerox PARC). Japończycy mają małe słowo - ma - na „to, co jest pomiędzy” - być może najbliższym angielskim odpowiednikiem jest „pełnoekranowy”. Kluczem do tworzenia świetnych i sprawdzalnych systemów jest znacznie więcej niż projektowanie ich modułów, a nie ich wewnętrznych właściwości i zachowań. Pomyśl o Internecie - aby żyć, (a) musi pozwalać na wiele różnych rodzajów pomysłów i realizacji, które wykraczają poza jakikolwiek pojedynczy standard, i (b) umożliwiać różne stopnie bezpiecznej interoperacyjności między tymi pomysłami.

(Oczywiście dzisiaj większość ludzi nawet nie skupia się na przedmiotach, ale na klasach, co jest jeszcze bardziej błędne).

Przesyłanie wiadomości ma fundamentalne znaczenie dla OO, zarówno jako metafory, jak i mechanizmu.

Jeśli wyślesz komuś wiadomość, nie wiesz, co ona z nią zrobi. Tylko rzeczą, jaką można zauważyć, jest ich reakcja. Nie wiesz, czy sami przetworzyli wiadomość (tj. Czy obiekt ma metodę), czy przekazali wiadomość komuś innemu (delegacja / proxy), nawet jeśli ją zrozumieli. Na tym polega enkapsulacja, na tym właśnie polega OO. Nie można nawet odróżnić serwera proxy od rzeczywistego, o ile odpowiada on oczekiwaniom.

Bardziej „nowoczesnym” terminem „przesyłanie komunikatów” jest „dynamiczne wysyłanie metod” lub „wirtualne wywołanie metod”, ale traci ono metaforę i skupia się na mechanizmie.

Istnieją więc dwa sposoby spojrzenia na definicję Alana Kay: jeśli spojrzysz na nią samodzielnie, możesz zauważyć, że przesyłanie wiadomości jest w zasadzie opóźnionym wywołaniem procedury, a późne wiązanie oznacza enkapsulację, więc możemy stwierdzić, że # 1 i # 2 są w rzeczywistości zbędne, a OO polega na późnym wiązaniu.

Później wyjaśnił jednak, że ważną rzeczą jest przesyłanie wiadomości, dlatego możemy spojrzeć na to z innej strony: przesyłanie wiadomości jest opóźnione. Otóż, gdyby przesyłanie wiadomości było jedyną możliwą rzeczą, to # 3 byłoby trywialnie prawdziwe: jeśli jest tylko jedna rzecz, a ta sprawa jest spóźniona, wówczas wszystkie rzeczy są spóźnione. Po raz kolejny enkapsulacja wynika z przesyłania wiadomości.

Podobne uwagi znajdują się również w „ Understanding Data Abstraction”, zrewidowanym przez Williama R. Cooka, a także w jego Propozycji dotyczącej uproszczonych, nowoczesnych definicji „Object” i „Object Oriented” .

Dynamiczna wysyłka operacji jest podstawową cechą obiektów. Oznacza to, że wywołana operacja jest dynamiczną właściwością samego obiektu. Operacji nie można zidentyfikować statycznie i ogólnie nie ma sposobu na dokładne wykonanie operacji w odpowiedzi na dane żądanie, poza uruchomieniem go. Jest to dokładnie to samo, co w przypadku pierwszorzędnych funkcji, które są zawsze wysyłane dynamicznie.

W Smalltalk-72 nie było nawet żadnych przedmiotów! Były tylko strumienie wiadomości, które zostały przeanalizowane, przepisane i przekierowane. Najpierw pojawiły się metody (standardowe sposoby parsowania i przekierowania strumieni wiadomości), później pojawiły się obiekty (grupy metod, które dzielą pewien stan prywatny). Dziedziczenie nastąpiło znacznie później, a klasy wprowadzono jedynie jako sposób na wsparcie dziedziczenia. Gdyby grupa badawcza Kay wiedziała już o prototypach, prawdopodobnie nigdy nie wprowadziliby zajęć.

Benjamin Pierce w typach i językach programowania argumentuje, że cechą definiującą orientację obiektową jest otwarta rekurencja .

Tak więc: według Alana Kay, OO polega na przesyłaniu wiadomości. Według Williama Cooka, OO polega na dynamicznej wysyłce metod (co tak naprawdę jest tym samym). Według Benjamina Pierce'a w OO chodzi o Open Recursion, co w zasadzie oznacza, że ​​autoreferencje są dynamicznie rozwiązywane (a przynajmniej tak należy się zastanowić) lub, innymi słowy, przesyłanie wiadomości.

Jak widać, osoba, która ukuła termin „OO”, ma raczej metafizyczne spojrzenie na przedmioty, Cook ma raczej pragmatyczny pogląd, a Pierce bardzo rygorystyczny pogląd matematyczny. Ale ważne jest to, że filozof, pragmatyk i teoretyk są zgodni! Wiadomości to jeden filar OO. Kropka.

Zauważ, że nie ma tu mowy o dziedziczeniu! Dziedziczenie nie jest niezbędne dla OO. Ogólnie rzecz biorąc, większość języków OO ma jakiś sposób ponownego wykorzystania implementacji, ale niekoniecznie musi to być dziedziczenie. Może to być na przykład jakaś forma przekazania uprawnień. W rzeczywistości traktat z Orlando omawia delegowanie jako alternatywę dla dziedziczenia oraz to, w jaki sposób różne formy delegowania i dziedziczenia prowadzą do różnych punktów projektowania w przestrzeni projektowania języków zorientowanych obiektowo. (Należy pamiętać, że w rzeczywistości nawet w językach obsługujących dziedziczenie, takich jak Java, ludzie są tak naprawdę uczeni, jak tego unikać, co ponownie wskazuje, że nie jest to konieczne dla OO.)

Jörg W Mittag
źródło
1
@DavidArno Twój komentarz w ogóle nie jest konstruktywny. Sam Alan Kay twierdzi, że ukuł termin „przedmiot” dla tej koncepcji (choć, jak sądzę, nie sama koncepcja). Jeśli masz zamiar zaprzeczyć znanemu autorytetowi w tej dziedzinie, przynajmniej napisz bardziej konstruktywny komentarz.
Andres F.,
1
@DavidArno Także, czy głosowanie jest twoje? Więc ktoś poświęcił czas na napisanie wyczerpującej listy różnych opinii, od znanych ekspertów, na temat tego, co oznacza OOP, i głosowałeś za nią, ponieważ nie zgadzasz się z jednym zdaniem? Oookay.
Andres F.
2
@AndresF. Odpowiedź można streścić w następujący sposób: „istnieją jednak dwie szkoły Alana Kay i wszystkich innych. Ponieważ ta pierwsza wymyśliła termin, że automatycznie ma rację, a każdy, kto się z nim nie zgadza, jest w błędzie”. Jest to odwołanie do fałszywej odpowiedzi autorytetu. Tak więc głosowanie negatywne.
David Arno,
2
W rzeczywistości odpowiedź tę można podsumować jako „istnieją trzy szkoły myślenia, pochodzące z trzech zupełnie różnych punktów widzenia i nikt się z nikim nie zgadza, w rzeczywistości wszyscy są zgodni”. Lingwistyczny preskryptywista powiedziałby, że Alan Kay wymyślił ten termin, może powiedzieć, co to znaczy, i mówi, że to oznacza komunikację. Lingwistyczny deskryptywista powiedziałby: nie, Alan Kay nic nie mówi, musimy spojrzeć na to, jak ten termin jest rzeczywiście używany , i to właśnie zrobił Cook: zbadał, jakie języki są powszechnie określane jako OO (Java, C ++ , C # itp.) Mają ze sobą wspólnego, a on stwierdził
Jörg W Mittag
3
jedno: messaging.He studiował jakich językach powszechnie określane jako nie OO brakuje, że języki powszechnie określane jako OO mieć, i znalazł jedną rzecz: wiadomości. Teoretyk wieży z kości słoniowej bierze rachunek λ i patrzy na to, co najmniejszy zestaw cech to to, co trzeba dodać, aby uzyskać coś, co jest powszechnie określane jako OO, i dochodzi do otwartej rekurencji , która jest w zasadzie budulcem wiadomości .
Jörg W Mittag,
3

Jak stwierdza @Philipp, źródłem problemu jest brak oficjalnej definicji tego, co sprawia, że ​​język programowania jest zorientowany obiektowo. Rzeczywiście jest to prawdopodobnie dobra rzecz. Istnieje wiele sposobów wspierania programowania OO, z których każdy ma swoje zalety i wady. Dyskusje o tym, które języki są bardziej „czystym OO”, tak naprawdę niewiele osiągają.

Jednak patrząc na 5 wymienionych atrybutów, moim zdaniem modułowość jest zdecydowanie dziwna. Modułowość to tak naprawdę atrybut programu, a nie język programowania. Na poziomie językowym atrybutem jest „wsparcie modularyzacji”, które zazwyczaj przyjmuje formę mechanizmu „modułów” pr „pakietów”.

Ale moim prawdziwym sprzeciwem wobec modułowości jest to, że nie jest to klucz do programowania OO ani języków programowania OO, o ile archetypowy język programowania Smalltalk-80 w ogóle nie obsługiwał modułów. A kiedy się nad tym zastanowić, wsparcie językowe modułów w wielu powszechnie używanych OOPL jest „słabe”.

Moduły są zaprojektowane do obsługi „programowania w dużym”… gdzie baza kodu staje się zbyt duża, aby jedna osoba mogła ją w pełni zrozumieć. I nie potrzebujesz modułów w języku programowania do modularyzacji kodu.


Nie wchodzę w debatę na temat pozostałych 4 atrybutów i tego, czy (na przykład) jakie modele „dziedziczenia” są czystym OO. Ponadto, chociaż Alanowi Kay przypisuje się wynalezienie programowania OO, nie musi to oznaczać, że jego definicje OO / i OOPL mają pierwszeństwo. Oczywiście tak nie jest. Jest wiarygodne źródło, ale istnieją inne źródła, które dają inne definicje OO & OOPLs że (w praktyce) przeprowadzić większą wagę.

Stephen C.
źródło
2
+1 Modułowość jest w rzeczywistości powszechnie akceptowana jako pożądany atrybut większości systemów oprogramowania, niezależnie od użytego języka programowania i paradygmatu. Wiele języków, które nie są OO, obsługuje modularyzację.
Andres F.
+1 @AndresF. komentarz. Rzeczywiście, „programowanie strukturalne” i „stopniowe udoskonalanie” (technika myślenia o strukturze kodu) pochodzi z tygla „zwiększającej się złożoności skutkującej jeszcze gorszym oprogramowaniem”. Gdyby poprzedziło to COBOL, język ten nie miałby tak negatywnej reputacji IMHO. I postrzegam OO pragmatycznie jako po prostu strukturę wyższego rzędu. I mam na myśli, że O / O bazowa struktura OO nie jest lepsza niż najgorszy COBOL.
radarbob,