Programowanie obiektowe - co o nim sądzicie?

0

W zasadzie to obiektowość trochę mi przypomina SCRUMa, tzn. ludzie dzielą się na tych, którzy uważają, że to zbędna robota i tych, którzy twierdzą, że nie. Wśród tych ostatnich nie ma natomiast zgody co do tego co właściwie ten SCRUM/ ta obiektowość jest. Oczywiście mamy różnice w proporcjach. Wydaje mi się, że jeśli chodzi o SCRUMa to będzie miał on w członku zespołu o tyle gorętszego zwolennika, o ile jego rola jest mniej sprecyzowana, tzn. mniej SCRUM będzie wzbudzał entuzjazmu w programistach i testerach, a więcej w specjalistach od miękkich skillów, przepływu pracy i w managmencie nieodgadnionego szczebla.

Jeśli chodzi o obiektowość to pewnie sto procent programistów w Twoim zespole włącznie z Tobą uważa ją za (w mniejszym lub większym stopniu) nieuniknioną i poza społecznością Suckless.org oraz jakimiś nielicznymi wyjątkami można będzie spotkać podobne opinie. Do utworzenia tego wątku zachęciło mnie to nagranie:
link
Dosyć ładnie się automatycznie tłumaczy w Googlu jeśli ktoś (tak jak ja) nie rozumie od razu wszystkiego na bieżąco. Co ciekawe autor nie potępia Javy. Stawia hipotezę, że była przyczyną triumfu programowania obiektowego w biznesie, ale bez obiektowości również osiągnęłaby wtedy sukces, bo miała dużo przewag nad konkurencją. Myślę, że warto przytoczyć te zdanie:

Jest również bardzo naturalne, że budując coraz większe systemy i złożone rzeczy w miarę możliwości chcemy prostych reguł, którymi mamy się kierować. Programowanie obiektowe wydaje się oferować jednostkę abstrakcji (unit of abstraction? :/) i zestaw wytycznych, dzięki którym możemy stopniowo implementować coraz większe systemy. Ten sposób myślenia
myślenia doprawadził nas do wzorców, a następnie do zasad SOLID, wstrzykiwania zależności oraz Test Driven Development i wszystkie te rzeczy, które zostały później narzucone przez wiele osób, które upierają się, że jest to obecnie jedyny prawdziwy sposób programowania obiektowego, ale dla mnie wszystkie te najlepsze praktyki to tylko plasterki, które rekompensują fakt, że oryginalna wizja programowania obiektowego nigdy się nie ziściła i co kilka lat pojawia się w mieście nowa ideologia mówiąca o tym, jak faktycznie zajmujemy się programowaniem obiektowym w rzeczywistości tym razem.

Jeszcze o autouzupełnianiu wcześniej jest powiedziane, że ludzie myślą, że jeśli chcą mieć podpowiedzi dla funkcji to obiektowość jest konieczna tymczasem można to osiągnąć przez uzupełnianie funkcji dla pierwszego argumentu jaki przyjmują. Albo źle zrozumiałem. Spotkaliście się z czymś takim?

4

OOO ma sens i jest przydatne jeśli stosuję się je świadomie.

Niestety w wielu projektach ludzie nie są świadomi i pakują OOO z reguł tam, gdzie najmniej pasuje.

6

Zależy od tego co rozumiesz przez "programowanie obiektowe", bo dużo definicji ma takie coś:

  • Niektórzy przez programowanie obiektowe po prostu rozumieją używanie klas
  • Inni, że to jest używanie klas wraz z interfejsami
  • Dla niektórych programowanie obiektowe to używanie metod public/protected/private, oraz nadpisywania metod
  • Dle niektórych programowanie obiektowe to np używanie mixinów/traitów jak w rubym, albo extendowanie typów integer/string
  • Dla innych programowanie obiektowe głównie chodzi o polimorfizm (nie ważne czy z silnym czy słabym typowaniem)
  • Dla jeszcze innych, to oznacza po prostu enkapsulowanie danych i wystawianie ich za pomocą metod (według tej definicji np funkcja zwracają strukturę może być obiektem)

Także zależy co masz na myśli.

Ja osobiście kiedy mówię o programowaniu obiektowym mam na myśli dwa ostatnie punkty, i myślę że programowanie obiektowe w połączeniu z funkcyjnym (użyte równocześnie) to najlepszy design modułów jaki znamy. To jak łączyć moduły w większe systemy, to już inna bajka.

2

Generalnie rzadko działa i jest fajny tylko w połączeniu z innymi paradygmatami.
W typowym kodzie komercyjnym założenia OOP idą do kosza bo np. jak enkapsulować coś co koniec końców trzeba persystować?

5
Grzyboo napisał(a):

jak enkapsulować coś co koniec końców trzeba persystować?

Odpowiednio.

Twoja nieumiejętność w zastosowaniu OOP poprawną enkapsulację, to nie jest argument przeciwko OOP.

3

Moim zdaniem ludzie krytykują programowanie obiektowe, ponieważ patrzą na to paskudztwo OOP jakie jest w Javie, rozwlekłe getery setery itp. Najładniejsza obiektowość jest w takich językach jak Ruby, Dart, C# tutaj jest to ładnie zaprojektowane. Możliwe że nawet lepiej to wygląda niż takie mieszanie obiektowośći z programowaniem funkcyjnym w Kotlin, Scala, TS.

5
paranoise napisał(a):

Jest również bardzo naturalne, że budując coraz większe systemy i złożone rzeczy w miarę możliwości chcemy prostych reguł, którymi mamy się kierować.

Prosta reguła jest taka, żeby myśleć o tym, co jest pomiędzy - o tym, jak przepływają informacje między obiektami, a nie o tym, jak wygląda sam pojedynczy obiekt.
Np. załóżmy, że mamy wszystkie pola publiczne. Czy to łamie zasadę hermetyzacji czy nie?

Moim zdaniem nie da się tego określić patrząc na sam obiekt, bo jeśli nikt nie będzie wyciągał tych pól, to nic się nie stanie. Nawet w językach, które nie mają prywatnych pól można się umówić, że coś jest prywatne i nie ruszać. Prywatne pola mają jedynie to zagwarantować na poziomie języka.

Natomiast to, co łamie hermetyzację, to sytuacja, że faktycznie obiekt A będzie wyciągał prywatne informacje z B.

I popatrzmy na takie gettery/settery. To przewrotny sposób, w jaki można łamać hermetyzację. Bo na poziomie klasy wszystko jest okej - wszystkie pola prywatne. Jednak na poziomie wymiany informacji jest możliwa sytuacja, że obiekt A będzie wyciągał prywatne dane z obiektu B, albo je podmieniał.

Aha: krytykując gettery/settery mam na myśli ich bezmyślne stosowanie. Umiejętnie użyte spełniają swoją rolę tam, gdzie są potrzebne. Ale mam na myśli coś takiego, że jak się ma 10 pól, to do wszystkich jest getter/setter z automatu. A niestety tego i inne praktyki ludzie nazywają OOP. Czyli jak ograć system i złamać zasady, ale tak, żeby nie było widać, że je łamiemy.

Ale czy należy wszędzie stosować hermetyzację? Czasami dobrze jest mieć wszystkie pola publiczne i się do nich odwoływać radośnie, bo czasem nie potrzebujemy klasy w sensie OOP, a bardziej pojemnika na dane, struktury sterowanej z zewnątrz (wtedy byłby to paradygmat bardziej proceduralny, ale co w tym złego? Można mieszać paradygmaty. Niestety ludzie wchodząc w jakiś paradygmat, starają się w 100% każdy kawałek kodu pisać w tym paradygmacie na siłę ).

0

Nie wiem czy to nie w tym filmie programista z Francji łamie poprzez źle napisaną obiektowość kod Javy. Od 48:03.

5

Myślę, ze Scrum i OOP mają tyle współnego, że są logicznymi, spójnymi rozsądnymi praktykami, ale wielu programistów to strasznie leniwe stworzenia i nie chciało się doczytać co to właściwie jest. Każdy więc mówi to co tam sobie skojarzył, że w OOP są klasy i trzeba robić gettery i settery. To co z tego wychodzi jest bardzo różne…
Warto też zadać pytanie o którą szkołę OOP mamy na myśli, bo obiektowość w C++ i Javie to coś trochę innego niż w SmallTalku, Common Lispie czy Ruscie. Ogólnie rzecz ujmując, stosując ze zrozumieniem zarówno OOP jak i Scrum są fajne, a jeśli nie są to bywa śmiesznie, a bywa tragicznie. :)

3

OOP jest piękne, jest to jeden z tych pomysłów człowieka, który realnie zmienił ten świat i nie ma co z tym dyskutować. Prostota modelowania problemów przy pomocy obiektów jest genialna i łatwo przyswajalna, stąd OOP jest głównym paradygmatem.
OOP is love, OOP is life.

2
Riddle napisał(a):

Zależy od tego co rozumiesz przez "programowanie obiektowe", bo dużo definicji ma takie coś:

  • Niektórzy przez programowanie obiektowe po prostu rozumieją używanie klas
  • Inni, że to jest używanie klas wraz z interfejsami
  • Dla niektórych programowanie obiektowe to używanie metod public/protected/private, oraz nadpisywania metod
  • Dle niektórych programowanie obiektowe to np używanie mixinów/traitów jak w rubym, albo extendowanie typów integer/string
  • Dla innych programowanie obiektowe głównie chodzi o polimorfizm (nie ważne czy z silnym czy słabym typowaniem)
  • Dla jeszcze innych, to oznacza po prostu enkapsulowanie danych i wystawianie ich za pomocą metod (według tej definicji np funkcja zwracają strukturę może być obiektem)

Także zależy co masz na myśli.

Ja osobiście kiedy mówię o programowaniu obiektowym mam na myśli dwa ostatnie punkty, i myślę że programowanie obiektowe w połączeniu z funkcyjnym (użyte równocześnie) to najlepszy design modułów jaki znamy. To jak łączyć moduły w większe systemy, to już inna bajka.

Na literkę h czy i, czy jak tam policzyć
"obiektowe" jest wtedy, jak używa się ... tu świadomie uciekam od religijnego określenia "wzorce", choć o to chodzi ... ujmę: używa się dobrych praktyk.

Osobiscie dzielę na "pierwszą falę OOP" m.in. z przerostem dziedziczenia, do dziś pokutuje w marnych tutorialach, "drugą falę" z refleksja nad wadami pierwszej, wzorcami (nie rozumianymi religijnie)

rjakubowski napisał(a):

OOP jest piękne, jest to jeden z tych pomysłów człowieka, który realnie zmienił ten świat i nie ma co z tym dyskutować. Prostota modelowania problemów przy pomocy obiektów jest genialna i łatwo przyswajalna, stąd OOP jest głównym paradygmatem.
OOP is love, OOP is life.

Popieram

2
elwis napisał(a):

Myślę, ze Scrum i OOP mają tyle współnego, że są logicznymi, spójnymi rozsądnymi praktykami, ale wielu programistów to strasznie leniwe stworzenia i nie chciało się doczytać co to właściwie jest. Każdy więc mówi to co tam sobie skojarzył, że w OOP są klasy i trzeba robić gettery i settery. To co z tego wychodzi jest bardzo różne…
Warto też zadać pytanie o którą szkołę OOP mamy na myśli, bo obiektowość w C++ i Javie to coś trochę innego niż w SmallTalku, Common Lispie czy Ruscie. Ogólnie rzecz ujmując, stosując ze zrozumieniem zarówno OOP jak i Scrum są fajne, a jeśli nie są to bywa śmiesznie, a bywa tragicznie. :)

Fajne i ważne rozróżnienia wprowadzasz. Dodam swoje
OOP framerowków graficznych o (zbyt) głębokiej hierarchii czy reszty świata
OOP z uniwersytetów lat 70-80 żywe miedzy 10 osób na każdym - <500 na świecie czy OOP w rękach setek tysiecy (już nie eksperymentujemy, a klepiemy)

3

Programowanie obiektowe - co o nim sądzicie?

Obiekty są całkiem spoko, ale programowanie zorientowane obiektowo jest tragiczne pod wieloma względami. Próbując znaleźć jakiś przykład systemu gdzie mogę stwierdzić, że podejście OOP okazało się pomocne muszę się cofnąć aż do początków mojej "kariery" do 2011 roku.

Twoja nieumiejętność w zastosowaniu OOP to nie jest argument przeciwko niemu.

(DISCLAIMER: Powyższy cytat to ogólny argument który pojawia się w tego typu dyskusjach) Ponieważ OOP to pojęcie abstrakcyjne i całkowicie oderwane od rzeczywistości, umiejętność zastosowania OOP jest totalnie subiektywne i niemierzalne. Czyjaś opinia na temat rzeczonych "umiejetności" kogokolwiek może pozostać tylko opinią i będzie ciężko poprzeć ją czymkolwiwk rzeczywistym by móc uznać ją za faktyczny argument.

8

To przecież proste:

class Człowiek {
 łaź();
}

class Łódka {
 pływaj();
}

class Krokodyl extends Człowiek, Łódka {
 łaź();
 pływaj();
}

czego nie rozumiecie?

1
jarekr000000 napisał(a):

To przecież proste:

class Człowiek {
 łaź();
}

class Łódka {
 pływaj();
}

class Krokodyl extends Człowiek, Łódka {
 łaź();
 pływaj();
}

czego nie rozumiecie?

To jest właśnie jedna z miskoncepcji czym jest OOP. Taki pomysł jak "modelowanie świata" to jest jakaś bzdura.

2

Nie mam nic przeciwko OOP ale jestem przeciwny dziedziczeniu

1

Najważniejsze rzeczy z OOP wg mnie:

  • rozpoznać wcześnie palladyna/ewangelistę i ostrzec zespół
  • warto znać i rozpoznać, nie warto za to ginąć
  • warto rozumieć co ktoś do nas mówi w "języku OO"

Poza tym, to świetny temat do shit stormów i udowadniania kto bardziej (nie) umie w OOP, albo dysput jak wygląda "tró OOP".

Czasem programista doznaje zamroczenia olśnienia, "Wszystko co robiłem do tej pory było amatorskie! Dzięki OOP wszystko się zmieni! Real game changer!". Później przychodzi trochę doświadczenia z OOP i pojawia się potrzeba misji: "to jest tak dobre, że muszę się podzielić ze światem tą dobrocią" (np. prezentacje w ramach zespołu). Świat ma jednak zdanie odrębne, co rodzi reakcję: "muszę wyjaśnić jak wygląda prawdziwe OOP, dlaczego jest dobre i dlaczego świat się myli!". Później przychodzi opamiętanie i refleksja: "To jeden z wielu paradygmatów, może powinienem dać szansę innym? Czy da się je połączyć i jak to zrobić?" A jeszcze dalej "Czy ja tego potrzebuję?" Może da się prościej? Po prostu "dziel i rządź"? (Jak dzielić? ? Co oddzielać? Kiedy przestać?)

Tak wyglądała moja droga. Kiedyś byłem zafascynowany OOP, do tego stopnia, że szukałem do Eclipsa pluginów do "Design patterns" (co dziwne, takie pluginy były rozwijane i dla mnie był to główny argument za instalacją Eclipsa :-) ) Później przyszła "orientacja na biznes", a ostatnio orientacja na siebie ("I'm too old for this shit").

I teraz, jak zamienimy OOP na coś innego, to nie ma co wchodzić na tę samą ścieżkę jeszcze raz, tylko wybrać istotne przystanki.

Nie wiem czy te doświadczenia z OOP przekładają się na innych. Może podobna ścieżka? Może zupełnie inna?

1
anonimowy napisał(a):

Nie mam nic przeciwko OOP ale jestem przeciwny dziedziczeniu

Tylko ze OOP bez dziedziczenia to zbior dobrych praktyk ktory rownie dobrze mozna stosowac do FP/Haskella czy Rusta :P

1
anonimowy napisał(a):

Nie mam nic przeciwko OOP ale jestem przeciwny dziedziczeniu

Gdyż?
Nie ogarniasz?
Nigdy nie pisałeś nic złożonego gdzie dziedziczenie rozwiązuje wiele problemów lub zwyczajnie ułatwia życie?
Są jakieś inne powody?

8
4w0rX4t4X napisał(a):
anonimowy napisał(a):

Nie mam nic przeciwko OOP ale jestem przeciwny dziedziczeniu

Gdyż?
Nie ogarniasz?
Nigdy nie pisałeś nic złożonego gdzie dziedziczenie rozwiązuje wiele problemów lub zwyczajnie ułatwia życie?
Są jakieś inne powody?

Dziedziczenie to najciaśniejsza relacja jaką możesz dodać, i praktycznie nigdy nie ma powodu żeby wybrać dziedziczenie zamiast kompozycje.

2

Prostota modelowania problemów przy pomocy obiektów jest genialna i łatwo przyswajalna, stąd OOP jest głównym paradygmatem.

No właśnie wcale nie jest prosta.

OOP (w rozumieniu takim jak Java) całkiem nieźle modeluje zdania że "obiekt x posiada równocześnie własności interfejsu A oraz B", ale już bardzo mocno ma pod górkę jak chcesz zamodelować "obiekt x posiada własności interfejsu A albo B". I jeszcze bardziej pod górkę jak obiekt x musi mieć stan zależny od tego czy jest A czy jest B, np. pewne pola mające sens dla A nie mają sensu dla B.

Przykładowo:

enum Output {
   StdOut,
   StdErr,
   File(String),   
   None
}

W OOP ta prosta strukturka to byłoby całe drzewko klas na kilkadziesiąt linii ;)

Prostota modelowania struktur danych przy pomocy typów algebraicznych jest genialniejsza i łatwiej przyswajalna niż przy pomocy OOP. :P

0

@Krolik: @rjakubowski obaj jesteście trochę w błędzie - przecież OOP nigdy nie służyło do żadnego modelowania niczego :|

To jakieś frazesy powtarzane przez osoby które nie rozumieją tego paradygmatu.

0

Ja tam korzystam, w ogóle ja programuje w zależności od potrzeb, jak robię coś co jest do niczego nie potrzebne jakiś skrypt, to zastosuje inne podejście niż np. do jakiegoś systemu, który chciałbym móc potem w przyszłości modyfikować, utrzymwać.

Ogólnie lubię najebane abstrakcji, coraz to wyższych warstw, obiekty później moduły lubię upraszczać.
Nawet z reacta na angulara zmieniłem, żeby przez same środowisko być zmuszanym do lepszego utrzymywania kodu, jest po prostu łatwiej SOLID kod tworzyć, framework zmusza do większego dbania, ale dalej można zaniedbać.

Modele Deep learning bardzo ciekawie się tak projektuje, żeby można wymieniać każdy element modelu na inny i potem nawet junior bez żadnej wiedzy może sobie poradzić z obsługą.

1

Jak ktoś chce użyć dziedziczenia, to niech się zastanowi najpierw nad:

  • interfejsami (coś się zachowuje wg określonej specyfikacji)
  • kompozycją (coś zawiera coś innego)
  • referencją (coś odnosi się do czegoś innego)
  • generykami (coś jest nieokreślone i może występować w wielu odmianach i opiszmy to abstrakcyjnie)
  • enumami (jest n rodzajów czegoś), szczególnie w stylu Rust, gdzie enumy mogą zawierać w sobie dane, więc są jakby uniami
  • callbackami (referencjami do funkcji) czy innymi parametrami ustawianymi w obiektach w czasie wykonania

Tzn. nie mówię, żeby dziedziczenia nie używać w ogóle, tylko w większości przypadków jest ono używane niepotrzebnie. Nawet sztandarowy przykład z psem i kotem, które mają metodę say to w zasadzie bardziej przykład na to, gdzie mogą się przydać interfejsy (czyli, że obiekty zachowują się zgodnie ze specyfikacją), a nie dziedziczenie klasowe, czyli w zasadzie kopiuj-wklej-modyfikuj.

0

Dziedziczenie ma głównie sens jeśli w kodzie używamy więcej niż dwa pochodne obiekty. Chociażby ze względu na LSP. W każdym innym przypadku na 99% istnieje lepszy sposób niż dziedziczenie. Są jeszcze mixiny, ale to kompletnie odrębny przypadek :P

0

Sporo fuckupów w OOP jest spowodowane przez złe przyzwyczajenia, które w gruncie rzeczy są bezsensowne. Np mówi się ludziom że "atrybuty obiektów powinny być ustawiane w konstruktorze", w myśl idei że lepiej żeby obiekty były niemutowalne. I to jest prawda.

Tylko problem z tą zasadą jest taki, że wtedy ludzie myślą że nie można wydzielić metody z konstruktora, i wydaje im się że np taki kod jest zły:

class MyObject {
  int a;
  
  MyObject(int a) {
    extracted(a);
  }

  void extracted(int a) {
    this.a = a;
  }
}

Przy czym zupełnie nie jest. W myśl programowania obiektowego taki kod jest totalnie, w 100% w porządku. Ale przez specyfikę niektórych języków i złe przyzwyczajenia - wielu programistów twierdzi że taki kod jest całkowicie niedopuszczalny (mimo że nie potrafią podać uniwersalnych argumentów przeciwko niemu). Przez specyfikę języka mam na myśli to żę np Java i c# potrafią wymusić inicjalizację pola (final, readonly) w konstruktorze, ale nie w wydzielonej metodzie - ale to jest wada języka, a nie podejścia. Jak piszemy kod obiektowy np w JS, pythonie i php to taki kod jest w zupełności okej.

Więc na głównego wroga większości paradygmatów ja bym wskazał złe przyzwyczajenia.

0

W ogóle, skoro język Python został wywołany do tablicy to zacznijmy od tego, że Java nie jest językiem obiektowym, a Python nim jest.

1

Problem nie polega na tym czy jest dobre czy złe, problem polega na tym do czego go używasz.
dla przykładu jak piszesz program który ma działać szybko pochłaniać mało zasobów bo piszesz na jakiś małe arm gdzie flash masz parę kb a ramu jeszcze mniej to pisanie w oop jest po prostu debilne.
z kolei jak piszesz duży system przetwarzania danych gdzie nie ograniczają cie zasoby a ważne jest by był czytelny, przejrzysty i bezpieczny to oop jest w większości przypadków jedynym wyborem.
jak piszesz jakieś gównoskrypty jednorazowego/prostego użytku to w większości wybór programowania funkcyjnego/proceduralnego jest optymalnym rozwiązaniem.

1
KamilAdam napisał(a):

Tylko ze OOP bez dziedziczenia to zbior dobrych praktyk ktory rownie dobrze mozna stosowac do FP/Haskella czy Rusta :P

Skoro tak, to chyba dobrze, bo to oznacza, że to zalecenia dość uniwersalne.

0
hzmzp napisał(a):

piszesz na jakiś małe arm gdzie flash masz parę kb a ramu jeszcze mniej to pisanie w oop jest po prostu debilne.

W jakim sensie debilne? Chyba chodzi ci o to, że implementacja OOP w danym języku programowania nie współgra z wymaganiami pisania na "małe arm"?

Nie kwestionuję tego, ale to wygląda na jakiś skrót myślowy i mylenie abstrakcyjnej koncepcji z implementacją.

A jakie dokładnie elementy w danej implementacji OOP powodują, że jest ona niewydajna?

1 użytkowników online, w tym zalogowanych: 0, gości: 1