Nie dziedzicz wcale

Oryginalny post: Inherits Nothing

Autor: Jeff Atwood

Zauważyłeś, że nowi programiści .NET mają tendencję do używaniu dziedziczenia do... hmm... wszystkiego? W pewnym stopniu jest to zrozumiałe, ponieważ dziedziczenie jest wykorzystywane w całym frameworku; wszystko w .NET dziedziczy z jednej głównej klasy. Jest jednak drobna różnica: my piszemy jakąś tam logikę biznesową, nie tworzymy języka. To co jest właściwe podczas tworzenia języka może nie być odpowiednie dla prostego kodu, który przede wszystkim musi być łatwy w utrzymaniu i łatwy do zrozumienia.

Dziedziczenie to wyspecjalizowany mechanizm i powinno być używane tylko w sytuacjach, w których rzeczywiście zachodzą relacja rodzic-potomek i wszystkie wynikające z tego właściwości. Jestem przekonany, że właśnie w tym momencie straciłem kilku czytelników będących purystami OO. Więc zanim pomyślisz sobie, że jestem szaleńcem, który całkowicie porzucił zasady OO, chciałbym zwrócić uwagę na moje doborowe towarzystwo: Dan Appleman uważa podobnie. Poniżej znajduje się krótki wycinek z jego doskonałej (i cały czas aktualnej) książki Moving to VB.NET: Strategies, Concepts and Code:

Byłem programistą C++ dłużej niż Visual Basic – i zresztą cały czas w tych dwóch językach programuję. Byłem zdecydowanym zwolennikiem programowania zorientowanego obiektowo od czasu kiedy zrozumiałem ideę klas w 1977 roku. Programowałem również we frameworkach takich jak ATL, które w bardzo dużym stopniu – i to z powodzeniem - opierają się na dziedziczeniu.

Ale jeśli chodzi o używanie dziedziczenia w moich aplikacjach lub komponentach przez te wszystkie lata, przychodzi mi do głowy może pół tuzina przypadków (co najwyżej), kiedy dziedziczenie było rzeczywiście właściwym wyborem.

Więc, tak, .NET używa dziedziczenia – ono jest wbudowane w architekturę. Tak, kod tworzony przez różnych projektantów będzie opierał się na dziedziczeniu, aby dać Ci framework na którym będziesz mógł budować swój własny kod.

Ale, jeśli rzeczywiście zrozumiałeś dziedziczenie, możesz przez cały okres swojej kariery nie stworzyć ani jednej klasy lub komponentu w oparciu o dziedziczenie.

Prowadzi to do wniosków, które również ja wypowiem: dziedziczenie jest tylko jedną z wielu możliwych dróg do ponownego wykorzystania kodu. Posiadanie prostego obiektu, bez tych wszystkich skomplikowanych (i zazwyczaj ukrytych) zasad dziedziczenia jest zazwyczaj wystarczające dla osiągnięcia najważniejszego celu: ponownego wykorzystania kodu.

Na argument, że „skoro .NET jest zbudowany na dziedziczeniu, my również powinniśmy na nim budować!”, odpowiem pytaniem: jak wielu z nas tworzy języki programowania? Jak wielu z nas tworzy jądra systemów operacyjnych? W rzeczywistości są to ekstremalne i rzadkie przypadki, i nie powinny być stosowane jako wzór w kreowaniu czegoś innego.

Dla mnie narzut dziedziczenia – podobnie jak zwiększanie stopnia skomplikowania w jakikolwiek inny sposób – z góry skazuje je na odrzucenie, przynajmniej dopóki nie zostanie uzasadniona inna decyzja. Nie używaj dziedziczenia, dopóki brakuje stuprocentowych argumentów za jego użyciem.

Data publikacji oryginału: sierpień 7 2004

10 komentarze:

michal pisze...

Dziedziczenie nie powinno być używane w celu ponownego użycia kodu (jeżeli to był jedyny cel). Uzasadniony cel dziedziczenia to polimorficzne wykorzystywanie obiektów (oczywiście przy odpowiednim zastosowaniu zasady LSP).

michal pisze...

Dziedziczenie nie powinno być używane w celu ponownego użycia kodu. Uzasadnione użycie dziedziczenia to polimorficzne wykorzystanie obiektów (z odpowiednim zastosowaniem reguły LSP).

michal pisze...

Fajnie, mimo, że pokazało mi błąd dodania komentarza to i tak go dodało :)

Robert Gawron pisze...

Autor poszedł na łatwiznę i skrytykował, a nie podał przykładów, gdzie błędnie wykorzystano dziedziczenie i nie podał też alternatyw.

JM pisze...

Błędem jest tworzenie specyfikacji, typu 'kwadrat', 'kwadratzdziurka : kwadrat', itd. w przypadku c++, było by nawet 'kwadratzdziurka : kwadrat, dziurka'. itd.

Powinno się skupić na tworzeniu interfejsów i klas abstrakcyjnych - po tym już trzeba dziedziczyć, ale pozwala to ładnie ogarnąć projekt ;-)

//PS. sorry.. wypiłem dwie kawy i nadal przymulony jestem, jak dojdę do siebie to postaram się jaśniej napisać;-)

Robert Gawron pisze...

Ciekawy artykuł z Wikipedii odnośnie niektórych błędów w stosowaniu dziedziczenia:
http://en.wikipedia.org/wiki/Liskov_substitution_principle

(Zapomniałem dopisać w poprzednim komentarzu)

Anonimowy pisze...

Dziedziczenie da się zastąpić kompozycją, co może korzystnie wpłynąć na elastyczność kodu. Nie zawsze jednak elastyczność jest potrzebna, a do tego koszt w postaci dodatkowej pracy na pewno wystąpi ;)

Konrad Kubiec pisze...

Czy to tylko mi się wydaje, że ten nowy wpis to niezbyt wysokiej jakości zapychacz? Jak dyskusja na poziomie: Co lepsze, ++ czy +=? I bez żadnych argumentów "technicznych". Nawet nie zbudowano wyraźnego punktu do dyskusji. Brak polotu, pomysłu, czy uszczypliwej uwagi. Coś ciekawszego poproszę następnym razem!

mixer pisze...

@Konrad Kubiec
Dyskusja nad używaniem/nie używaniem dziedziczenia aż tak trywialna chyba nie jest :) Myślę, że trudno nie zgodzić się z autorem, że dziedziczenie powinno być stosowane z umiarem. Bo z dziedziczeniem jest trochę jak z tym młotkiem - "gdy jest twoim jedynym narzędziem, wszystko dookoła wygląda na gwóźdź" (http://demotywatory.pl/1188331/Mlotek).

Jeżeli chcesz bardziej zaawansowany, techniczny tekst, to polecam:
Uses and Abuses of Inheritance, Part 1
Uses and Abuses of Inheritance, Part 2

nilphilus pisze...

@mixer: temat ciekawy, wpis taki sobie ;-)
podziękował za linki, przeglądam sobie ;-)

Prześlij komentarz

Related Posts with Thumbnails