Czy OOP staje się łatwiejsze czy trudniejsze? [Zamknięte]

36

Kiedy koncepcje programowania obiektowego zostały wprowadzone do programistów wiele lat temu, wygląda to interesująco, a programowanie jest czystsze. OOP był taki

Stock stock = new Stock();
stock.addItem(item);
stock.removeItem(item);

Łatwiej było to zrozumieć dzięki samoopisowej nazwie.

Ale teraz OOP, ze wzorcem takim jak obiekty transferu danych, obiekty wartości, repozytorium, wstrzykiwanie zależności itp., Stało się bardziej złożone. Aby osiągnąć powyższe, konieczne może być utworzenie kilku klas (np. Streszczenie, fabryka, DAO itp.) I zaimplementowanie kilku interfejsów

Uwaga: nie jestem przeciwny najlepszym praktykom, które ułatwiają współpracę, testowanie i integrację

tunmise fasipe
źródło
23
Stworzenie dobrej architektury oprogramowania zawsze było trudne i (najprawdopodobniej) zawsze będzie.
johannes
6
Zmieniłbym nazwę addItemna addi removeItemdla remove. Ponieważ jest łatwiejszy do odczytania. stock.add(item)lub stock.remove(item). I bardziej zorientowany na OOP.
razpeitia
1
Oryginalny OOP nie wyglądał prawie tak, jak pokazałeś. W OOP nie chodzi o składnię , chodzi o rodzaj abstrakcji spopularyzowanej przez Smalltalk. To niekoniecznie dowodzi, że twój punkt jest błędny, ani przesłanka nie jest wadliwa; raczej jest to nawet bardziej prawdziwe, niż się wydaje.
Konrad Rudolph,
1
porównujesz jabłka i pomarańczy, według logiki, wtedy programowanie imperatywne (tj. pętle i warunek if) jest prostsze niż wszystkie rzeczy, które mamy dzisiaj. Programowanie imperatywne to elementy składowe klas / OOP, a klasy / OOP to elementy konstrukcyjne wzorców projektowych. W miarę postępów sprawy stają się bardziej złożone, ponieważ rozwiązujesz bardziej złożone problemy.
Lie Ryan,
2
@LieRyan - widziałem, jak problemy stają się skomplikowane tylko dlatego, że nikt nie był w stanie ich rozwiązać za pomocą prostego programowania imperatywnego i zaatakował je wzorami projektowymi na OOP oprócz prostego rozwiązania imperatywnego, które powinno być wdrożone samodzielnie.
mouviciel

Odpowiedzi:

35

Sam OOP niewiele się zmienił od samego początku. Zbadano kilka nowych punktów widzenia, ale podstawowe zasady są nadal takie same. Co więcej, zbiorowa wiedza gromadzona przez lata sprawia, że ​​życie programisty jest łatwiejsze niż trudniejsze. Wzory projektowe nie stanowią przeszkody; stanowią zestaw narzędzi do rozwiązywania standardowych problemów, destylowanych na podstawie wieloletniego doświadczenia.

Dlaczego więc dzisiaj postrzegasz OOP jako bardziej złożony niż wtedy, gdy zacząłeś go używać?

Jednym z powodów może być to, że kod, na który jesteś narażony, staje się bardziej złożony - nie dlatego, że OOP stał się bardziej skomplikowany, ale dlatego, że zrobiłeś postępy w drabinie uczenia się i możesz czytać większe i bardziej złożone podstawy kodu.

Innym powodem może być to, że chociaż paradygmat złożoności się nie zmienił, rozmiar i złożoność przeciętnego projektu oprogramowania może równie dobrze mieć. Mając moc obliczeniową dostępną w telefonach komórkowych klasy klienta, która byłaby mokrym marzeniem dewelopera na serwerze mniej niż dwie dekady temu, opinia publiczna zasadniczo oczekuje sprytnych animowanych graficznych interfejsów użytkownika nawet dla najtańszej aplikacji do rzucania, a komputery stacjonarne klasy podstawowej są mocniejsze niż „superkomputer” z lat osiemdziesiątych, naturalne jest, że poprzeczka została podniesiona od początków Smalltalk i C ++.

Jest też fakt, że we współczesnych aplikacjach współbieżność i równoległość są raczej normą niż wyjątkiem, a aplikacje często muszą komunikować się między różnymi maszynami, generując i analizując całe zoo protokołów. Chociaż OOP jest świetny jako paradygmat organizacyjny, ma swoje ograniczenia, podobnie jak każdy inny paradygmat: na przykład nie zapewnia dużej ilości abstrakcji dla współbieżności (większość implementacji jest mniej więcej przemyślana lub całkowicie zlecana bibliotekom) , i nie jest to najlepsze możliwe podejście do budowania parserów i przekształcania danych. Współczesne programowanie często napotyka ograniczenia paradygmatu OOP, a wzorce projektowe mogą cię zaprowadzić. (Osobiście, Uważam, że potrzebujemy wzorców projektowych, co jest tego oznaką - jeśli paradygmat zapewniłby te rozwiązania od razu po wyjęciu z pudełka, byłoby bardziej wyraziste dla tych problemów, a standardowe rozwiązania byłyby oczywiste. Nie ma wzorca projektowego opisującego dziedziczenie metody, ponieważ jest to podstawowa cecha OOP; ale istnieje wzorzec fabryczny, ponieważ OOP nie zapewnia oczywistego naturalnego sposobu konstruowania obiektów polimorficznie i przezroczysto.)

Z tego powodu większość współczesnych języków OOP zawiera funkcje innych paradygmatów, co czyni je bardziej ekspresyjnymi i potężnymi, ale także bardziej złożonymi. C # jest tego najlepszym przykładem: ma oczywiste korzenie OOP, ale funkcje, takie jak delegaty, zdarzenia, wnioskowanie o typie, warianty typów danych, atrybuty, anonimowe funkcje, wyrażenia lambda, generyczne itp., Pochodzą z innych paradygmatów, w szczególności programowania funkcjonalnego .

tdammers
źródło
Wzorce projektowe dodały złożoności. Znaczące wzorce projektowe niekoniecznie są OOP, ale dodane w celu zwiększenia OOP.
tunmise fasipe
@tunmisefasipe: Niezupełnie. Wzory projektowe to tylko sprawdzone rozwiązania standardowych problemów; nie są one „dodatkiem” do OOP, ale konsekwencją. Złożoność już tam była; wzorce projektowe zapewniają strategie książek kucharskich, jak sobie z tym poradzić.
tdammers
17

Nie, staje się coraz bardziej przeprojektowany. I masz rację - na czacie SO C ++ często żartujemy z AbstractSingletonFactoryProxyBeanBridgeAdapterManagers, które widzimy w kodzie Java.

Ale dobry kod nie wykazuje tej właściwości. W dobrym kodzie nadal możesz powiedzieć

std::stack<int> s;
s.push(5);
s.pop();
DeadMG
źródło
4
Nie wynika to jasno z twojego postu, ale myślę, że nadmiar inżynierii jest widoczny zarówno w kodzie Java, jak i C ++. Nie jest to właściwość żadnego języka jako takiego, ale praktyki programistów ... Oba języki pozwalają na pisanie dobrego kodu, chociaż żaden (IMO) nie jest specjalnie do tego odpowiedni :) Struktury w Javie niestety są do kitu.
Andres F.,
12
Mówiąc o nadmiernej inżynierii, ten wątek jest obowiązkowy: dyskusji.joelonsoftware.com/default.asp?joel.3.219431
Bezpieczne
3
@AndresF. prawda, ale wydaje się, że nie dostajesz jej zbyt wiele w kodzie C ++, podczas gdy robisz to w Javie i .NET: wystarczy spojrzeć na wzorzec projektowy MVVMVMMD msdn.microsoft.com/en-us/magazine/hh965661.aspx jako jeden przykład tego, jak bierzesz „prosty kod” i klepniesz w niego wzór, aby wyglądał „łatwiej”, a następnie klepiesz inny wzór w wzór, ponieważ oryginalny wzór nie był tak prosty jak reklamowany. Nadmiar inżynierii staje się coraz bardziej powszechny.
gbjbaanb
5
Kłóciłbym się z „stawaniem się”. Nadmiar inżynierii jest tak stary jak inżynieria.
Gort the Robot
4
@AndresF. Na czacie szczególnie sprzeciwiamy się Javie, ale prawdą jest, że Java, bardziej niż C ++ , zachęca do nadmiernej inżynierii, ponieważ czyni ją bardziej przystępną cenowo (GC), a popularne biblioteki Java dla przedsiębiorstw spopularyzowały ten styl, jak zauważyłeś siebie.
Konrad Rudolph
10

Powiedziałbym, że problemy z „złożonością”, o których wspominasz, nie mają nic wspólnego z OOP. Ma to więcej wspólnego z rozwiązywaniem problemów.

Wiele lat temu pracowałem nad systemem, w którym klasa domeny była odpowiedzialna za ładowanie się z bazy danych, np

var userId = Request.QueryString["UserID"].ToInt();
var user = new User(userId);
user.Name = ...;
...
user.Save();

To jest bardzo przejrzysty kod. Nie ma problemu ze zrozumieniem tego. Problemem byłoby jednak testowanie kodu przez jednostkę. Mianowicie, w jaki sposób miałbym przetestować Userklasę bez konieczności ładowania jednej z bazy danych? Jak mam przetestować ten kod obsługi żądań internetowych bez dostępu do bazy danych? To po prostu niemożliwe.

Dlatego mamy wzorzec podobny do repozytorium, który oddziela odpowiedzialność za zarządzanie logiką domeny od użytkownika od funkcjonalności faktycznego ładowania i zapisywania jednego w magazynie danych. MKOl pomaga w zmniejszeniu sprzężenia, czyniąc kod bardziej testowalnym itp.

Więc jeśli wrócimy do przykładu, który piszesz, co zrobiłbyś z akcją po jej utworzeniu? Zapisz go w bazie danych

Stock stock = new Stock();
stock.addItem(item);
stock.removeItem(item);
this.StockRepository.Add(stock);

Ten czerwony! W postępie OOP nie ma ruchu, który sugeruje, że powinno być trudniej. Niestety, jeśli zdecydujesz się użyć mapera OR do kodu dostępu do danych, możesz mieć problem z tym, że maper OR nakłada ograniczenia na sposób pisania systemu. Ale to inna sprawa.

Jeśli jesteś nowy w tych wzorach, może być konieczne nauczenie się nowego stylu programowania. Ale ten styl programowania nie jest trudniejszy niż oldskulowe programowanie OOP.

Pete
źródło
Znasz wysiłek, jaki musisz podjąć, aby skonfigurować swoje repozytorium. Chociaż po skonfigurowaniu staje się wielokrotnego użytku.
tunmise fasipe
być może problem tkwi w testowaniu jednostkowym, gdybyśmy mieli lepsze narzędzia do testowania całości (jak i tak musisz) zamiast drobnych elementów, mielibyśmy systemy, w których było mniej błędów?
gbjbaanb
2
@gbjbaanb: już to mamy, nazywane testowaniem integracyjnym / funkcjonalnym. Testy jednostkowe służą innym, ale równie niezbędnym celom
Kevin
@gbjbaanb - Mamy już świetne narzędzia do testowania całego systemu / testów akceptacyjnych, np. Cucumber na platformie Rails. Ale zespoły, które są naprawdę dobre i piszą bardzo niewiele błędów, ale także dostarczają szybko, piszą wiele testów jednostkowych i tylko kilka testów ogólnosystemowych. Zobacz temat „Trójkąta testowego
Pete
4

Ani. Nasze problemy tak naprawdę się nie zmieniły; pasek dopuszczalnego kodu został podniesiony.

Aby osiągnąć powyższe, konieczne może być utworzenie kilku klas (np. Streszczenie, fabryka, DAO itp.) I zaimplementowanie kilku interfejsów

Nie musisz tego robić. Ale jeśli tego nie zrobisz, problemy się pojawią; problemy, które zawsze tam były. Teraz jednak programiści mają wystarczające doświadczenie, aby zidentyfikować te problemy i zapewnić mechanizmy ich łagodzenia (w razie potrzeby). Dowiadujemy się o nich więcej i wymyślamy lepsze rozwiązania (patrz - na przykład opinie programistów na temat singletonu).

Ale musisz także zdać sobie sprawę, że wprowadzenie programistów do OO (lub cokolwiek innego w tym zakresie) będzie miało tendencję do połykania w wyjątkowych okolicznościach. Po prostu łatwiej jest wytłumaczyć szczęśliwą ścieżkę i martwić się resztą, gdy początkujący ją znajdą. Nie ma srebrnej kuli; więc tak, przypuszczam, że rzeczy zawsze będą wydawać się trudniejsze, gdy sielankowe złudzenie zostanie złamane ...

Telastyn
źródło
3

Przykłady „wprowadzenie do OO” są o wiele prostsze niż aplikacje w świecie rzeczywistym. Potrzebujesz tylko jednej klasy, aby osiągnąć powyższe. Problem w tym, że niewiele robi. Niektóre wzorce projektowe próbują się zbliżyć (jak ActiveRecord.) Ale ostatecznie każdy przykład, który nie jest trywialny, będzie miał więcej niż jedną klasę; To dobrze.

Jeanne Boyarsky
źródło
Zauważ też, że struktury narastają z czasem. Więc tak, programowanie wymaga więcej wiedzy. Oznacza to również, że można zrobić więcej w krótszym czasie.
Jeanne Boyarsky
3

Języki programowania używające obecnie OO starają się sprostać złożonym wymaganiom i środowiskom, które ciągle się zmieniają. OO pozwala swoim odbiorcom ukryć różne poziomy złożoności (między innymi funkcjami), dzięki czemu kodowanie staje się bardziej przejrzyste i łatwiejsze do zbudowania i zrozumienia. Jednak ta funkcja nie zawsze jest dostępna po wyjęciu z pudełka. W twoim przykładzie OO pozwoliło ci ukryć przede mną niektóre szczegóły, podając metodę zarządzania elementami w kolekcji, a może nawet utrwalić je za pomocą metody „AddItem”. Wydatki na ukrywanie złożoności mogą skutkować łatwym w użyciu i wielokrotnego użytku szkieletem, który upraszcza życie. Na przykład wiele implementacji ORM umożliwia komunikację z bazami danych bez konieczności zapisywania przez SQL szczegółów SQL. Jest to naprawdę potężne i ułatwia programistom.

Wzory, o których mówisz, są właśnie takie. Mają ułatwić ci życie. Ale to od Ciebie zależy, czy je adoptujesz i dostosujesz. Fakt, że potrzeba więcej pracy, jest po prostu dlatego, że zyskujesz więcej korzyści. To jest jak płacenie więcej za Ferrari. Jeśli chcesz dodatków, płacisz za nie. Jeśli więc zdecydujesz się zbudować skalowalne rozwiązanie N-Tier, które można uruchomić na kilku serwerach i różnych bazach danych zaplecza, wiąże się to z pewnymi kosztami. Jeśli Twoja aplikacja nie wymaga takiej złożoności, zignoruj ​​dodatkowe elementy i wróć do najprostszego rozwiązania, które zaspokoi Twoje potrzeby (KISS i YAGNI).

Podsumowując, nie sądzę, że OOP jako sama koncepcja staje się bardziej złożona, my, użytkownicy OOP, mamy możliwość korzystania z niej na różne sposoby, i to dobrze.

Bez szans
źródło
Wyczyść punkty. Znam YAGNI. Co to jest KISS?
tunmise fasipe
2
@tunmisefasipe, KISS to krótka nazwa zasady projektowania. Oryginalne słowa to „Keep It Simple (Stupid)” (zob. En.wikipedia.org/wiki/KISS_principle ), ale bardziej uprzejmym sformułowaniem może być „Keep It So Simple”.
NoChance
3
@tunmisefasipe - KISS = Keep It Simple, Stupid. Zdanie, które powtarzam sobie PONAD, PONAD i PONAD, i wciąż nie zawsze wydaje się wnikać.
Michael Kohne
@MichaelKohne, wszyscy tak robimy! Myślę, że sztuką jest upraszczanie rzeczy. E = M C C mówi bardzo dużo w bardzo zwięzłej formie!
NoChance
3

Krótka odpowiedź : Tak, ponieważ masz do czynienia z trudniejszymi problemami.

Długa odpowiedź (silnie stronnicza) : Dla mnie wzorce projektowe zwykle wskazują, że niektóre paradygmaty mają problemy w danym obszarze. Wzorce OOP radzą sobie z problemami OOP (na niższym poziomie wzorce Java radzą sobie z problemami Java), wzorce FP radzą sobie z problemami FP itp.

Podczas programowania możesz mieć różne priorytety. Możesz chcieć mieć odpowiedni program, możesz chcieć mieć najkrótszy czas wprowadzenia produktu na rynek, najszybszy możliwy program, długoterminową konserwację lub natychmiastową konserwację poprzez nowy wynajem. W zależności od krzaczastości, w której się znajdujesz, będziesz mieć bardzo różne - jeśli programujesz sterownik elektrowni, chcesz to zrobić za pierwszym razem, a nie od czasu do czasu za każdym razem naprawić błąd („Czy za każdym razem naciskasz Ctrl+Alt+Del?”). Jeśli jesteś w HPC, logika może być względnie prosta, ale chcesz ją wykonać tak szybko, jak to możliwe itp. Itp. Dodatkowo niektóre paradygmaty lepiej pasują do niektórych problemów (np. Programowanie AI i logiki, danych i relacyjnych baz danych).

OOP jest w pewnym sensie „zbyt dobry” w prostych przypadkach i jest to historia „modelowania prawdziwych wydarzeń na żywo”. Na przykład w pierwszej książce o OOP czytałem były zajęcia Person, Employeea Managerze is-azwiązku. Jak dotąd tak dobrze, ale co, jeśli pracownik zostanie awansowany na kierownika?

Z drugiej strony inne paradygmaty mają trudniejsze lekcje za pierwszym razem - na przykład FP z niezmiennymi zmiennymi (zabawne jest to, że ludzie, którzy mieli doświadczenie w programowaniu, często mają trudności z nauką niż ci, dla których jest to pierwszy język) - jednak ostatecznie są nie trudniejsze niż OOP. Testowanie czystych funkcji jest banalne, a w Haskell / Scala / ... masz narzędzia, które generują dla Ciebie testy.

PS. Tak - odpowiedź jest stronnicza w stosunku do OOP i przyznaję, że w pewnym stopniu jest „w reakcji” na OOP. OOP ma swoje zastosowania, ale moim zdaniem nie jest to jedyne, ostateczne rozwiązanie.

PPS. Tak - używaj wzorców projektowych - sprawiają, że programowanie OOP jest ostatecznie prostsze.

PPPS. Użyłem OOP jako synonimu programowania imperatywnego OOP.

Maciej Piechotka
źródło
2

Myślę, że bardziej chodzi o to, że dokumenty i przykłady stają się bardziej realistyczne.

Wczesne książki OOP (szczególnie wczesne książki Java) prezentowały absurdalnie uproszczony widok programowania aplikacji. Przykłady „Debetuj konto bankowe za pomocą 10-liniowego programu Java” zawsze było szczególnie denerwujące, ponieważ widziałem przykłady tego prostego zadania z 6000 linii kodu COBOL (i próbę zastąpienia Javy uruchomioną do 3500 linii, zanim został porzucony) jak niewykonalne!).

Na szczęście książki OO mają teraz tendencję do uznania złożoności prawdziwego życia i dostarczenia użytecznych przykładów radzenia sobie z nimi.

Ale jeśli chcesz zobaczyć, jak założyć konto bankowe w zaledwie 15 liniach kodu, programowanie funkcjonalne jest dla ciebie

James Anderson
źródło