Wadą OOP? [zamknięte]

Zazwyczaj nie chcę znać szczegółów minusów UPS, ale czułem się trochę dziwnie, gdy pokłóciłem się na wywiadzie, w którym ostatnio uczestniczyłem. Pytanie, które zostało mi wysłane, to powiedzieć mi jedną wadę programowania obiektowego (OOP). W tym czasie czułem, że OOP jest najbardziej dojrzałym poziomem programowania po modelach proceduralnych i funkcjonalnych. Odpowiedziałam mu więc, że nie widzę żadnych negatywów.

Ale rozmówca powiedział, że jest kilka, poprosiłem go, żeby wymienił jedną, jeśli nie ma nic przeciwko. Dał przykład, że nie trawię dobrze. Powiedział, że wzór OOP nie ściśle wdraża zasady dziedziczenia i przytoczył przykład satelity / rakiety, w którym części ciała rozpadają się okresowo, aby usunąć wagę podczas startu rakiety i powiedział, że dziedziczenie nie obsługuje tego.

Jego przykład wydawał mi się bardzo dziwny, powodem było zastosowanie spadku do tego przykładu.

Rozumiem, że przykład, który podał, prawie nie miał żadnego sensu, ale miałem tę wątpliwość -

Czy możemy odłączyć hierarchie klas dynamicznie (jestem pewien w Javie nie jest to możliwe) w idealnej projektowanie obiektowe?

Author: bragboy, 2010-05-18

18 answers

Nie do końca rozumiem jego przykład.

Ważne jest jednak, aby zrozumieć, że OOP jest bardzo skuteczny dla rzeczy, które mogą być naturalnie modelowane za pomocą niego, i jest bardzo nieskuteczny dla innych rzeczy (np. przekrojowe obawy lub aspekty). Jest to jedna z wad OOP. Innym jest to, że często wiąże się z pewnym kosztem czasu pracy ze względu na dynamiczne wysyłanie.

Ponadto bardzo łatwo jest nadużywać OOP, aby robić bezsensowne abstrakcje. Posiadanie rakiety z ciała jest jednym przykład. Moje doświadczenie jest takie, że początkujący Programiści albo nie ufają i nie używają dziedziczenia, albo są zbyt chętni i używają go nieprawidłowo, gdy inne zachowania (takie jak agregacja) są bardziej odpowiednie. Z czasem doświadczenie i zrozumienie mechanizmu ulegają poprawie.

Nie jestem pewien, co miał na myśli mówiąc "wzorzec OOP nie ściśle implementuje reguł dziedziczenia", ponieważ OOP nie jest wzorcem. Jednym z potencjalnych problemów jest to, że można napisać Podtyp, który może naruszać zasadę Liskowa podstawienie, tak aby metoda nadpisywania nie zachowywała się "co najmniej" jak metoda nadpisywania. Nie ma możliwości automatycznego sprawdzania tego, więc możliwe jest pisanie kodu, który narusza zasady OOP.

Jeśli chodzi o twoje ostatnie pytanie " Czy możemy odłączyć hierarchie klas w idealnym obiektowo zorientowanym projekcie?", Nie jestem pewien, co masz na myśli. Jeśli pytasz o zmianę hierarchii w czasie wykonywania i uczynienie jej tak, aby relacja podtypowania przestała istnieć z jakiegoś punktu w egzekucja, więc tak. Jest to możliwe w niektórych językach, takich jak Smalltalk. Niektórzy twierdzą, że jest to "więcej OOP". W Smalltalku 'metody' obsługiwane przez typ są określane w punkcie wywołania metody na podstawie bieżącej hierarchii i bieżącej zawartości każdej klasy. Chociaż uwielbiam smalltalk, jest to jedna z funkcji, na której nie szaleję, ponieważ wolę sprawdzanie w czasie kompilacji z mniejszą ilością niespodzianek w czasie wykonywania.

 18
Author: Uri,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-05-17 22:54:34

tylko dlatego, że masz młotek, to nie znaczy, że wszystko jest gwoździem.

Odkryłem, że wiele osób często myli się, kiedy zastosować skład vs. dziedziczenie używając OOP jako stylu programowania. przykład, który przytoczyłeś z pytania wywiadu, wydaje się być przypadkiem tego rodzaju zamieszania.

Jedną z rzeczy, których nauczyłem się z doświadczenia, jest to, że podczas gdy dziedziczenie jest miłym paradygmatem ekspresji " IS-A" relacje między bytami w projekcie, często lepiej jest faworyzować kompozycję, niż dziedziczenie .

Ale przeanalizujmy sedno pytania ankieterów: Kiedy OOP jest wyborem paradygmatu?.

OOP najlepiej współpracuje z projektami wielkoskalowymi, wielomodułowymi. dla " rozwój w małych " - takich jak skrypty lub przetwarzanie transformacyjne, może wymagać dużej ilości kosztów, bez konieczności dodawania wartość. Ale nawet w takich przypadkach, o ile nie piszesz kodu odrzucającego, argumentowałbym, że duże rozwiązanie często ewoluuje od mniejszych, więc ustalenie struktury i rozdzielenie obaw na początku może zaoszczędzić ci smutku później.

Ostatecznie programowanie OOP wymaga również pewnego poziomu rygoru projektowego i planowania, a także zrozumienia podstawowych zasad orientacji obiektu . Jeśli nie chcesz poświęcić czasu na naukę i zrozumienie tych zasad ... cóż, być może programowanie OOP nie jest dla Ciebie.

Poza tym, pewne rodzaje problemów nadają się również do alternatywnych stylów programowania. Na przykład, przetwarzanie transformacyjne jest dość przydatne do funkcjonalnego stylu programowania - w którym wynik jest obliczany i przekazywany do kolejnych etapów transformacji w celu uzyskania ostatecznego wyniku. Problemy, w których musisz wyszukać lub odpytywać domenę o pewne pasujące informacje, są możliwe do języki zapytań (jak SQL), w których opisujesz swój zamiar deklaratywnie, a nie imperatywnie.

Jest w stanie rozpoznać, jakiego rodzaju problem rozwiązujesz przechodzi długą drogę w kierunku wyboru jakiego rodzaju języka lub narzędzia użyć. odpowiednie narzędzia mogą znacznie ułatwić pracę ... niewłaściwy może to utrudnić lub uniemożliwić.

 34
Author: LBushkin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-05-17 22:46:13

Chociaż zgadzam się z wnioskiem rozmówcy (OOP jest wadliwy), jego logika wydaje się być nonsensem. Wygląda na to, że krytykuje coś, czego nie rozumie, bo żaden Kompetentny programista OO nie sprawiłby, że rakieta odziedziczyłaby po swoich pędnikach.

Ludzie zrobili dobrą krytykę przeciwko OOP, choć. Na przykład egzekucja Steve 'a Yegge' a w Królestwie rzeczowników .

 15
Author: Chuck,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-05-17 22:50:16

Jego przykład nie ma sensu. Rakieta nie dziedziczy po ciele. "Ma" ciało. To zabezpieczenie. Więc w pewnym momencie "usuniesz" część przymocowaną do rakiety, gdy została wyrzucona.

 11
Author: jmucchiello,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-05-17 22:26:06

Chociaż nie do końca rozumiem podany przykład, ponieważ dla mnie brzmi to jak kompozycja Dam wadę OOP

OO jest trudne do przetestowania

  • Brak bezpośredniego dostępu do zmiennych/atrybutów klasy do odczytu/zapisu-może być konieczne wprowadzenie getterów i seeterów, które przerywają ubezwłasnowolnienie.

  • Dziedziczenie może zmienić zachowanie metody w podklasie

  • Obiekty mają stan. Może być trudno wygenerować te stany, ponieważ my zależy od publicznego interfejsu.

  • Klasy ze spójnością loh mogą być trudne do przetestowania, ponieważ może to oznaczać, że Klasa robi więcej niż jest określona.

 9
Author: Robben_Ford_Fan_boy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-05-17 22:38:36

Widzę, do czego zmierzał. Myślę, że argument był w zasadzie skoncentrowany wokół wady dziedziczenia - jeśli nie jesteś ostrożny, lub jeśli dziedziczysz zbyt wiele razy, aby nadal rozszerzać funkcjonalność, możesz skończyć z nadętym bałaganem klasy z ładunkiem zbędnych funkcji i brakiem spójności.

Jego analogia działa, jeśli weźmiemy pod uwagę, że gdy rakieta spali paliwo w segmencie, segment staje się zbędny, a tym samym martwy. Rakieta może Odrzuć segment, ale nie sądzę, aby można było wykluczyć sekcje klasy, której nie chcesz dziedziczyć (chociaż popraw mnie, jeśli się mylę, bo brzmi to pożytecznie).

 3
Author: Moonshield,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-05-17 22:34:28

Czy przykład rakiety mógł nawiązywać do faktu, że w wielu obiektowych językach typ obiektu jest niezmienny? Oznacza to, że jeśli posiadam obiekt Student, a osoba, którą reprezentuje, kończy studia i staje się pracownikiem, nie mogę przekształcić obiektu Student w obiekt Employee. Muszę stworzyć nowy, stracić tożsamość obiektu w procesie, a w konsekwencji zaktualizować wszystkie odniesienia wskazujące na byłego ucznia.

Oczywiście taka cecha przeszkadzałaby typowanie statyczne (Typ niezmienny, że typ obiektu jest podtypem typu statycznego dowolnego odniesienia wskazującego na niego). Ale w niektórych kontekstach elastyczność może być tego warta.

 2
Author: meriton,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-05-17 23:09:34

Klasykiem jest preferowanie kompozycji nad dziedziczeniem. Dziedziczenie jest tam, aby uchwycić abstrakcje wzdłuż szwu, że Twój system różni się wzdłuż.

Jeśli nie do końca uchwycisz tę abstrakcję, to tak, dostaniesz dziwne siły na swoich projektach. Ale jest to problem programowania w świecie, w którym abstrakcje nie są całkiem odpowiednie dla tego, co próbujesz osiągnąć. Nie, żeby kiedykolwiek były idealne.

 1
Author: Keith Nicholas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-05-17 22:32:25

Przeczytaj ten doskonały artykuł na temat Dlaczego rozszerzenia są złe . To powiedziawszy, nie mogę powiedzieć, że jest to con programowania zorientowanego obiektowo.

Twoim ideałem dla statku kosmicznego jest Czarny Obelisk z 2001: Odyseja kosmiczna.

 1
Author: Alexander Pogrebnyak,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-05-17 22:39:42

Największą wadą, jaką przychodzi mi do głowy z OOP, jest brak wsparcia dla funkcji wyższego rzędu. Chociaż można przekazać obiekt zawierający metodę, jest to gadatliwe i nieefektywne. Znacznie lepiej byłoby móc przejść w funkcji bezpośrednio do innej funkcji.

 1
Author: Robert,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-05-17 22:45:15

Dotyczące niepotrzebnych metod w klasach nadrzędnych: Czy nie są oznaką złej architektury? Chodzi mi o to, czy nie powinno się wyodrębnić na etapie strugania funkcjonalności potrzebnych każdej klasie, a następnie mieć łańcuch klas pochodną jednej od drugiej?

Na przykład mamy klasy A, B, C i D. Klasa A ma metody klasy B, C I d. Klasa B ma metody potrzeby klasy D. Możemy więc wyprowadzać klasę D z B i B z A. z drugiej strony będziemy wyprowadzać C z A, ponieważ C nie potrzebuje rzeczy B ma. Więc w zasadzie rozwiązaliśmy problem posiadania niepotrzebnych rzeczy, dodając jedną dodatkową klasę w hierarchii. Oczywiście, gdyby coś takiego nie zostało złapane na etapie planowania i Klasa B została użyta jako klasa bazowa, trudniej byłoby podzielić klasę B na dwie klasy, ale przy dodatkowym wysiłku rozwiązano problem niepotrzebnego bagażu.

 1
Author: AndrejaKo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-05-17 22:48:18

Jestem pewien, że nigdy nie słyszałem o statycznie wpisywanym języku, takim jak Java, który jest w stanie przekształcić obiekt w inny, pozostawiając odniesienie do obiektu nienaruszone, ale jestem pewien, że można to sfałszować delegatami itp. To powiedziawszy, bez fundamentalnie dobrej myśli, prawdopodobnie byłby bałagan.

Nie wiem, jak rozmówca przedstawił pytanie lub jak odpowiedziałeś, ale jednym z największych krótkich wpadek OOP nie jest tak naprawdę sam OOP. To słabe wykorzystanie OOP i złe " IS-A" relacje ludzie próbują tworzyć. Jeśli jedynym powodem, dla którego możesz wymyślić hierarchię dziedziczenia, jest ponowne użycie kodu, jest to zły powód. AOP można twierdzić, że jest to lepsze podejście do tego problemu. (zanim zagłosujesz, pamiętaj, że powiedziałem "może być")

OOP jest o interfejsie i typie, a nie o implementacji. Wiedząc, że obiekt może zwrócić listę kandydatów do pracy, to wszystko, co muszę wiedzieć. Niezależnie od tego, czy pochodzi z RDBMS, column oriented db, web service, czy nawet arkusz kalkulacyjny jest nieistotny. Wiem, że mogę przekazać ten obiekt jako parametr innym metodom i mogą one wywołać "FetchJobCandidates" i Wiem, że dostanie kandydatów do pracy. Po drodze są pułapki, ale przede wszystkim, jeśli myślisz o klasach opartych na tym, co wystawiają reszcie świata, a nie na to, co robią wewnętrznie, jesteś na lepszej stopie IMO.

 1
Author: Jim L,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-05-17 23:57:17

Możemy po prostu powiedzieć użyj tego w OOP?

RocketShip.BodyPart1 = nothing or

RocketShip.BodyPart1.isDetached = false?

Uważam, że nie jest to wina samego OOP, ale ograniczenie języka programowania używanego do jego implementacji.

 1
Author: paul,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-05-20 09:07:00

Spójrz na te artykuły . Istnieją różne wyjaśnienia niektórych wad OOP, szczególnie zagrożeń związanych z zmuszaniem rzeczy do hierarchii, jak w przykładzie twojego rozmówcy.

 1
Author: finnw,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-05-20 10:02:51

Jednym ze sposobów modelowania obiektu, który zmienia swoją podklasę, jest użycie wzorca stanu . Korzystając z twojego pytania z wywiadu i pomocy Wikipedii , Oto kod Javy, który pokazuje, jak możesz modelować przejścia stanu, gdy rakieta przechodzi przez różne etapy. Nie pokazałem etapów modułu dowodzenia, ale podążają one za podobnym wzorcem poprzez zejście na Księżyc, wejście na Księżyc, spotkanie na księżycowej orbicie i powrót na Ziemię. Prawdopodobnie znajdziesz znacznie więcej ciekawe zachowania do dodania do interfejsu ISpaceShipState.

public class SpaceShip {
    private ISpaceShipState m_state = new SaturnFiveState();

    public void setState(ISpaceShipState state) {
        m_state = state;
    }

    public void jettison() {
        m_state = m_state.transition();
    }

    public int getStageNumber() {
        return m_stage.getStageNumber();
    }

    public int getNumberOfRocketMotors() {
        return m_stage.getNumberOfRocketMotors();
    }

    public String getRocketMotorTypeName() {
        return m_stage.getRocketMotorTypeName();
    }
}

interface ISpaceShipState {
    public ISpaceShipState transition();
    public int             getStageNumber();
    public int             getNumberOfRocketMotors();
    public String          getRocketMotorTypeName();
}

public class SaturnFiveState implements ISpaceShipState {
    public ISpaceShipState transition() {
        return new SaturnFiveSecondStageState();
    }

    public int getStageNumber() {
        return 1;
    }

    public int getNumberOfRocketMotors() {
        return 5;
    }

    public String getRocketMotorTypeName() {
        return "F-1";
    }
}

public class SaturnFiveSecondStageState implements ISpaceShipState {
    public ISpaceShipState transition() {
        return new SaturnFiveThirdStageState();
    }

    public int getStageNumber() {
        return 2;
    }

    public int getNumberOfRocketMotors() {
        return 5;
    }

    public String getRocketMotorTypeName() {
        return "J-2";
    }
}

public class SaturnFiveThirdStageState implements ISpaceShipState {
    public ISpaceShipState transition() {
        return new SaturnFiveCommandModuleState();
    }

    public int getStageNumber() {
        return 3;
    }

    public int getNumberOfRocketMotors() {
        return 1;
    }

    public String getRocketMotorTypeName() {
        return "J-2";
    }
}

Czy możemy dynamicznie (jestem pewien, że w Javie nie jest to możliwe) odłączać hierarchie klas w idealnej konstrukcji obiektowej?

Możliwe jest symulowanie dynamicznego pisania w Javie za pomocą reflection, chociaż kod jest bardzo niezgrabny w porównaniu do tego samego w języku pisanym dynamicznie.

 1
Author: richj,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-05-20 10:29:52

Myślę, że główną wadą jest jego moc. Jedną z najczęstszych rzeczy robionych w OOP jest zastąpienie klas nadrzędnych klasami pochodnymi w niektórych miejscach, aby specjalizować się w zachowaniu kodu. Cóż, jeśli nie zrobi się tego ostrożnie, łatwo jest unieważnić niektóre z założeń przyjętych w kodzie rozmówcy; i to może być bardzo trudne do wykrycia podczas przeglądania kodu, ponieważ typy, które widzisz zadeklarowane, nie są tymi, które są faktycznie używane.

W skrócie: polimorfizm może być niewyraźny i dlatego łatwo przeoczyć dziwne zachowania w klasach pochodnych.

 1
Author: fortran,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-05-20 12:38:05

Inni już to omówili, ale jeśli się nad tym zastanowić, nie wszystko jest przedmiotem. W informatyce nic nie jest tak naprawdę przedmiotem. Po prostu abstrakujemy pojęcie przedmiotu.

Na przykład skały składają się z materii. Możemy myśleć o skałach jako o obiektach w kategoriach obliczeniowych (terminy OOP), ale to nie pomaga w programowaniu wokół pojęcia skały.

Jeśli myślisz o głównych pojęciach programowania obiektowego; enkapsulacji, polimorfizmie, klasach, spadek.. istnieją problemy z tymi wszystkimi podstawowymi koncepcjami OOP.

 1
Author: Berlin Brown,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-03-13 05:32:15

Może coś w rodzaju problemu koła-elipsy

 1
Author: sa_nyc,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-12-11 00:28:23