Patologie OOP w Javie - długie metody(?)

0

Wiadomo że OOP w Javie poszło w zupełnie innym kierunku niż początkowe założenia OOP.
Zamiast klas z metodami mamy rachityczne encje/DTO z akcesorami (brak logiki biznesowej) lub beany sesyjne bez stanu, zamiast dziedziczenia kompozycje i interfejsy.
Można też zrozumieć anonimowe klasy zamiast lambdy. W sumie naturalne rozwiązanie.

Pytanie 1:
Czy to wszystko może prowadzić (i prowadzi) w waszym kodzie do klas które mają metody po kilkadziesiąt linii (2-3 ekrany)?

Pytanie 2:
Czy są sytuacje w których długie metody są nieuniknione? Jakie to sytuacje?

Kilka zasobów które potwierdzają że warto pisać krótko:
http://www.javacodegeeks.com/2012/12/rule-of-30-when-is-a-method-class-or-subsystem-too-big.html
http://codebetter.com/jeremymiller/2005/04/26/long-methods-and-classes-are-evil/

1

Nie i nie. Żadna zbyt długa metoda, czy też posiadająca więcej niż 2 poziomy zagłębienia nie powinna przejść code review ;)

Nie bardzo rozumiem Twoją tezę jakoby Java rozminęła się gdzieś z założeniami OOP.

0
airborn napisał(a):

Nie bardzo rozumiem Twoją tezę jakoby Java rozminęła się gdzieś z założeniami OOP.

Mam na myśli głównie to co już napisałem.

Dodatkowo:

Zasada 'bez pośredników'. Wyrzuć obiekty które nie robią nic poza przyjmowaniem żądania i przekazywaniem go innemu obiektowi.
Zasada 'nie spodziewaj się, że wykonam całą robotę'. Nie pytaj innych obiektów o ich wartość (wartości) i nie pracuj na nich sam. Każ obiektowi wykonać pracę dla Ciebie i dać Ci ważniejszy wynik.

"Programowanie obiektowe", Peter Coad/Jill Nicola, 1993

W wymienionej serii (Coad/Yourdon, OOA/OOD/OOP) nie ma nawet wspomnienia o interfejsach - podstawa dzisiejszego OOP w Javie.

1

Długie metody w dowolnym języku (nie musi być obiektowy), to przejaw lenistwa lub głupoty autora.
Metoda na 20 linii jest już za długa, a co dopiero mówić o stronach (ekranach).
Osobiście stopień skomplikowania metody wolę mierzyć liczbą instrukcji warunkowych (pętle, ify, switche).

2

Klasa na 1500 linii zawsze spoko.

1
vpiotr napisał(a):

W wymienionej serii (Coad/Yourdon, OOA/OOD/OOP) nie ma nawet wspomnienia o interfejsach - podstawa dzisiejszego OOP w Javie.

Ale przecież interfejsny nie mają za dużo wspólnego z obiektowym programowaniem, w takim sensie w jakim ty go rozumiesz(małpka dziedziczy po zwierzątku). Także, bulszit, interfejsy != obiektowe podejście.
To jest raczej robienie czegoś co naturalne jest w np: Ruby, mianowicie duck typing, i w tym kierunku bym szedł.

0

Ale o co chodzi?

vpiotr napisał(a):

Wiadomo że OOP w Javie poszło w zupełnie innym kierunku niż początkowe założenia OOP.

No, z tym, że "wiadomo" to dyskutować się nie da.

vpiotr napisał(a):

nie ma nawet wspomnienia o interfejsach - podstawa dzisiejszego OOP w Javie.

A jak to się ma do łamania zasad OOP? Naprawdę wierzysz, że książka, którą napisano w latach 90tych (informacja z wiki) opisuje "początkowe" założenia OOP z lat 70? I fakt, że w tej książce nikt nie wspomniał o interfejsach jest jakoś tajemniczo powiązany z tym, że ludzie piszą długie kawałki kodu?

Mam jakieś takie wrażenie, że nie do końca rozumiesz, czym jest programowanie obiektowe. Za to przeczytałeś kilka tekstów i je dodatkowo źle zrozumiałeś.

Tak na boku:

airborn napisał(a):

(...)posiadająca więcej niż 2 poziomy zagłębienia(...)

MarekR22 napisał(a):

(...)Metoda na 20 linii jest już za długa(...)

Generalnie - spojrzałem na swój nowszy kod i oba warunki przeszedł, ale rzucanie "sztywnymi" liczbami jest dla mnie przesadą.

0

Proszę o odpowiedzi na zadane pytania. Dyskusja o tym kto co czytał lub nie albo czym jest OOP to zupełnie inny temat.

3
vpiotr napisał(a):

Czy to wszystko może prowadzić (i prowadzi) w waszym kodzie do klas które mają metody po kilkadziesiąt linii (2-3 ekrany)?
nie, poza paroma zamierzonymi dlugimi klasami/metodami nie przekraczam kilkaset linii na klase i wiecej niz (malego) ekranu na metode.

vpiotr napisał(a):

Czy są sytuacje w których długie metody są nieuniknione? Jakie to sytuacje?
nie ma takich sytuacji

przyznam troche draznia mnie pomysly typu 'max 25 linijek na metode' albo 'min 80% pokrycia testami', imo zwlaszcza doswiadczeni programisci powinni polegac na swoim zdrowym rozsadku a nie rozkochiwac sie w tego typu regulkach.

0

Można też zrozumieć anonimowe klasy zamiast lambdy. W sumie naturalne rozwiązanie.

W Javie 8 przecież są już lambdy.

Co do linii to w Clean Code, jeśli się nie mylę, wujcio opowiadał o jakimś hobbystycznym projekcie jego ziomka, który założył sobie, że jego metody nie będą dłuższe niż 3 czy tam 4 linijki. No i spoko było mówił :D

1

Może rozgraniczmy na dobry początek to co wynika z języka od tego co wynika ze sposobu w jaki jest używany.

Sama składnia języka powoduje, że trzeba się trochę napisać by cokolwiek napisać. Java jest barokowa z tymi wszystkimi nawiasami, zawijasami i wąsami. W niewielkim stopniu poprawia to wprowadzenie lambd. W tej samej kategorii "siedzą" interfejsy. To, że nikt o nich nie wspominał w tej czy innej książce o OOP nie oznacza, że nie są one OOP. Teoria tworzenia kodu (w tym OOP) ewoluuje i dziś gdy silny nacisk kładzie się na IoC i przerzucenie wiązania obiektów na kontener interfejsy są bardzo fajne.

Kolejnym elementem są DTO, których historia sięga zamierzchłych czasów gdy trzeba było używać interfejsu Serializable na potrzeby Hibernate czy serializacji do XML. To powodowało, że do niektórych pól klasy należało dodać słówko transient, co powodowało, że trzeba było pisać własne metody do serializacji i deserializacji (by tworzyć poprawne obiekty) co w efekcie powodowało, że napisanie prostego DTO było szybsze i łatwiejsze. Zresztą i tu mamy "zonk" z serialVersionUID, który nie doczekał się żadnego rozsądnego mechanizmu pozwalającego na automatyzację zarządzania wersjami klasy.

@vpiotr, a twoje pytania dotyczą sposobu korzystania z języka.

ad 1. Jest to przejaw nie tyle co lenistwa, co podejścia "jakoś(ć) to będzie" i tworzenia kodu "good enough", czyli zaspokajania potrzeb biznesowych, a nie technicznych. Obecnie w projekcie odpuściłem sobie sonara, bo nie miałem siły walczyć z ludźmi o to by przed mergem przepuszczali kod przez sonara i starali się eliminować największe babole.

ad 2. Tu odpowiedzialność jest pomiędzy językiem, a człowiekiem. Czasami język nie pozwala na tworzenie wizualnie krótkich metod ponieważ np. wymagana jest odpowiednia obsługa wyjątków (np. kilka różnych klas, dla których wspólna nad klasa to Exception). Z drugiej strony niektóre operacje np. na danych są z natury długie np. ręczne transformowanie obiektów z jednej domeny do innej. Tu skrócenie kodu czasami jest bardzo trudne i wymaga wprowadzenia niepotrzebnych komplikacji np. całej gamy konwerterów.
Jednak, to są nieliczne przypadki. Zazwyczaj długość metody zależy od tego jak programista myśli o operacji, którą metoda reprezentuje, czy jest to operacja atomowa, czy też kompozycja kilku kroków.

1

Jako, że odpowiedź na pytanie @Wizzie nie mieści się w komentarzu....

Obecnie wprowadzanie DTO jest średnio przydatne. Encje powinny zawierać w sobie logikę, która pozwala przynajmniej na ich "samookreślenie się" w ramach domeny porównaj Jakiś czas temu @koziołek na... Jednak jest pewna grupa problemów, gdzie DTO (w postaci rachitycznego POJO) jest całkiem dobrym pomysłem.

  1. Gdy jest częścią definicji API w REST. Obiekty REST-owe (czytaj JSONy) co do zasady są tylko kontenerami na informacje. Nie ma sensu pchać do nich logiki. Szczególnie, że zmiana logiki może pociągnąć za sobą zmiany w strukturze obiektu. Wprowadzenie DTO w takim wypadku jest uzasadnione gdyż będzie ono pełnić rolę "niezależnego" API. Czegoś w rodzaju interfejsu, ale na poziomie struktur danych.

  2. Gdy dokonujemy transformacji w strukturach danych pomiędzy niezależnymi elementami systemu. Przypadek podobny do poprzedniego z tą różnicą, że nie wychodzimy poza JVM. Dzięki takiemu podejściu możemy sobie ustalić w miarę stabilne API da poszczególnych elementów oraz co ważne nie ma pokusy używania kodu z jednego elementu w innym. Tu uwaga warto obserwować wskaźniki duplikacji kodu. Dzięki temu można w odpowiednim momencie wydzielić nowe klasy.

Podsumowując, DTO nadal są przydatne, ale należy ich używać tam gdzie wzorzec ten został wymyślny - do dogadywania różnych części systemu, które niekoniecznie powinny albo w ręcz nie mogą współdzielić pewnych fragmentów logiki.

0
Koziołek napisał(a):

ad 1. Jest to przejaw nie tyle co lenistwa, co podejścia "jakoś(ć) to będzie" i tworzenia kodu "good enough", czyli zaspokajania potrzeb biznesowych, a nie technicznych. Obecnie w projekcie odpuściłem sobie sonara, bo nie miałem siły walczyć z ludźmi o to by przed mergem przepuszczali kod przez sonara i starali się eliminować największe babole.

Mam wrażenie że w przypadku o którym myślę (z życia) chodziło o agresywne powstrzymywanie się od dziedziczenia.

"Przy braku dziedziczenia (tylko implementacja interfejsu!) nie ma przecież sensu zostawiać jakiś reużywalny kawałek kodu (wydzielona nie-prywatna metoda) użytkownikom klasy, bo przecież i tak z niego nie skorzystają" - tak mogli myśleć ludzie generujący "grube" metody. Ale to tylko moje zgadywanie.

2

Polecam :

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