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

Patologie OOP w Javie - długie metody(?)
vpiotr
  • Rejestracja:ponad 13 lat
  • Ostatnio:prawie 3 lata
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/

airborn
  • Rejestracja:ponad 15 lat
  • Ostatnio:prawie 7 lat
  • Postów:274
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.

vpiotr
  • Rejestracja:ponad 13 lat
  • Ostatnio:prawie 3 lata
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.

edytowany 1x, ostatnio: vpiotr
spartanPAGE
e tam, dobre proxy nie jest złe :P
MarekR22
Moderator C/C++
  • Rejestracja:około 17 lat
  • Ostatnio:mniej niż minuta
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).


Jeśli chcesz pomocy, NIE pisz na priva, ale zadaj dobre pytanie na forum.
edytowany 1x, ostatnio: MarekR22
2

Klasa na 1500 linii zawsze spoko.

niezdecydowany
niezdecydowany
  • Rejestracja:ponad 12 lat
  • Ostatnio:ponad 9 lat
  • Lokalizacja:Bieszczady
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ł.


"Perhaps surprisingly, concurrent programming isn’t so much about threads or
locks, any more than civil engineering is about rivets and I-beams."
W0
  • Rejestracja:ponad 12 lat
  • Ostatnio:około 2 godziny
  • Postów:3551
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ą.

MarekR22
a czy ja pisałem, że to ścisła reguła? NIE! Nawet dałem podałem alternatywę definicji "długiej" funkcji. Na dodatek to 20 to i tak spory zapas.
vpiotr
  • Rejestracja:ponad 13 lat
  • Ostatnio:prawie 3 lata
0

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

niezdecydowany
niezdecydowany
ja zaznaczyłem tylko bzdury - na temat się nie wypowiem bo się nie zmam.
vpiotr
nie znam się to się wypowiem?
niezdecydowany
niezdecydowany
wypowiedziałem się, bo napisałeś w tamtym poście BZDURY - które tak NAP!@#DALJĄ w oczy, że nie mogłem zostawić tego bez komentarza.
W0
Przecież już dostałeś dobrą odpowiedź. @airborn: "Nie i nie.".
katelx
  • Rejestracja:prawie 10 lat
  • Ostatnio:4 miesiące
  • Lokalizacja:Hong Kong
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.

Wizzie
  • Rejestracja:prawie 11 lat
  • Ostatnio:ponad 7 lat
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

niezdecydowany
niezdecydowany
bez sensu(bo dlaczego, 3/4 a nie 5 ?), liczba linii zawsze powinna być po coś, np: Sandi Metz i jej 6 lini, ma taką podstawę że metoda może maksymalnie zbudować if'a + els'a - i to jest koniec odpowiedzialności.
Wizzie
liczbę podałem z d**y, bo nie chciało mi się szukać w książce :D
Koziołek
Moderator
  • Rejestracja:prawie 18 lat
  • Ostatnio:około miesiąc
  • Lokalizacja:Stacktrace
  • Postów:6821
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.


Sięgam tam, gdzie wzrok nie sięga… a tam NullPointerException
Wizzie
co sądzisz o DTO w projektach na nowych wersjach JPA/Hibernate?
Koziołek
Moderator
  • Rejestracja:prawie 18 lat
  • Ostatnio:około miesiąc
  • Lokalizacja:Stacktrace
  • Postów:6821
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.


Sięgam tam, gdzie wzrok nie sięga… a tam NullPointerException
vpiotr
  • Rejestracja:ponad 13 lat
  • Ostatnio:prawie 3 lata
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.

edytowany 1x, ostatnio: vpiotr
L4
  • Rejestracja:około 15 lat
  • Ostatnio:11 miesięcy
2

Polecam :

vpiotr
Niezłe.
Kliknij, aby dodać treść...

Pomoc 1.18.8

Typografia

Edytor obsługuje składnie Markdown, w której pojedynczy akcent *kursywa* oraz _kursywa_ to pochylenie. Z kolei podwójny akcent **pogrubienie** oraz __pogrubienie__ to pogrubienie. Dodanie znaczników ~~strike~~ to przekreślenie.

Możesz dodać formatowanie komendami , , oraz .

Ponieważ dekoracja podkreślenia jest przeznaczona na linki, markdown nie zawiera specjalnej składni dla podkreślenia. Dlatego by dodać podkreślenie, użyj <u>underline</u>.

Komendy formatujące reagują na skróty klawiszowe: Ctrl+B, Ctrl+I, Ctrl+U oraz Ctrl+S.

Linki

By dodać link w edytorze użyj komendy lub użyj składni [title](link). URL umieszczony w linku lub nawet URL umieszczony bezpośrednio w tekście będzie aktywny i klikalny.

Jeżeli chcesz, możesz samodzielnie dodać link: <a href="link">title</a>.

Wewnętrzne odnośniki

Możesz umieścić odnośnik do wewnętrznej podstrony, używając następującej składni: [[Delphi/Kompendium]] lub [[Delphi/Kompendium|kliknij, aby przejść do kompendium]]. Odnośniki mogą prowadzić do Forum 4programmers.net lub np. do Kompendium.

Wspomnienia użytkowników

By wspomnieć użytkownika forum, wpisz w formularzu znak @. Zobaczysz okienko samouzupełniające nazwy użytkowników. Samouzupełnienie dobierze odpowiedni format wspomnienia, zależnie od tego czy w nazwie użytkownika znajduje się spacja.

Znaczniki HTML

Dozwolone jest używanie niektórych znaczników HTML: <a>, <b>, <i>, <kbd>, <del>, <strong>, <dfn>, <pre>, <blockquote>, <hr/>, <sub>, <sup> oraz <img/>.

Skróty klawiszowe

Dodaj kombinację klawiszy komendą notacji klawiszy lub skrótem klawiszowym Alt+K.

Reprezentuj kombinacje klawiszowe używając taga <kbd>. Oddziel od siebie klawisze znakiem plus, np <kbd>Alt+Tab</kbd>.

Indeks górny oraz dolny

Przykład: wpisując H<sub>2</sub>O i m<sup>2</sup> otrzymasz: H2O i m2.

Składnia Tex

By precyzyjnie wyrazić działanie matematyczne, użyj składni Tex.

<tex>arcctg(x) = argtan(\frac{1}{x}) = arcsin(\frac{1}{\sqrt{1+x^2}})</tex>

Kod źródłowy

Krótkie fragmenty kodu

Wszelkie jednolinijkowe instrukcje języka programowania powinny być zawarte pomiędzy obróconymi apostrofami: `kod instrukcji` lub ``console.log(`string`);``.

Kod wielolinijkowy

Dodaj fragment kodu komendą . Fragmenty kodu zajmujące całą lub więcej linijek powinny być umieszczone w wielolinijkowym fragmencie kodu. Znaczniki ``` lub ~~~ umożliwiają kolorowanie różnych języków programowania. Możemy nadać nazwę języka programowania używając auto-uzupełnienia, kod został pokolorowany używając konkretnych ustawień kolorowania składni:

```javascript
document.write('Hello World');
```

Możesz zaznaczyć również już wklejony kod w edytorze, i użyć komendy  by zamienić go w kod. Użyj kombinacji Ctrl+`, by dodać fragment kodu bez oznaczników języka.

Tabelki

Dodaj przykładową tabelkę używając komendy . Przykładowa tabelka składa się z dwóch kolumn, nagłówka i jednego wiersza.

Wygeneruj tabelkę na podstawie szablonu. Oddziel komórki separatorem ; lub |, a następnie zaznacz szablonu.

nazwisko;dziedzina;odkrycie
Pitagoras;mathematics;Pythagorean Theorem
Albert Einstein;physics;General Relativity
Marie Curie, Pierre Curie;chemistry;Radium, Polonium

Użyj komendy by zamienić zaznaczony szablon na tabelkę Markdown.

Lista uporządkowana i nieuporządkowana

Możliwe jest tworzenie listy numerowanych oraz wypunktowanych. Wystarczy, że pierwszym znakiem linii będzie * lub - dla listy nieuporządkowanej oraz 1. dla listy uporządkowanej.

Użyj komendy by dodać listę uporządkowaną.

1. Lista numerowana
2. Lista numerowana

Użyj komendy by dodać listę nieuporządkowaną.

* Lista wypunktowana
* Lista wypunktowana
** Lista wypunktowana (drugi poziom)

Składnia Markdown

Edytor obsługuje składnię Markdown, która składa się ze znaków specjalnych. Dostępne komendy, jak formatowanie , dodanie tabelki lub fragmentu kodu są w pewnym sensie świadome otaczającej jej składni, i postarają się unikać uszkodzenia jej.

Dla przykładu, używając tylko dostępnych komend, nie możemy dodać formatowania pogrubienia do kodu wielolinijkowego, albo dodać listy do tabelki - mogłoby to doprowadzić do uszkodzenia składni.

W pewnych odosobnionych przypadkach brak nowej linii przed elementami markdown również mógłby uszkodzić składnie, dlatego edytor dodaje brakujące nowe linie. Dla przykładu, dodanie formatowania pochylenia zaraz po tabelce, mogłoby zostać błędne zinterpretowane, więc edytor doda oddzielającą nową linię pomiędzy tabelką, a pochyleniem.

Skróty klawiszowe

Skróty formatujące, kiedy w edytorze znajduje się pojedynczy kursor, wstawiają sformatowany tekst przykładowy. Jeśli w edytorze znajduje się zaznaczenie (słowo, linijka, paragraf), wtedy zaznaczenie zostaje sformatowane.

  • Ctrl+B - dodaj pogrubienie lub pogrub zaznaczenie
  • Ctrl+I - dodaj pochylenie lub pochyl zaznaczenie
  • Ctrl+U - dodaj podkreślenie lub podkreśl zaznaczenie
  • Ctrl+S - dodaj przekreślenie lub przekreśl zaznaczenie

Notacja Klawiszy

  • Alt+K - dodaj notację klawiszy

Fragment kodu bez oznacznika

  • Alt+C - dodaj pusty fragment kodu

Skróty operujące na kodzie i linijkach:

  • Alt+L - zaznaczenie całej linii
  • Alt+, Alt+ - przeniesienie linijki w której znajduje się kursor w górę/dół.
  • Tab/⌘+] - dodaj wcięcie (wcięcie w prawo)
  • Shit+Tab/⌘+[ - usunięcie wcięcia (wycięcie w lewo)

Dodawanie postów:

  • Ctrl+Enter - dodaj post
  • ⌘+Enter - dodaj post (MacOS)