Dlaczego klasy danych są uważane za zapach kodu?

18

W tym artykule twierdzi się, że klasa danych to „zapach kodu”. Powód:

To normalne, gdy nowo utworzona klasa zawiera tylko kilka pól publicznych (a może nawet garść programów pobierających / ustawiających). Ale prawdziwą mocą obiektów jest to, że mogą one zawierać typy zachowania lub operacje na swoich danych.

Dlaczego obiekt zawiera tylko dane? Jeśli podstawowym obowiązkiem klasy jest reprezentowanie danych, czy dodanie metod działających na danych nie złamałoby zasady pojedynczej odpowiedzialności ?

Sipo
źródło
1
Będzie to silnie zależeć od funkcji językowych. Na przykład w Pythonie nie ma rozróżnienia między „polem” a jego akcesoriami, chyba że robisz wszystko, co w twojej mocy, aby napisać Javę w Pythonie .
jscs
1
Wydaje mi się, że posiadanie niektórych klas zawierających tylko dane nie jest zapachem kodu, ale jeśli większość z nich jest podobna, to mówimy o antipattern „domenie anemiczne” en.wikipedia.org/wiki/Anemic_domain_model
Tulains Córdova
1
Nie rozumiem, jak to pytanie jest duplikatem. Pozostałe pytania dotyczą wykorzystania klas danych w OO, podczas gdy to dotyczy wad klas danych - zupełnie innych tematów.
Milos Mrdovic
Być może zechcesz przeczytać tę odpowiedź na temat przepełnienia stosu, która jest znacznie bardziej zróżnicowana niż najczęściej głosowana odpowiedź, która postuluje niższość modelu bogatej domeny i przedstawia ją jak udowodniony fakt. stackoverflow.com/questions/23314330/…
McLovin

Odpowiedzi:

31

Nie ma absolutnie nic złego w posiadaniu czystych obiektów danych. Autor utworu szczerze mówiąc nie wie o czym mówi.

Takie myślenie wynika ze starego, nieudanego pomysłu, że „prawdziwe OO” jest najlepszym sposobem na programowanie i że „prawdziwy OO” polega na „bogatych modelach danych”, w których łączy się dane i funkcjonalność.

Rzeczywistość pokazała nam, że tak naprawdę jest odwrotnie, szczególnie w tym świecie rozwiązań wielowątkowych. Czyste funkcje w połączeniu z niezmiennymi obiektami danych to zdecydowanie lepszy sposób na kodowanie.

David Arno
źródło
1
Chciałem tylko dodać, że czyste obiekty danych mogą być nieocenione w modelowaniu relacji, sprawdzaniu poprawności, kontrolowaniu dostępu / zmian.
Adrian
2
Chociaż dobrze, jeśli te czyste funkcje, które jako argument przyjmują tylko instancję niezmiennego obiektu danych, są implementowane jako metody na obiekcie danych.
RemcoGerlich,
7
Jeśli funkcja przyjmuje argument tego typu danych, jest już sprzężona z danymi.
RemcoGerlich,
4
Głosowanie w dół, ponieważ jest to niepoprawne lub co najwyżej kwestia opinii. W języku OO zwykle sensowne jest, aby obiekt zawierał zarówno dane (które mogą być niezmienne!), Jak i metody, które na nie działają. Czyste funkcje i oddzielne dane są świetne w paradygmatach innych języków, ale jeśli robisz OO, rób to całkowicie.
Marnen Laibow-Koser
3
Rzeczywistość pokazała nam wiele rzeczy. -1 dla dogmatycznej wiedzy „wszyscy inni zawiedli”. Ponadto autor nie twierdzi, że czyste obiekty danych są „złe”, tylko że są „zapachem kodu” i zasługują na przesłuchanie. Żałuję tylko, że mam jeden głos oddania dla mojego kraju. :-)
user949300
7

Nie ma absolutnie nic złego w posiadaniu czystych obiektów danych. Autor ma opinię, której nie podzielają znani mi twórcy oprogramowania.

Zwłaszcza w przypadku mapowania bazy danych na ogół masz klasy jednostek, które zawierają tylko pola przechowywane w bazie danych oraz moduły pobierające i ustawiające. Wikipedia Hibernacja (framework)

Idea dziury w ziarenach Java wykorzystywanych przez wiele narzędzi / struktur opiera się na klasach danych zwanych ziarenkami, które zawierają tylko pola oraz powiązane z nimi funkcje pobierające i ustawiające. Wikipdia JavaBeans

Fazit:
Jeśli ktoś twierdzi, że coś jest „złe” lub „pachnie kodem”, zawsze powinieneś szukać podanych powodów. Jeśli przyczyny nie przekonują, zapytaj kogoś o lepsze powody lub inną opinię. (Tak jak zrobiłeś na tym forum)

MrSmith42
źródło
Autor nie twierdzi, że czyste obiekty danych są „złe”. Mówią, że czyste obiekty danych to „zapach kodu”, co oznacza, że ​​powinieneś pomyśleć dwa razy o ich użyciu.
user949300
1
@ user949300, wydajesz się zdezorientowany. Jeśli autor nazywa je zapachem kodu, oznacza to, że może być z nimi coś nie tak. Ponieważ są one powszechnie uznawane za bardzo dobrą praktykę, wyraźnie nie pachną kodem. Zatem MrSmith42 ma rację: nie ma w nich absolutnie nic złego.
David Arno,
4

Dobry argument, dlaczego Martin Fowler:

„Tell-Don't-Ask to zasada, która pomaga ludziom pamiętać, że orientacja obiektowa polega na łączeniu danych z funkcjami działającymi na tych danych. Przypomina nam, że zamiast pytać o dane dane i działać na podstawie tych danych, powinien zamiast tego powiedzieć obiektowi, co ma robić. To zachęca do przeniesienia zachowania na obiekt, aby przejść do danych ”.

https://martinfowler.com/bliki/TellDontAsk.html

Curtis Yallop
źródło
1
Problem polega na tym, że Fowler sztucznie ogranicza „powiedz, nie pytaj”, zmieniając funkcje z zadawania szerszego zakresu na samo pytanie o zakres obiektu. Nadal pytają. „Powiedz, nie pytaj” może w rzeczywistości pójść o krok dalej, naprawdę mówiąc tym funkcjom za pomocą ich list argumentów. W ten sposób dochodzimy do obiektów danych i oddzielnych (pod względem danych) funkcji będących prawdziwą implementacją „powiedz, nie pytaj”. Zamiast być dobrym argumentem za twierdzeniem, że klasy danych mają zapach kodu, w rzeczywistości dodatkowo dowodzi czegoś przeciwnego.
David Arno,
2
@DavidArno Zapomniałeś o enkapsulacji i ukrywaniu się. Mówisz obiektowi, aby wykonał metodę składową, a metoda składowa wchodzi do czarnej skrzynki obiektu i robi wszystko, aby uzyskać odpowiedź. Jeśli pytasz obiekt z zewnątrz, nie masz dostępu do jego stanu prywatnego, więc albo obiekt ujawnia więcej stanu, niż jest to mądre, albo pytający musi przeskoczyć więcej obręczy, niż to konieczne. Nie rozumiem, dlaczego kiedykolwiek „pytasz” obiekt w środowisku OO. (Inne paradygmaty programowania mogą oczywiście wymagać różnych podejść.)
Marnen Laibow-Koser
2
@DavidArno Oczywiście możesz przekazać bazparametr jako metodę statyczną, ale aby to zrobić, musisz najpierw poprosić o obiekt. Być może ma to sens w paradygmacie programowania, w którym metody były pierwotne (jak powiedzmy programowanie funkcjonalne), ale w środowisku OO absolutnie tak nie jest, ponieważ obiekty są pierwotne i powinny zawierać zarówno dane, jak i funkcje do działania. Twierdzenie, że usunięcie metody z obiektu zwiększyło enkapsulację, jest również dokładnie wstecz , o ile wiem, ponieważ oznacza to, że teraz bazpojawiłeś się poza obiektem.
Marnen Laibow-Koser
1
@ MarnenLaibow-Koser, nie twierdzę, że „robię OO”. Piszę kod i używam do tego dobrych technik. Niezależnie od tego, czy te techniki pochodzą z paradygmatu funkcjonalnego, paradygmatu OO, czy paradygmatu cholerny, nie interesuje mnie to. Wybranie paradygmatu i trzymanie się go tak dokładnie, jak to możliwe, to czysty dogmat. To jest złe To jest niedorzeczne. Dusi cię i powoduje gorszy kod. Nie rób tego
David Arno
1
@DavidArno Przeciwnie, jeśli w pełni zaangażujesz się w paradygmat (dowolny porządny paradygmat, nie tylko OO), otrzymasz potężne abstrakcje na wysokim poziomie i logicznie spójny, możliwy do utrzymania kod. Nie mówię, że jest to dogmatyczne, ale raczej pragmatyczne. Widziałem i utrzymywałem zbyt wiele kodu, który najwyraźniej został wytworzony z takim podejściem jak twoje, w którym autor tak naprawdę nie przywiązał się do logicznej spójności używanego systemu. Jest trudny do zrozumienia, trudny w utrzymaniu i trudny do modyfikacji. Żaden paradygmat nie jest idealny, ale ogólnie mieszanka (o ile nie zostanie dokładnie przemyślana) jest trudniejsza do zrozumienia.
Marnen Laibow-Koser
2

Musisz zrozumieć, że istnieją dwa rodzaje obiektów:

  • Obiekty, które mają zachowanie . Powinny one powstrzymywać się od publicznego udostępniania większości / dowolnych członków danych. Spodziewam się tylko bardzo niewielu zdefiniowanych metod dostępu.

    Przykładem może być skompilowane wyrażenie regularne: Obiekt jest tworzony w celu zapewnienia określonego zachowania (w celu dopasowania łańcucha do określonego wyrażenia regularnego i zgłoszenia (częściowych) dopasowań), ale sposób, w jaki skompilowane wyrażenie regularne działa, nie należy do użytkownika biznes.

    Większość klas, które piszę, należą do tej kategorii.

  • Obiekty, które są tak naprawdę tylko danymi . Powinny one po prostu ogłosić wszystkich swoich członków publicznie (lub zapewnić im pełny zestaw akcesoriów).

    Przykładem może być klasa Point2D. Nie ma absolutnie żadnego niezmiennika, który należy zapewnić członkom tej klasy, a użytkownicy powinni mieć dostęp do danych za pośrednictwem myPoint.xi myPoint.y.

    Osobiście nie używam takich klas dużo, ale wydaje mi się, że nie ma większego kodu, który napisałem, który gdzieś nie używa takiej klasy.

Osiągnięcie biegłości w orientacji obiektowej obejmuje uświadomienie sobie, że to rozróżnienie istnieje, i nauczenie się klasyfikowania funkcji klasy do jednej z tych dwóch kategorii.


Jeśli kodujesz w C ++, możesz uczynić to rozróżnienie wyraźnym, używając classdla pierwszej kategorii obiektów i structdla drugiej. Oczywiście oba są równoważne, ale classoznacza to, że wszyscy członkowie są domyślnie prywatni, podczas gdy domyślnie structdeklarują wszystkich członków jako publiczni. Który właśnie rodzaj informacji chcesz przekazać.

cmaster - przywróć monikę
źródło
1
Wyjaśnienie downvote byłoby fajne ...
cmaster - przywróć Monikę
Dziękuję za odpowiedź. Nienawidzę, gdy ludzie głosują bez powodu. Jeśli masz problem z odpowiedzią, wyjaśnij dlaczego .
Sipo