Dlaczego OOP jest trudny? [Zamknięte]

91

Kiedy zacząłem używać języka obiektowego (Java), po prostu przeszedłem na „Cool” i zacząłem kodować. Nigdy tak naprawdę nie myślałem o tym aż do niedawna po przeczytaniu wielu pytań na temat OOP. Mam ogólne wrażenie, że ludzie się z tym zmagają. Ponieważ nie uważałem tego za trudne i nie powiedziałbym, że jestem geniuszem, myślę, że musiałem coś przeoczyć lub źle to zrozumieć.

Dlaczego OOP jest trudny do zrozumienia? Czy trudno to zrozumieć?

gablin
źródło
72
Odpowiadam: Nietrudno to zrozumieć, po prostu trudno opanować. Programowanie jako całość jest w ten sposób.
Steven Evers
2
umm, prawda? Może programiści, którzy nie potrafią programować, ciężko obwiniają ups zamiast swoich linii kodu? nie wiem, ale nigdy nie słyszałem, żeby ktoś powiedział, że trudno to zrozumieć. Widziałem jednak, że ppl twierdzi, że funkcjonalność jest dziwna, zwłaszcza że nie mogą zmienić wartości swojej zmiennej.
5
@ acidzombie42: funkcjonalność wcale nie jest dziwna. nie musisz pisać listy poleceń, aby zmienić zawartość zmiennych reprezentujących lokalizację w pamięci RAM. zmienne reprezentują wartości, nie zmieniasz wartości; 42 pozostaje 42, x pozostaje x - cokolwiek x jest. piszesz funkcje, które mapują ich parametry na wyniki. wartościami są: liczby, listy wartości, funkcje od wartości do wartości, programy, które wywołują skutki uboczne i wynikową wartość przy wykonywaniu, i więcej. w ten sposób wynik funkcji głównej zostanie obliczony przez kompilator, czyli program, który można wykonać.
comonad
5
Ostatnio uczyłem się Haskell. Im więcej się uczę i rozumiem na temat programowania funkcjonalnego, tym bardziej czuję, że OOP jest trudne. Myślę, że głównym powodem tego jest to, że OOP próbuje powiązać dane (obiekt / klasę) z funkcją, która na nich działa (metoda). Jest to źródłem problemu i opracowano wiele wzorców projektowych OOP, aby uniknąć łączenia danych i funkcji. Przykład: wzorzec fabryczny służy do oddzielenia konstruktora (który jest funkcją) od rzeczywistego obiektu, na którym działa.
ming_codes,
1
Ponieważ jest źle nazwany. To naprawdę powinno być programowanie zorientowane na podmiot, w którym podmiot wykonuje akcję (czasownik), a obiekt otrzymuje akcję - John rzucił piłkę. Tak więc johnsBall.throw () tak naprawdę nie ma sensu.
Chris Cudmore,

Odpowiedzi:

119

Osobiście uważałem, że mechanika OOP jest dość łatwa do zrozumienia. Najtrudniejsze było dla mnie „dlaczego”. Kiedy zostałem po raz pierwszy zetknięty, wydawało mi się, że to rozwiązanie problemu. Oto kilka powodów, dla których myślę, że większość ludzi ma trudności:

  1. Nauczanie OO od początku przez IMHO to okropny pomysł. Kodowanie proceduralne nie jest „złym nawykiem” i jest właściwym narzędziem do niektórych zadań. Poszczególne metody w programie OO i tak wydają się dość proceduralne. Ponadto, zanim nauczy się programowania proceduralnego wystarczająco dobrze, aby jego ograniczenia stały się widoczne, OO nie wydaje się zbyt przydatne dla studenta.

  2. Zanim naprawdę zrozumiesz OO, musisz poznać podstawy struktur danych oraz funkcje późnego wiązania / wyższego rzędu. Trudno wywołać polimorfizm (który w zasadzie przekazuje wskaźnik do danych i zestaw funkcji, które działają na danych), jeśli nawet nie rozumiesz koncepcji konstruowania danych zamiast używania prymitywów i przekazywania funkcji wyższego rzędu / wskaźniki do funkcji.

  3. Wzorów projektowych należy uczyć jako czegoś podstawowego dla OO, a nie czegoś bardziej zaawansowanego. Wzory projektowe pomagają zobaczyć las przez drzewa i dają względnie konkretne przykłady, w których OO może uprościć prawdziwe problemy, a w końcu i tak będziesz chciał się ich nauczyć. Ponadto, gdy naprawdę pojawi się OO, większość wzorów projektowych staje się oczywista z perspektywy czasu.

dsimcha
źródło
5
bajeczna odpowiedź, szczególnie numer 1. Oczywiście metody w OO wyglądają jak metody w języku proceduralnym, ale teraz są umieszczone w obiektach, które również mają stan.
Dan Rosenstark,
3
Szczególnie podoba mi się twój 1. i 3. punkt. Mój przyjaciel jest gaga w zakresie wzorców projektowych i ciągle mu powtarzam, że jeśli używasz dobrego OOP, większość z nich wywodzi się bardzo naturalnie z początkowego problemu.
CodexArcanum
7
+1 za „Trudną rzeczą było dla mnie„ dlaczego ”tego. Trochę czasu i wysiłku zajmuje zrozumienie i zastosowanie podstaw języka (enkapsulacja) oraz zasad projektowania i metod refaktoryzacji w kierunku wspólnych rozwiązań (wzorców projektowych).
Belun,
12
Zgadzam się z punktem 1, z zastrzeżeniem, że musisz wykonać lepszą robotę, wyjaśniając OO osobom, które już wiedzą, jak programować proceduralnie, niż miało to miejsce podczas nauki. Nie, nie jest użyteczne ani pouczające rozmawianie o Catklasie, która dziedziczy Mammal, użyj prawdziwego przykładu z prawdziwego programu, który napisalibyśmy proceduralnie. Jak prosta struktura danych.
Carson63000,
4
-1 Wzory projektowe są dziś tak mocno podkreślane. Są ważne, jasne, ale: po pierwsze, są ważne dla wszystkich paradygmatów: funkcjonalne, ustrukturyzowane, a także OO; a po drugie, nie są częścią paradygmatu, tylko wygodny dodatek, którego można używać, jak wiele innych. @ SoftwareRockstar ładnie wyjaśnia to w swojej odpowiedzi.
CesarGon
56

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 Ddziedziczącego z innego class Boznacza, że ​​obiekty class Ddzielą się absolutnie, pozytywnie, wszystkimi cechami class B. class Dmoże dodawać nowe i różne własne cechy, ale wszystkie cechy class Bmuszą 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:

  1. 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ę.
  2. Zapewnij, że wszystkie samochody mają cztery koła, i po prostu sklasyfikuj te inne jako „nie samochody”, chociaż wiemy, że tak naprawdę są.
  3. 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).

Jerry Coffin
źródło
Bardzo dobrze powiedziane, a zwłaszcza, że ​​większość problemów z OOP, które dajesz, to nie tylko problemy ze zrozumieniem go przez początkujących, ale raczej ogólne kwestie OOP, które większość programistów OOP nauczy się myśleć. Ostatnio pracuję nad projektowaniem gier, w których model komponentu działa bardzo dobrze, co ściśle odwzorowuje pojęcie modeli relacyjnych, a nie hierarchicznych.
CodexArcanum
7
Heh, właśnie o tym myślałem. Jak wszystkie pierwsze materiały do ​​nauki, które czytałem na temat OOP, wydawały się koncentrować na dziedziczeniu, podczas gdy moje doświadczenie coraz bardziej mówi mi, że dziedziczenie jest w większości bezużyteczne, jeśli nie szkodliwe.
rmac
Brzmi jak programowanie zorientowane na tabelę , choć powiem, że zdaję sobie sprawę, że OOP nie jest srebrną kulą rozwoju oprogramowania.
OnesimusUnbound
1
@OnesimusUnbound: różnica polega na tym, że programowanie ogólne jest prawdziwym, praktycznym sposobem na zrobienie czegoś, podczas gdy programowanie zorientowane na tabelę jest w większości szaleńcami na punkcie teorii o tym, jak coś może działać (przeczytaj stare posty TopMind w comp.object, a ty Zobaczę, co mam na myśli - w rzeczywistości posty mogą nie być stare; o ile wiem, kontynuuje do dziś).
Jerry Coffin
3
Właśnie dlatego interfejsy są tak świetne. Bierzemy modelowanie dziedziczenia i odwracamy je do podejścia opartego na pierwszym rzędzie. Na przykład na przykładzie psa można założyć, że każdy pies ma rodzaj i maksymalnie dwa nadgatunki (po jednym dla każdego rodzica) dla określonej rasy. Może również istnieć właściwość listy zawierająca cechy, ale możliwa różnorodność sprawia, że ​​nie ma sensu zmieniać ich w określoną strukturę. Lepiej jest przeprowadzić głębokie wyszukiwanie, aby zaindeksować cechy i połączyć podobne rasy na podstawie tych wyników.
Evan Plaice
26

OOP wymaga umiejętności abstrakcyjnego myślenia; dar / przekleństwo, które tak naprawdę ma niewiele osób, nawet profesjonalnych programistów.

John Kraft
źródło
35
Całe programowanie jest abstrakcyjne.
JeffO
28
@Jeff O - Nie zgadzam się. Programowanie wymaga jedynie umiejętności mówienia komuś, jak zrobić coś krok po kroku. Jeśli możesz powiedzieć komuś, jak zrobić kanapkę z masłem orzechowym i galaretką, masz możliwość wpisywania poleceń w interfejsie programowania. To jest zupełnie inny zestaw umiejętności niż abstrakcyjne modelowanie kanapek ap, b & j i tego, jak wchodzi w interakcje ze światem.
John Kraft,
16
Podawanie komuś 2 ołówków, a następnie wręczanie im 1 ołówka i pytanie, ile ma ołówków, jest konkretne. 2 + 1 = 3 jest abstrakcją.
JeffO
17
Zgadzam się z Jeffem. Programowanie to w zasadzie zarządzanie abstrakcjami. Przynajmniej tak jest w przypadku wszystkiego oprócz najbardziej podstawowego przebiegu programu (ponieważ wszystko inne będzie zbyt skomplikowane bez abstrakcji). Nauka programowania jest wyraźna, gdy nowicjusz uczy się, jak kontrolować abstrakcje. Tam spada metafora przepisu. Programowanie nie przypomina gotowania i chociaż pojedynczy algorytm można przyrównać do przepisu, programowanie zasadniczo różni się od implementacji izolowanych algorytmów.
Konrad Rudolph
2
@KonradRudolph Świetny punkt. +1 za „Wszystko inne będzie zbyt skomplikowane bez abstrakcji” .
Karthik Sreenivasan
21

Myślę, że możesz podsumować podstawową trudność w ten sposób:

// The way most people think.
Operation - object - parameters
// Example:
Turn the car left.

// The way OOP works conceptually
Object - operation - parameters
// Example:
Car.Turn(270);

Jasne, ludzie mogą przyzwyczaić się do mapowania „lewej” jako 270, a tak, powiedzenie „Car.Turn” zamiast „obrócić samochód” nie jest tak wielkim skokiem. ALE, aby dobrze sobie radzić z tymi obiektami i je tworzyć, musisz odwrócić normalne myślenie.

Zamiast manipulować obiektem, mówimy temu obiektowi, aby faktycznie robił rzeczy samodzielnie. To może już nie być trudne, ale polecenie otwarcia okna brzmi dziwnie. Ludzie nieprzyzwyczajeni do tego sposobu myślenia muszą nieustannie zmagać się z tą dziwnością, aż w końcu stanie się ona naturalna.

John Fisher
źródło
7
Dobry wgląd. Myślę, że problem polega na tym, że w prawdziwym życiu nie ma zbyt wiele rzeczy, które można zrobić, co nie jest związane z innymi przedmiotami. OO działa dobrze, o ile obiektom nakazuje się modyfikować ich stan wewnętrzny: prostokąt.enlarge (margin_in_pixels), ale lata temu zdałem sobie sprawę z ograniczeń. Pewnego dnia my programiści instalowaliśmy sprzęt. Ktoś mądry „crack.turn” Zabawne, ale przyszło mi do głowy: pewnie, śruba może zmienić jej orientację, ale tak naprawdę jest to operacja między szafką a śrubą; żaden obiekt nie może wykonać samego zadania. OO po prostu nie jest wystarczająco dobre.
DarenW
3
+1, po latach pisania „substr (data, 0,4)”, trudno jest napisać „date.substring (0,4)”
ern0
4
+1 za fragment kodu. Wyraźnie przedstawia faktyczny proces myślowy.
Karthik Sreenivasan
2
Przeczytałbym to jako polecenie, które wysyłasz. Jak w „powiedz samochodowi, aby skręcił w lewo”. Oop polegał na wysyłaniu wiadomości do obiektów, więc tak to interpretuję.
bunglestink
1
Dobry wgląd, więc może OOP jest bardziej odpowiedni do modelowania „systemów agentów”?
Qbik
21

Każdy paradygmat wymaga pewnego popchnięcia „ponad krawędź”, aby zrozumieć, dla większości ludzi. Z definicji jest to nowy sposób myślenia, dlatego wymaga pewnej ilości porzucenia starych pojęć i pewnego stopnia pełnego zrozumienia, dlaczego nowe pojęcia są użyteczne.

Myślę, że duży problem polega na tym, że metody nauczania programowania są ogólnie dość słabe. OOP jest teraz tak powszechny, że nie jest tak zauważalny, ale nadal często go widać w programowaniu funkcjonalnym:

  • ważne pojęcia ukryte są pod nieparzystymi nazwami (FP: Co to jest monada? OOP: Dlaczego czasami nazywają je funkcjami, a innym razem metodami?)

  • nieparzyste koncepcje są objaśniane w metaforach, a nie w kategoriach tego, co faktycznie robią, dlaczego ich używasz, lub dlaczego ktokolwiek myślał o ich użyciu (FP: Monada to skafander kosmiczny, zawija trochę kodu. OOP: An obiekt jest jak kaczka, może hałasować, chodzić i dziedziczyć po zwierzętach)

  • dobre rzeczy różnią się w zależności od osoby, więc nie jest całkiem jasne, co będzie punktem zwrotnym dla każdego ucznia, a nauczyciel często nawet nie pamięta. (FP: Och, monady pozwalają ukryć coś w samym typie i kontynuować bez konieczności jawnego zapisywania tego, co się dzieje za każdym razem. OOP: Och, obiekty pozwalają zachować funkcje dla pewnego rodzaju danych z tymi danymi.)

Najgorsze jest to, że jak wskazuje pytanie, niektórzy ludzie natychmiast zrozumieją, dlaczego koncepcja jest dobra, a niektórzy nie. To naprawdę zależy od tego, jaki jest punkt krytyczny. Dla mnie kluczem było uchwycenie, że obiekty przechowują dane i metody dla tych danych, po czym wszystko inne po prostu pasuje jako naturalne rozszerzenie. Potem miałem skoki, jak uświadomienie sobie, że wywołanie metody z obiektu jest bardzo podobne do wykonania wywołania statycznego z tym obiektem jako pierwszym parametrem.

Małe skoki później pomagają udoskonalić zrozumienie, ale jest to pierwsza, która zabiera osobę z „OOP nie ma sensu, dlaczego ludzie to robią?” do „OOP jest najlepszy, dlaczego ludzie robią coś jeszcze?”

CodexArcanum
źródło
8
Szczególnie nienawidzę metaforyzmu, częściej niż nie, myli raczej niż opisuje.
Lie Ryan,
3
„Potem miałem skoki, jak uświadomienie sobie, że wywołanie metody z obiektu jest bardzo podobne do wykonania wywołania statycznego z tym obiektem jako pierwszym parametrem”. Chciałbym, aby podkreślano to od samego początku, tak jak w językach takich jak Python.
Jared Updike,
1
Mój problem z używaniem metafor do wyjaśniania pojęć polega na tym, że nauczyciel często zatrzymuje się na metaforze, jakby to wyjaśniało całą sprawę. Nie, to nie jest pełne wyjaśnienie; to tylko ilustracja, która pomoże nam owinąć głowy wokół właściwego wyjaśnienia.
jhocking
Świetna odpowiedź! +1 za wyjaśnienie, że pierwszy krok do zrozumienia OOP będzie ważniejszy niż to, co nastąpi później jako naturalne rozszerzenia z dobrym zrozumieniem podstawy. : D
Karthik Sreenivasan
dittos na temat uczenia się „skaczącego”: kiedy zacząłem postrzegać OOP jako „jedynie” modułową / strukturalną / stopniową konstrukcję, ale na sterydach; kiedy przepisałem niektóre bardzo stare i zniekształcone programy COBOL. Niezależnie od globalnego zakresu COBOL, zastosowałem zasady OO z niestandardowymi strukturami rekordów, zmiennymi jednozadaniowymi oraz ściśle skoncentrowanymi, modułowymi i strukturalnymi akapitami (metodami).
radarbob
15

Ponieważ podstawowe wyjaśnienie OOP ma bardzo, bardzo mało wspólnego z tym, jak jest używane w terenie. Większość programów do nauczania tego próbuje używać modelu fizycznego, takiego jak „Myśl o samochodzie jako obiekcie, a koła o obiektach, drzwiach i skrzyni biegów ...”, ale poza pewnymi niejasnymi przypadkami programowania symulacyjnego, obiekty są znacznie częściej wykorzystywane do reprezentowania pojęć niefizycznych lub do wprowadzania pośrednich. Skutkuje to tym, że ludzie rozumieją to intuicyjnie w niewłaściwy sposób.

Nauczanie na podstawie wzorców projektowych jest znacznie lepszym sposobem na opisanie OOP, ponieważ pokazuje programistom, jak niektóre rzeczywiste problemy z modelowaniem można skutecznie atakować obiektami, zamiast opisywać je w sposób abstrakcyjny.

Dan Monego
źródło
13

W większości nie zgadzam się z odpowiedzią dsimcha:

  1. Nauczanie OO od samego początku nie jest złym pomysłem, podobnie jak nauczanie języków proceduralnych. Ważne jest to, że uczymy ludzi pisania jasnego, zwięzłego, spójnego kodu, niezależnie od OO lub proceduralnych.

  2. Poszczególne metody w dobrych programach OO wcale nie są proceduralne. Staje się to coraz bardziej prawdziwe wraz z ewolucją języków OO (czytaj C #, ponieważ inny niż C ++ to jedyny inny język OO, jaki znam) i ich składnia staje się coraz bardziej złożona z dnia na dzień (lambda, LINQ do obiektów itp.). Jedynym podobieństwem między metodami i procedurami OO w językach proceduralnych jest ich liniowy charakter, który, jak sądzę, wkrótce by się zmienił.

  3. Nie można również opanować języka proceduralnego bez zrozumienia struktur danych. Koncepcja wskaźnika jest równie ważna dla języków proceduralnych, jak dla języków OO. Na przykład przekazywanie parametrów przez odniesienie, co jest dość powszechne w językach proceduralnych, wymaga zrozumienia wskaźników tak samo, jak wymagane jest nauczenie się dowolnego języka OO.

  4. Nie sądzę, że wzorców projektowych należy uczyć w ogóle na początku programowania OO, ponieważ w ogóle nie są one fundamentalne dla programowania OO. Z pewnością można być dobrym programistą OO, nie wiedząc nic o wzorcach projektowych. W rzeczywistości osoba może nawet stosować dobrze znane wzorce projektowe, nawet nie wiedząc, że są one udokumentowane odpowiednimi nazwami i że napisano o nich książki. Zasadniczo należy uczyć zasad projektowania, takich jak pojedyncza odpowiedzialność, otwarte zamknięcie i segregacja interfejsu. Niestety, wielu ludzi, którzy uważają się za programistów OO w tych dniach, albo nie znają tej podstawowej koncepcji, albo po prostu ignorują ją i dlatego mamy tak dużo śmieciowego kodu OO.

Tak, aby odpowiedzieć na pytanie oryginalnego plakatu, OO jest trudniejszym do zrozumienia pojęciem niż programowanie proceduralne. Jest tak, ponieważ nie myślimy o właściwościach i metodach przedmiotów z prawdziwego życia. Na przykład ludzki mózg nie myśli o „TurnOn” jako o metodzie telewizyjnej, ale postrzega ją jako funkcję włączania telewizora przez człowieka. Podobnie, polimorfizm jest obcą koncepcją dla ludzkiego mózgu, który na ogół widzi każdy obiekt z życia tylko jedną „twarzą”. Dziedzictwo znowu nie jest naturalne dla naszych mózgów. To, że jestem programistą, nie oznacza, że ​​mój syn byłby jednym z nich. Mówiąc ogólnie, ludzki mózg musi być przeszkolony do nauki OO, podczas gdy języki proceduralne są dla niego bardziej naturalne.

SoftwareRockstar
źródło
2
+1 - Ja również nie sądzę, że wzorce projektowe są niezbędne do nauczania OOP na poziomie podstawowym, możesz być dobrym programistą OOP i nie znać żadnego wzorca projektowego. Z drugiej strony widać, że znane wzorce projektowe wyłaniają się naturalnie od dobrych programistów OOP. Wzory projektowe są zawsze odkryte, a nie wynalezione.
Gary Willoughby,
1
+1 - Świetna odpowiedź. Podoba mi się czwarty punkt, który powiedziałeś. To prawda, że można być dobrym programistą OO, nie wiedząc, jakie naprawdę są wzorce projektowe!
Karthik Sreenivasan
Zgadzam się z punktem 4, ponieważ większość wzorców projektowych to nic innego jak podejście gumy balonowej / taśmy izolacyjnej do kodowania ekspresyjnego wokół ograniczeń języka. W innych paradygmatach wzorce projektowe mogą być zupełnie inne i oparte na własnych ograniczeniach. Nie zgadzam się z 2, LINQ i lambdas są nadal wykonywane w sposób proceduralny, po prostu zapewniają starannie zapakowane abstrakcje wyższego poziomu. Poświęć trochę czasu na rozwój z dynamicznie wpisywanym językiem proceduralnym / funkcjonalnym, takim jak JavaScript, a zobaczysz, co mam na myśli.
Evan Plaice,
6

Myślę, że wielu programistów ma trudności z początkowym projektowaniem i planowaniem na początek. Nawet jeśli ktoś wykona dla ciebie cały projekt, nadal możesz oderwać się od zasad OOP. Jeśli wezmę garść kodu spaghetti i wrzucę go do klasy, czy to naprawdę OOP? Ktoś, kto nie rozumie OOP, może nadal programować w Javie. Nie myl też trudności w zrozumieniu z niechęcią do stosowania określonej metodologii lub nie zgadzania się z nią.

JeffO
źródło
5

Powinieneś przeczytać Objects Never? Cóż, prawie nigdy. (Wymagane członkostwo w ACM) przez Mordechai Ben-Ari, który sugeruje, że OOP jest tak trudne, ponieważ nie jest to naturalny paradygmat, który jest czymś naturalnym. (Chociaż mam zastrzeżenia do tego artykułu, ponieważ nie jest jasne, jakie kryteria jego zdaniem program musi spełnić, aby powiedzieć, że jest napisany na paradygmacie OOP w przeciwieństwie do paradygmatu proceduralnego używającego języka OO).

Ken Bloom
źródło
5

Programowanie obiektowe samo w sobie nie jest trudne.

Trudność polega na tym, aby robić to dobrze. Gdzie umieścić wycięcie między kodem, aby łatwo przenieść rzeczy do wspólnego obiektu podstawowego i rozszerzyć je później? Jak sprawić, by Twój kod był użyteczny dla innych (rozszerzanie klas, zawijanie serwerów proxy, metoda przesłonięcia) bez przeskakiwania przez obręcze, aby to zrobić.

To jest trudna część, a jeśli zrobione dobrze, może być bardzo eleganckie, a jeśli zrobione źle, może być bardzo niezdarne. Moje osobiste doświadczenie jest takie, że potrzeba dużo praktyki, aby być we wszystkich sytuacjach, w których ŻYCZYŁEŚ, abyś zrobił to inaczej, aby tym razem zrobić to wystarczająco dobrze .

użytkownik1249
źródło
„Moje osobiste doświadczenie polega na tym, że trzeba dużo ćwiczyć we wszystkich sytuacjach, w których chciałbyś, abyś zrobił to inaczej, aby tym razem zrobić to wystarczająco dobrze”. OOP wydaje się być skodyfikowaną listą sposobów, aby nie zrobić tego źle, co nie ma sensu, dopóki nie zrobisz tego źle.
Jared Updike,
@Jared, niezupełnie. Porównaj to do rozwiązywania sodukus. Istnieją różne sztuczki, które możesz zrobić, aby je rozwiązać, ale zajmuje to dużo czasu i ćwiczysz, aby robić to dobrze bez cofania się.
Jeśli ktoś myśli o „wspólnym obiekcie podstawowym” jak o wspólnym przodku, staje się jasne. To naprawdę takie proste. Trudno jest zrozumieć, że istnieje tak wiele mylących wyjaśnień od ludzi próbujących wyglądać mądrze.
annoying_squid
4

Właśnie oglądałem wideo Richarda Feynmana omawiające, w jaki sposób ludzie mogą mieć zupełnie inne metodologie w głowie, myśląc - mam na myśli zupełnie inną sytuację.

Kiedy robię projektowanie na wysokim poziomie, zdarza mi się wizualizować obiekty, widzę je, widzę ich interfejsy i widzę, jakie ścieżki muszą przechodzić informacje.

Mam również problemy z zapamiętywaniem szczegółów i uznałem, że OO jest świetną pomocą organizacyjną - dużo łatwiej jest znaleźć funkcjonalność niż skanowanie luźno zorganizowanej listy podprogramów.

Dla mnie OO było wielką korzyścią, ale jeśli nie wizualizujesz w ten sam sposób lub nie robisz architektury wysokiego poziomu, prawdopodobnie jest to bezcelowe i denerwujące.

Bill K.
źródło
+1 Czuję to samo, ale jest wiele pchnięć w przeciwnym kierunku, w tym mixy Ruby ... co sprawia, że ​​zdajesz sobie sprawę, że ścisłe OO nie jest dla wszystkich.
Dan Rosenstark,
@ Yar Tak, właśnie to mówiłem. Chociaż osobiście nie mogę sobie wyobrazić nic lepszego (a Ruby przywiozła mnie NUTS za rok, w którym go użyłem), zaczynam rozumieć, że każdy ma inny sposób postrzegania tego. Może niektórzy ludzie używają dotyku lub słuchu podczas myślenia zamiast wizualizacji, a OO po prostu ich nie uruchamia.
Bill K
Myślę, że pomaga to również zachęcać do bardziej naturalnych konwencji nazewnictwa. Nie musisz już kodować typu funkcji w nazwie funkcji (jak INSTR) - ponieważ nazwa jest dołączona do typu (jak string::find)
Ken Bloom
@Ken, chociaż się zgadzam, myślę, że jest to bardziej kwestia silnego pisania niż OO - Ruby ma OO, ale tracisz wiele informacji o typie z powodu pisania kaczki - Ruby zwykle mówi „wyślij (to)” i oczekuje abyście wiedzieli, jaką magiczną metodę „to” musi zastosować, aby działać.
Bill K
@ Bill, masz rację. To bardziej kwestia języków, które obsługują programowanie ogólne. Możesz uzyskać ładne naturalne konwencje nazewnictwa z systemami modułowymi i typowymi dla klas, takimi jak Haskell, i nie ma w tym przypadku żadnych innych ograniczeń. Gdyby C miał przeciążenie, można by uzyskać takie same nazwy rodzajowe w C.
Ken Bloom
4

Zrobiłem programowanie GW-Basic i Turbo Pascal dość długo, zanim zapoznałem się z OO, więc początkowo MÓGŁEM się tym zająć.

Nie mam pojęcia, czy tak dzieje się z innymi, ale dla mnie było tak: mój proces myślenia o programowaniu był czysto proceduralny. Jak w: „takie i takie się zdarzają, a następnie takie i takie mają miejsce w następnej kolejności” itp. Nigdy nie uważałem, że zmienne i dane są czymś więcej niż przelotnymi aktorami w przebiegu programu. Programowanie to „przepływ działań”.

Przypuszczam, że to, co nie było łatwe do uchwycenia (tak głupio, jak mi się teraz wydaje), to pomysł, że dane / zmienne naprawdę naprawdę mają znaczenie , w głębszym sensie, niż bycie ulotnymi aktorami w „przepływie” programu. Innymi słowy: próbowałem zrozumieć to, co się dzieje , a nie to , co jest , co jest prawdziwym kluczem do uchwycenia tego.

Stoły Bobby'ego
źródło
Ciekawy punkt widzenia. Kiedy staram się zrozumieć sensowne projekty C ++, myślę, że jestem odwrotny, myśląc przede wszystkim o danych, „ścieżce sygnału” bitów od pewnego „wejścia” do jakiegoś „wyjścia”. Podczas gdy ja również robiłem dużo Basic i Pascal, moje najwcześniejsze myślenie techniczne dotyczyło elektroniki.
DarenW,
3

Nie sądzę, że trudno to zrozumieć, ale może się zdarzyć, że wielu programistów pytających jest nowością w koncepcji, pochodzących z języków proceduralnych.

Z tego, co widziałem / czytałem wiele osób (przynajmniej na forach) szukaj „wyniku” z OOP. Jeśli jesteś programistą, który nie wraca i nie modyfikuje rozszerzenia swojego kodu, prawdopodobnie trudno będzie zrozumieć korzyści.

Ponadto istnieje wiele złych OOP, jeśli ludzie czytają / widzą to, łatwo jest zrozumieć, dlaczego mogą być dla nich trudne.

IMO musisz poczekać, aż „kliknie” lub zostać nauczonym przez kogoś z prawdziwą wiedzą, nie sądzę, że możesz się spieszyć.

DBlackborough
źródło
5
Jeśli pochodzisz ze środowiska akademickiego, rodzaje programów zabawek, które tam piszesz, w OOP również wydają się bezcelowe. Zacząłem uczyć się języka C na studiach i było to łatwe do zrozumienia, ponieważ każdy program miał 1 stronę, mniej niż 100 linii. Następnie próbujesz nauczyć się OOP, a to wszystko wymaga tego całego bagażu i narzutów na przedmioty, i wydaje się to bezcelowe. Ale dopóki nie napiszesz programu obejmującego wiele plików i kilka tysięcy wierszy, trudno zrozumieć, dlaczego jakiś styl programowania jest użyteczny.
CodexArcanum
3

Myślę, że dla wielu osób OOP jest trudne, ponieważ narzędzia tak naprawdę nie ułatwiają tego.

Dzisiejsze języki komputerowe są abstrakcją tego, co dzieje się na komputerze.

OOP to abstrakcyjny sposób reprezentowania abstrakcji.

Tak więc używamy abstrakcji do budowania abstrakcji za pomocą abstrakcji. Dodaj do tego, że to, co abstraktujemy, to zwykle bardzo złożone interakcje fizyczne / społeczne i, cóż, nic dziwnego.

ElGringoGrande
źródło
2

Mam blog o nazwie „Struggles in Object Oriented Programming”, który powstał w wyniku niektórych moich problemów z nauką tego. Myślę, że szczególnie trudno było mi to zrozumieć, ponieważ spędziłem tyle czasu na programowaniu proceduralnym i miałem trudność z myśleniem o tym, że obiekt może być reprezentowany przez zbiór atrybutów i zachowań (byłem przyzwyczajony do po prostu zbiór zmiennych i metod).

Ponadto istnieje wiele pojęć, które sprawiają, że język jest zorientowany obiektowo - dziedziczenie, interfejsy, polimorfizm, kompozycja itp. Naprawdę wiele można się nauczyć na temat teorii tego języka, zanim będzie można faktycznie pisać kod w sposób zorientowany obiektowo sposób, podczas gdy w przypadku programowania proceduralnego, jest to po prostu kwestia zrozumienia rzeczy, takich jak przydział pamięci dla zmiennych i wywołania punktu wejścia do innych metod.

Tim Claason
źródło
Zgadzam się - duża trudność, jaką ludzie mają z OO, polega na tym, że nauczyli się myśleć „proceduralnie”. W OO nie ma nic z natury trudnego, ale jeśli „znasz” techniki proceduralne, byłoby niespodzianką zobaczyć inny sposób ustrukturyzowania rzeczy.
Kirk Broadhurst
Bez wątpienia jest to zupełnie inny sposób myślenia niż programowanie proceduralne. Ale wbrew temu, co wielu mówi, nie jest to A) nienaturalny sposób myślenia i B) skomplikowany. Po prostu myślę, że nie nauczono tego dobrze.
annoying_squid
2

Motywacja. Trudniej jest się czegoś nauczyć, gdy nie rozumiesz dlaczego, a także wtedy, gdy nie możesz spojrzeć na to, co zrobiłeś, i stwierdzić, czy zrobiłeś to dobrze, czy nie.

Potrzebne są małe projekty, które wykorzystują OO do robienia użytecznych rzeczy. Proponuję przejrzeć książkę o wzorach projektowych i znaleźć taki, który jest oczywiście przydatny i dobrze współpracuje z OO. (Użyłem Strategii za jednym razem, gdy ją wypróbowałem. Coś takiego jak Flyweight lub Singleton byłoby złym wyborem, ponieważ są to sposoby używania obiektów w ogólności, a nie używania obiektów do osiągnięcia czegoś.)

David Thornley
źródło
Ludzie zawsze mówią gówno o Singletonie, ale potem jest zawsze zapraszany na przyjęcie. Ale to prawda, on nie jest OO OO DP.
Dan Rosenstark,
-1

Myślę, że zależy to od wieku (wiek jako wskaźnik doświadczenia) i, co ważniejsze, zainteresowania. Jeśli jesteś „młody” (to znaczy być może zielony) i nigdy nie myślałeś w inny sposób, wydaje się to całkiem proste. Z drugiej strony, jeśli uważasz, że jest to najfajniejsza rzecz, jaką kiedykolwiek widziałeś - przytrafiło mi się w wieku 28 lat lub coś w tym rodzaju - łatwo się zdziwić.

Z drugiej strony, jeśli myślisz, podobnie jak wielu moich studentów Javy, „dlaczego się tego uczymy, to tylko moda”, praktycznie nie można się tego nauczyć. Dotyczy to większości technologii.

Yar
źródło
1
OO, moda? Ile lat mają twoi uczniowie - podejrzewam, że ta „moda” jest starsza niż oni (pierwszy OO, który zrobiłem - o czym wiedziałem, że to był - był Simula około 1983/4 i Simula nie była w tym momencie nowa)
Murph
@Murph Było to około 2004-2005, a studenci mieli zdecydowanie ponad 45-50 lat (profesjonalni programiści z Iberii).
Dan Rosenstark,
ok, widzę, że mogli przegapić początek sprawy z OO. Ale do roku 2004/5 byliśmy już w wersji .NET, która jest prawie od ściany do ściany OO (-: Są rzeczy w fazie rozwoju, które można opisać jako mody, ale te, które się nie mżą, szybko ewoluują w dobre rzeczy
Murph,
1
@Murph, szczerze mówiąc, ci faceci byli programistami komputerów mainframe, których próbowali przekonwertować na Javę. To było naprawdę zabawne i wyjątkowe doświadczenie (nie jest to normalna opłata za moje dni trenera Java). Prawdą jest jednak, że widzieli wiele rzeczy, które przychodzą i odchodzą, ale oczywiście OO to coś więcej niż tylko moda. Oddzielna uwaga: miałem nadzieję, że to testowanie jednostkowe rozwali się jak moda, ale teraz okazuje się, że mam dużo testów jednostkowych do napisania ... :)
Dan Rosenstark
-1

Bez względu na wybrany paradygmat (OOP, funkcjonalny itp.), Aby napisać program komputerowy, musisz wiedzieć, jakie kroki wykona Twój program.

Naturalnym sposobem definiowania procesu jest zapisywanie jego kroków, w przypadku większych zadań dzielisz je na mniejsze kroki. To jest procedura, tak działa komputer, w ten sposób krok po kroku przeglądasz listę kontrolną.

OOP to inny sposób myślenia. Zamiast myśleć o liście kontrolnej zadań, które należy wykonać krok po kroku, myślisz o przedmiotach, ich umiejętnościach i relacjach. Więc napiszesz wiele obiektów, małych metod, a twój program będzie działał magicznie. Aby to osiągnąć, musisz przekręcić umysł ...

I dlatego OOP jest trudne. Ponieważ wszystko jest przedmiotem, wszystko, co robią, polega na proszeniu innych obiektów o zrobienie czegoś, a te inne przedmioty w zasadzie robią niektóre. Tak więc sterowanie w programie OOP może gwałtownie przeskakiwać między obiektami.

Calmarius
źródło
-1

Jako osoba, która obecnie uczy się programowania i ma pewne problemy w tym obszarze, nie sądzę, aby koncepcja była tak trudna do zrozumienia, jak konkretne jej implementacje. Mówię to, ponieważ mam pomysł na OOP i używam go w PHP przez około rok, ale kiedy przechodzę do C # i patrzę na wykorzystanie obiektów przez innych programistów, stwierdzam, że wiele osób robi to na różne sposoby których po prostu nie rozumiem. Właśnie to doprowadziło mnie do lepszego zrozumienia zasad OOP.

Oczywiście zdaję sobie sprawę, że problemem jest najprawdopodobniej mój brak doświadczenia z językiem ojczystym OOP i że z biegiem czasu znajdę nowe sposoby wykorzystania obiektów, które będą tak samo niejasne dla nowego programisty jak to, czym jestem obecnie doświadczam. Jerry Coffin dotyka tego kilka razy, szczególnie w swoim komentarzu:

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ść.

Uważam, że jest to bardzo dokładne, ponieważ to wrażenie, które często mam, widząc kogoś, kto tworzy klasy dla rzeczy, które tak naprawdę nie są rzeczami - konkretny przykład mi ucieka, ale najbliższy, jaki mogę wymyślić w locie, traktuje odległość jak obiekt (edytuję następnym razem, gdy zobaczę coś, co powoduje to samo zamieszanie). Czasami OOP wydaje się chwilowo lekceważyć własne zasady i staje się mniej intuicyjny. Zdarza się to najczęściej, gdy obiekty wytwarzają obiekty, dziedziczą od klasy, która je obudowuje, i tak dalej.

Myślę, że dla kogoś takiego jak ja, pomaga myśleć o obiektach jako mających wiele aspektów, z których jedna obejmuje traktowanie czegoś takiego jak obiekt, gdy inaczej by nie był. Coś w rodzaju odległości, z niewielkim przesunięciem paradygmatu, może wydawać się przedmiotem teoretycznym, ale nie takim, który można trzymać w dłoni. Muszę myśleć o tym jako o zestawie właściwości, ale bardziej abstrakcyjnym zestawie zachowań, takich jak dostęp do jego właściwości. Nie jestem pewien, czy jest to klucz do mojego zrozumienia, ale wydaje się, że to właśnie tam prowadzą moje obecne badania.

dsimer
źródło
1
Para punktów lub obiektów powinna być traktowana jako obiekt. I odległość należy przyjmować jako funkcję od obiektu. Używanie obiektów nie oznacza, że ​​tworzysz przedmioty ze wszystkiego.
Gangnus,
Jak powiedziałem, odległość była kiepskim przykładem. Jeśli chodzi o tworzenie obiektu ze wszystkiego, to odnoszę się konkretnie do tego, co widziałem, a nie do tego, co faktycznie zrobiłem - co na razie nie jest niczym.
dsimer
To zależy od języka - w SmallTalk odległość (i wszystko) JEST obiektem. Ale w C # wspominałeś, że byłoby źle.
Gangnus,
-2

Terminologie były dla mnie przeszkodą w nauce zasad programowania obiektowego (POOP). Kiedy zrozumiesz podstawy, elementy zaczynają się układać. Podobnie jak wszystkie rzeczy uczenie się nowych koncepcji jest trochę trudne.

Uzgodniono, że wzorce projektowe należy badać co najmniej równolegle do OOP.

lord-fu
źródło
-2

Głównym skokiem było dla mnie zrozumienie abstrakcyjnej koncepcji OOP. Teraz jestem zupełnie nowy w programowaniu. Programuję od roku do półtora roku, więc moje wprowadzenie do OOP dotyczyło ActionScript i Processing. Kiedy po raz pierwszy nauczyłem się kodowania ActionScript, nie było go w OOP. Nauczyłem się kodować bezpośrednio w panelu Operacje i w ten sposób poznałem podstawowe podstawy programowania (zmienne, funkcje, pętle itp.). Nauczyłem się więc, że robię coś bezpośrednio na scenę we Flashu lub Przetwarzaniu.

Kiedy pojawiło się OOP, uświadomienie sobie, że mogę tworzyć metody i właściwości w obiekcie, aby móc go używać i ponownie wykorzystywać, było początkowo trochę trudne. Wszystko było bardzo abstrakcyjne i trudne do przetworzenia, ale same języki programowania były znacznie lepsze, ale w pewnym sensie trzeba było zrobić krok naprzód, aby nawiązać te połączenia.

Kobby
źródło
wow, część tego nie miała żadnego sensu. „Wszystko było bardzo abstrakcyjne i trudne do przetworzenia między klasami i instancjami obiektów itp. Ale języki programowania stały się o wiele łatwiejsze do zrozumienia, kiedy dostałem OOP. Ale to trochę wymagało skoku faitl, aby nawiązać te połączenia na początku”
-2

Przepis

Dobre zrozumienie OOP = Dobry mentor lub dobre książki lub oba + Osobiste zainteresowania + Praktyka.

Zainteresowanie osobiste

Z mojego osobistego doświadczenia wynika , że osobiste zainteresowanie przechodzi długą drogę od przejścia od programowania proceduralnego do OOP z odpowiednimi opiniami mentorów lub dobrych książek lub razem .

Ćwicz, ćwicz i ćwicz

Moim najlepszym przyjacielem, aby lepiej zrozumieć OOP, była tylko praktyka. To zdecydowanie wzmocni twoje umiejętności OOP.

Jak mówi przysłowie: „Nie ma substytutu ciężkiej pracy ani skrótu do sukcesu”.

Powodzenia!

Karthik Sreenivasan
źródło