Czy OOP spełnia obietnicę ponownego użycia kodu? Jakie są alternatywy dla ponownego wykorzystania kodu?

56

Być może największą obietnicą użycia paradygmatu obiektowego jest ponowne użycie kodu. Niektórzy spierają się, że udało się to osiągnąć. Dlaczego został (nie) osiągnięty?

Czy kod jest ponownie wykorzystywany, ponieważ definiuje go OOP, czy projekty są bardziej produktywne?

Lub łatwiejszy w zarządzaniu? Lub łatwiejsze w utrzymaniu? A może z lepszą jakością?

Prawdopodobnie wszyscy zgadzamy się, że ponowne użycie kodu jest dobrą rzeczą, ale istnieje kilka sposobów na osiągnięcie tego celu. Pytanie dotyczy metody ponownego wykorzystania kodu oferowanej przez OOP. Czy to dobrze? Czy istnieją lepsze metody ponownego wykorzystania kodu niż orientacja obiektowa, podklasowanie, polimorfizm itp.? Jakie są lepsze sposoby? Dlaczego ?

Poinformuj nas o swoich doświadczeniach z ponownym użyciem OOP lub ponownym wykorzystaniu innych paradygmatów.

powiększenia
źródło
3
Ale to duplikat: programmers.stackexchange.com/questions/1059
Frank Shearar
7
Jest to komplementarne, a nie dokładnie powielone. Przeformułowałem, aby lepiej zrozumieć różnicę.
Maniero
Jeśli możesz głosować i uważasz, że jest to przydatne pytanie lub poniżej znajdziesz przydatne odpowiedzi, zagłosuj. Witryny StackExchange potrzebują głosów, aby zbudować dobrą społeczność. Możesz dać 30 głosów dziennie, nie marnuj ich. Specjalnie użytkownicy z wysoką renomę i niskich liczenia głosów podane proszę przeczytać: meta.programmers.stackexchange.com/questions/393/...
Maniero
2
Podobne pytanie tutaj: programmers.stackexchange.com/questions/1059/…
George Marian
2
@j_random_hacker: przeczytaj komentarze.
Maniero

Odpowiedzi:

34

Ponowne użycie kodu jest całkiem dobrym pomysłem. Niezbyt dobry .

Mam perspektywę zaczerpniętą z około 30 lat inżynierii oprogramowania, która próbuje „ponownie wykorzystać”.

Zacząłem badać „ponowne użycie kodu” jako temat badawczy już w latach 80., po odkryciu, że ponownie wykorzystałem projekt jednego systemu operacyjnego, który zbudowałem na początku lat 70., dla innego systemu operacyjnego, który zbudowałem pod koniec lat 70.

Dobrą częścią ponownego wykorzystania kodu jest zdolność do ponownego wykorzystania istniejącego wcześniej, uczciwego boga kodu. Ale świat jest pełen kodu; jak znaleźć to, czego chcesz? Oto, co nazywam klątwą ponownego użycia :

Jestem Święty Mikołaj (ok Open Source) i mam worek 1 miliarda komponentów oprogramowania. Możesz mieć jeden z nich.

Powodzenia w wyborze.

Aby dobrze rozwiązać problem ponownego użycia:

  • użytkownik musi w jakiś sposób określić, czego potrzebuje (funkcjonalność, wydajność, język docelowy, założenia środowiskowe, ...)
  • musi istnieć biblioteka kodu „wielokrotnego użytku”, który został zaindeksowany na różne sposoby według tych potencjalnych kryteriów
  • musi istnieć jakiś mechanizm wybierania elementów kandydujących (przy miliardie elementów nie można na nie patrzeć osobiście)
  • musi istnieć sposób na scharakteryzowanie, jak daleko od specyfikacji są wybrani kandydaci
  • powinien istnieć jakiś regularny proces, aby umożliwić użytkownikowi modyfikację wybranego kodu wielokrotnego użytku (oto największy wkład OOP: możesz edytować istniejący komponent / obiekt, zastępując jego szczeliny. OOP nie zapewnia żadnej innej pomocy).
  • wszystko to musi być zdecydowanie tańsze niż zwykłe przekodowanie

Przez lata odkryto przede wszystkim, że aby kod mógł być ponownie użyty, musi być zaprojektowany w tym celu lub zawiera zbyt wiele domniemanych założeń. Biblioteki, które odniosły największe sukcesy, były w rzeczywistości dość małe. Prawdopodobnie biblioteki i frameworki są kodem „wielokrotnego użytku” i odnoszą ogromne sukcesy; Java i C # odnoszą sukcesy nie dlatego, że są całkiem niezłymi językami komputerowymi, ale raczej dlatego, że mają do dyspozycji ogromne, dobrze zaprojektowane, zaimplementowane i udokumentowane biblioteki. Ale ludzie nie patrzą na kod źródłowy w bibliotekach; po prostu wywołują dobrze udokumentowany interfejs API (zaprojektowany tak, aby był ogólnie użyteczny).

To, czego ponowne użycie kodu nie dokonało (OOP też), zapewnia poprawę wielkości naszych systemów kodowania.

Myślę, że kluczową wadą jest to, że jakiekolwiek ponowne użycie kodu jest zasadniczo ograniczone, ponieważ kod ma zbyt wiele założeń . Jeśli sprawisz, że kod będzie mały, zminimalizujesz założenia, ale wtedy koszt budowy od zera nie będzie bardzo duży, a zyski z ponownego użycia nie będą skuteczne. Jeśli sprawisz, że fragmenty kodu będą ogromne, będą one prawie bezużyteczne w nowym kontekście. Podobnie jak Guliwer, są przywiązani do plaży milionem małych sznurków i po prostu nie możesz sobie pozwolić na przecięcie ich wszystkich.

Powinniśmy pracować nad ponownym wykorzystaniem wiedzy do konstruowania kodu . Jeśli możemy to zrobić, możemy zastosować tę wiedzę do skonstruowania potrzebnego nam kodu, obsługując bieżący zestaw założeń.

Aby to zrobić, nadal potrzebna jest ta sama zdolność specyfikacji do charakteryzowania komponentów oprogramowania (wciąż musisz powiedzieć, co chcesz!). Ale następnie zastosujesz tę wiedzę „konstrukcyjną” do specyfikacji, aby wygenerować pożądany kod.

Jako społeczność nie jesteśmy jeszcze w tym zbyt dobrzy. Ale ludzie robią to cały czas; dlaczego nie możemy tego zautomatyzować? Istnieje wiele badań, co pokazuje, że można to zrobić w wielu okolicznościach.

Jednym z kluczowych urządzeń potrzebnych do tego są mechaniczne narzędzia do akceptowania „opisów komponentów” (są to tylko formalne dokumenty i można je analizować jak języki programowania) i stosować do nich transformacje programów .

Kompilatory już to robią: -} I są naprawdę dobre w klasie problemów, które rozwiązują.

Modele UML z generowaniem kodu to jedna próba tego. Niezbyt dobra próba; właściwie w większości modeli UML mówi się: „Mam dane, które wyglądają tak”. Trudno jest wygenerować prawdziwy program, jeśli pominięto funkcjonalność.

Próbuję zbudować praktyczne systemy transformacji programów, narzędzie o nazwie DMS . Byłem dość dobrze rozproszony, stosując transformacje programu nie tyle do abstrakcyjnych specyfikacji, aby wygenerować kod, ale raczej do starszego kodu, aby go wyczyścić. (Są to ten sam problem w streszczeniu!). (Budowa takich narzędzi zajmuje dużo czasu; robię to od 15 lat, a tymczasem musisz jeść).

Ale DMS ma dwie kluczowe właściwości, które opisałem powyżej: możliwość przetwarzania dowolnych specyfikacji formalnych oraz zdolność do przechwytywania „wiedzy na temat generowania kodu” jako transformacji i stosowania ich na żądanie. I, co niezwykłe, generujemy w niektórych szczególnych przypadkach jakiś dość interesujący kod ze specyfikacji; DMS jest w dużej mierze zbudowany przy użyciu samego siebie do generowania swojej implementacji. To osiągnęło dla nas przynajmniej część obietnicy ponownego wykorzystania (wiedzy): wyjątkowo znacznego wzrostu wydajności. Mam zespół około 7 osób technicznych; napisaliśmy prawdopodobnie 1-2 MSLOC „specyfikacji” dla DMS, ale mamy około 10MSLOC wygenerowanego kodu.

Podsumowanie: ponowne wykorzystanie wiedzy generacyjnej to zwycięstwo, a nie ponowne użycie kodu .

Ira Baxter
źródło
4
IMHO, najlepsza odpowiedź. Ważną rzeczą jest ponowne wykorzystanie wiedzy / pomysłu, a nie kod.
kravemir
4
Mostly what has been discovered over the years is that for code to be reusable, it sort of has to be designed for that purpose, or it contains too many implicit assumptions.Doszedłem do podobnego wniosku, ale nie mogłem wyrazić tego tak zwięźle.
biziclop,
36

Ponowne użycie kodu jest osiągane w OOP, ale jest również osiągane w programowaniu funkcjonalnym. Za każdym razem, gdy pobierzesz blok kodu i sprawisz, że będzie można go wywołać przez resztę kodu, abyś mógł korzystać z tej funkcji w innym miejscu, jest ponowne użycie kodu.

Ten rodzaj ponownego użycia kodu sprawia, że ​​kod jest łatwiejszy w zarządzaniu, ponieważ zmiana tego jednego bloku na żądanie zmienia wszystkie miejsca, które są nazywane. Powiedziałbym, że ten wynik również poprawił jakość i czytelność.

Nie jestem pewien, czy OOP jest po to, aby zapewnić ponowne użycie kodu. Patrzę na OOP jako sposób na interakcję z obiektami i abstrahowanie szczegółów struktury danych.

Z Wikpedia:

Programowanie obiektowe ma swoje korzenie, które sięgają lat 60. XX wieku. Ponieważ sprzęt i oprogramowanie stają się coraz bardziej złożone, zarządzanie często staje się problemem. Naukowcy badali sposoby utrzymania jakości oprogramowania i opracowali programowanie obiektowe częściowo w celu rozwiązania typowych problemów poprzez silne podkreślenie dyskretnych jednostek logiki wielokrotnego użytku [potrzebne źródło]. Technologia skupia się raczej na danych niż na procesach, a programy składają się z samowystarczalnych modułów („klas”), z których każde wystąpienie („obiekty”) zawiera wszystkie informacje potrzebne do manipulowania własną strukturą danych („członkami”). Jest to sprzeczne z istniejącym programowaniem modułowym, które dominowało przez wiele lat i które koncentrowało się na funkcji modułu, a nie konkretnie danych, ale w równym stopniu umożliwiło ponowne użycie kodu, oraz samowystarczalne jednostki logiki programowania wielokrotnego użytku, umożliwiające współpracę poprzez zastosowanie połączonych modułów (podprogramów). To bardziej konwencjonalne podejście, które nadal się utrzymuje, ma tendencję do oddzielnego rozpatrywania danych i zachowania.

Chris
źródło
9
Programowanie funkcjonalne +1 może być sposobem na ponowne użycie kodu.
Jonas
1
@Matthieu M .: Cóż, jak wielokrotnego użytku double sqrt (double x)? Czyste funkcje są archetypem ponownego użycia.
Joonas Pulakka
3
@Joonas: double sqrt(double x), float sqrt(float x), int sqrt(int x)można zdefiniować wiele z nich, podczas gdy z ogólnym języku programowania trzeba Number sqrt(Number x)i można z nim zrobić.
Matthieu M.,
1
@Matthieu M .: Rzeczywiście, generycy zmniejszają replikację kodu, więc jest „bardziej wielokrotnego użytku”, tak. Myślę jednak, że prawdziwym kluczem do ponownego użycia jest zdefiniowanie prostych, małych, rozsądnych, czystych funkcji (jest to kierunek „programowania funkcjonalnego”) i przekazywanie ich, co jest możliwe w C. To bardziej ogólny styl programowania niż o możliwościach samego języka.
Joonas Pulakka
1
@Joonas: Ach, brakowało mi czystego słowa, masz rację, komponowanie małych czystych funkcji jest po prostu świetne, a nawet C oferuje do tego wskaźniki.
Matthieu M.
15

Tak i nie

Ponowne użycie kodu jest terminem uniwersalnym dla wielu różnych działań.

  1. Ponowne użycie kodu w ramach jednego projektu. Do tego doskonale nadaje się OO, dobrze zaprojektowana aplikacja dokładnie odwzoruje relacje modelowanego świata, eliminując w ten sposób zduplikowany kod w jak największym stopniu i wskazanym. Można jednak argumentować, że technologie sprzed OO mogą osiągnąć to samo, co jest prawdą, ale OO jest pod wieloma względami wygodniejsze.
  2. Biblioteki stron trzecich Wydaje się, że działa to równie dobrze z OO lub bez.
  3. Wielokrotne ponowne użycie kodu Największą obietnicą ponownego wykorzystania kodu przez OO był kod, który raz napisany dla jednej aplikacji może być później ponownie wykorzystany dla innej aplikacji, dla której nie został specjalnie zaprojektowany. Było to wściekłość, gdy pojęcie OO przeszło przez drzwi wyższych biur zarządzania, a OO zupełnie go nie osiągnął. Okazało się, że cel był kluczowym aspektem projektowania OO (i być może całego kodu proceduralnego, ale to tylko moja teoria), a próby zmiany przeznaczenia kodu zakończyły się katastrofami serwisowymi. (Dobrze znane antifatternity starego frameworka, którego nikt nie odważy się zmodyfikować, i jego przyjaciel, stąd zwykle pochodzą nieco inne frameworki dla każdej aplikacji).
biziclop
źródło
13

Chciałbym zamieścić długą odpowiedź, ale dlaczego? Udi Dahan wyjaśnia to znacznie lepiej niż potrafię.

http://www.udidahan.com/2009/06/07/the-fallacy-of-reuse/

Oto początek posta:

Ta branża jest zajęta ponownym wykorzystaniem.

Istnieje przekonanie, że gdybyśmy ponownie wykorzystali więcej kodu, wszystko byłoby lepiej.

Niektórzy nawet posunęli się do stwierdzenia, że ​​cały punkt orientacji obiektowej został ponownie wykorzystany - nie było, kapsułkowanie było wielką rzeczą. Po tej orientacji na komponenty miało nastąpić ponowne użycie. Najwyraźniej to również nie potoczyło się tak dobrze, ponieważ teraz pokładamy naszą nadzieję na orientację na usługi.

Całe księgi wzorców zostały napisane na temat tego, jak osiągnąć ponowne użycie z ukierunkowaniem dnia. Usługi zostały sklasyfikowane pod każdym względem, starając się to osiągnąć, od usług podmiotów i usług działalności, poprzez usługi procesów i usługi orkiestracji. Usługi tworzenia reklamowano jako klucz do ponownego użycia i tworzenia usług wielokrotnego użytku.

Równie dobrze mogę ci zdradzić mały, brudny sekret:

Ponowne użycie jest błędem

Tony
źródło
4
-1. Pan Dahan jest zajęty słomiankami; nikt poważnie nie wykorzystuje kodu nieogólnego, jak sugeruje, a jeśli usuniesz ten argument z jego artykułu, w rzeczywistości popiera lub odpowiednio wykorzystuje kod .
Steven A. Lowe,
3
@Steven A. Lowe Cóż, chciałbym, żeby to była prawda. Żałuję, że nie miałem szczęścia, ponieważ widziałem ponowne użycie kodu w formie innej niż ogólna. To nie było ładne.
Tony
1
jestem pewien, że to nie było - ale czy były poważne ? dilbert.com/strips/comic/1996-01-31
Steven A. Lowe
1
Uzgodnione, koszt ponownego użycia kodu jest naprawdę wysoki, więc nie opłaca się, chyba że mówisz w skali klas bazowych Java lub .NET. Zobacz youtube.com/watch?v=aAb7hSCtvGw
Andomar
13

Zgadzam się z Chrisem, programowanie funkcjonalne jest dobrym sposobem na ponowne użycie kodu.

Wiele programów ma powtarzające się struktury kodu. W tym celu w świecie OOP stosowane są niektóre wzorce projektowe , ale można to osiągnąć przez funkcje rekurencyjne i dopasowanie wzorców w funkcjonalnych językach programowania. Więcej informacji na ten temat znajduje się w pierwszym rozdziale Programowania funkcjonalnego w rzeczywistym świecie .

Myślę, że głębokie dziedzictwo w OOP może w wielu przypadkach wprowadzać w błąd. Masz klasę, a wiele ściśle powiązanych metod jest zaimplementowanych w różnych plikach. Jak powiedział Joe Armstrong o OOP:

Problem z językami obiektowymi polega na tym, że mają one całe to ukryte środowisko, które ze sobą niosą. Chciałeś banana, ale dostałeś goryla trzymającego banana i całą dżunglę.

Funkcje wysokiego rzędu są również bardzo przydatne, jeśli chodzi o ponowne użycie kodu, np. mapI foldrjest to podstawa MapReduce firmy Google .

Asynchroniczne przekazywanie wiadomości jest również dobrym sposobem na zorganizowanie złożonego oprogramowania, a niektórzy informatycy twierdzą, że założono, że obiekty komunikują się ze sobą asynchronicznie jak w Tell, nie pytaj o zasadę OOP. Zobacz więcej na ten temat w Programowaniu obiektowym: zła ścieżka? gdzie cytowany jest Joe Armstrong :

Zacząłem się zastanawiać, czym jest programowanie obiektowe i myślałem, że Erlang nie jest obiektowy, to funkcjonalny język programowania. Następnie mój promotor powiedział: „Ale mylisz się, Erlang jest wyjątkowo zorientowany obiektowo”. Powiedział, że języki zorientowane obiektowo nie są zorientowane obiektowo. Mogę myśleć, choć nie jestem do końca pewien, czy w to wierzę, czy nie, ale Erlang może być jedynym językiem zorientowanym obiektowo, ponieważ 3 założenia programowania zorientowanego obiektowo polegają na tym, że opiera się na przekazywaniu wiadomości , że istnieje izolacja między obiektami i mieć polimorfizm .

Asynchroniczne przekazywanie komunikatów jak w systemach sterowanych zdarzeniami oraz w Erlang jest również bardzo dobrym sposobem na odsprzęganie systemów, a luźne sprzężenie jest ważne w złożonych systemach. Przy dostatecznie oddzielonym systemie możesz ewoluować system podczas pracy, być może w różnych węzłach. Unibet przygotował świetną prezentację na ten temat: Architektura oparta na zdarzeniach domenowych

Myślę jednak, że większość ponownego użycia kodu odbywa się przy użyciu bibliotek i frameworków.

Jonas
źródło
2
Podoba mi się ten cytat z goryla. ^^
gablin 24.01.11
Myślałem, że pytanie dotyczy ponownego użycia kodu, a nie ładnej semantyki ..?
Daniel Lubarov,
6

Skromny potok unix zrobił więcej w zakresie ponownego wykorzystania kodu niż wszystko inne, co pojawiło się i zniknęło. Przedmioty okazały się być intuicyjnym sposobem strukturyzacji kodu, kiedy się pojawiały, a później ludzie zaczęli przyczepiać się do wszystkiego i wszystkiego na nim. Ogólnie rzecz biorąc, obiekty służą do enkapsulacji, a nie do ponownego użycia kodu, ponowne użycie kodu wymaga czegoś więcej, a hierarchia dziedziczenia klas jest słabym substytutem tego, czym tak naprawdę powinien być mechanizm ponownego wykorzystania kodu.

davidk01
źródło
4

OOP nie jest niczym specjalnym; możesz tworzyć kod wielokrotnego użytku z lub bez OOP. Czyste funkcje są szczególnie wielokrotnego użytku : na przykład java.lang.math.sqrt(double)przyjmuje liczbę i podaje liczbę. Bez OOP, ale zdecydowanie bardziej wielokrotnego użytku niż większość dostępnych kodów.

Joonas Pulakka
źródło
4

Z punktu widzenia programowania funkcjonalnego OOP dotyczy głównie zarządzania stanem.

W programowaniu funkcjonalnym możesz łatwo mieć setki przydatnych funkcji dla list: http://haskell.org/ghc/docs/6.12.1/html/libraries/base-4.2.0.0/Data-List.html .

Czy masz setki metod w klasie List? Metody publiczne są uważane za interfejs do stanu wewnętrznego, który ma być niewielki.

Niestety, zamiast (ponownego) używania wielu małych funkcji, niektórzy ludzie powielały funkcjonalność. Dla mnie to dlatego, że OOP nie zachęca do ponownego użycia kodu tak bardzo, jak programowanie funkcjonalne.

LennyProgrammers
źródło
1
Twoje wnioski są błędne, @ Lenny222. W OOP nie ma nic, co wymaga klas do utrzymania stanu. To jest kwestia jego architektury, czy przechowuje stan wewnętrznie, czy, podobnie jak klasy Integer Smalltalk, tworzy nowe obiekty z nowym stanem.
Huperniketes
1
Przykro mi, że nie wyraziłem się w sposób, który zapobiegłby temu nieporozumieniu: miałem na myśli to, że różnica między OOP i FP nie polega na tym, że kod ecourages OOP jest ponownie wykorzystywany bardziej niż FP (co sugeruje nagłówek). Doświadczyłem znacznie lepszego ponownego wykorzystania kodu z FP. Jeśli masz tylko niezmienne klasy, naśladujesz FP, dlaczego OOP w ogóle? W moim POV chodzi o imperatywne zarządzanie stanem.
LennyProgrammers
3

Dla mnie tak, ale nie przez cały czas, i można było to zrobić na inne sposoby.

Przez większość czasu, tworząc abstrakcyjną klasę bazową i tworząc konkretne implementacje tej klasy.

Wiele frameworków korzysta z dziedziczenia w celu ponownego wykorzystania kodu (Delphi, Java, .Net to tylko niektóre, które przychodzą na myśl natychmiast).

Nie oznacza to, że wiele bibliotek narzędziowych i fragmentów kodu również nie wykonało zadania, ale w dobrze zaprojektowanej hierarchii obiektów jest coś przyjemnego.

Chris Buckett
źródło
3

Z mojego doświadczenia odnoszę większy sukces w wykorzystywaniu kodu „wielokrotnego użytku” za pomocą ogólnych narzędzi programistycznych (takich jak szablony C ++) niż przy użyciu zasad OOP, takich jak hierarchie dziedziczenia.

Charles Salvia
źródło
2

OOP jest zbyt otwarty, aby można go było ponownie wykorzystać.

Jest zbyt wiele sposobów na ponowne użycie. Każda klasa publiczna pyta: „stwórz ze mnie nową instancję!” , każda metoda publiczna mówi: „zadzwoń do mnie!” , każda chroniona metoda daje: „zastąp mnie!” - i wszystkie te sposoby ponownego użycia są różne , mają różne parametry, pojawiają się w innym kontekście, wszystkie mają swoje różne zasady, jak je wywoływać / rozszerzać / zastępować.

Interfejs API jest lepszy, jest to ścisły podzbiór punktów OOP (lub non-oop), ale w rzeczywistości interfejsy API są nadmiernie rozbudowane i stale rosną, wciąż istnieje zbyt wiele punktów połączenia. Ponadto dobry interfejs API może ułatwić życie, jest to najlepszy sposób na zapewnienie interfejsu dla OOP.


Paradigm Datadlow zapewnia ścisły interfejs dla komponentów, mają porty następujących typów:

  • konsumenci (nakłady), oraz
  • producenci (wyniki).

W zależności od domeny istnieją pewne typy pakietów, więc klienci i producenci mogą być podłączeni, ponieważ mają te same (lub zgodne) porty. Najpiękniejsza część, którą można zrobić wizualnie, ponieważ nie ma żadnych parametrów ani innych poprawek na połączeniach, tak naprawdę po prostu łączą one konsumenta i producenta.

Byłem trochę niejasne, można spojrzeć na „przepływu danych” tag na StackOverflow lub Wikipedia „datafow programowania” lub Wikipedia „programowanie oparte przepływowym” .

(Napisałem również system przepływu danych w C ++. Więc OOP i DF nie są wrogami, DF to sposób organizacji na wyższym poziomie).

ern0
źródło
2

We CommonLisp istnieje wiele sposobów na ponowne użycie:

  • dynamiczne pisanie, domyślnie ogólny kod

  • imperatywne abstrakty, tj. podprogramy

  • orientacja obiektowa, z wielokrotnym dziedziczeniem i wielokrotną wysyłką

  • abstrakcja składni, zdolność do definiowania nowych konstrukcji syntaktycznych lub skrótu kodu tablicy kotła

  • abstrakcje funkcjonalne, zamknięcia i funkcje wyższego rzędu

Jeśli spróbujesz porównać środowisko CommonLisp z innymi językami, zobaczysz, że główną funkcją, która ułatwia ponowne użycie kodu, jest obecność zarówno obiektowych, jak i funkcjonalnych abstrakcji. Są bardziej komplementarne niż alternatywa: bez żadnej z nich jesteś zmuszony do ponownego zaimplementowania brakujących funkcji w niezdarny sposób. Zobacz na przykład klasy funktorów używane jako zamknięcia i dopasowywanie wzorca, aby uzyskać wysyłkę metody nierozszerzalnej.

Andrea
źródło
1

Naprawdę nie ma czegoś takiego jak „ponowne użycie” w sposób, w jaki ludzie to opisują. Ponowne użycie jest przypadkową własnością czegokolwiek. Trudno to zaplanować. To, co większość ludzi ma na myśli, mówiąc o „ponownym użyciu”, to „używać”. To zdecydowanie mniej atrakcyjny i ekscytujący termin. Kiedy korzystasz z biblioteki, zwykle używasz jej do tego, do czego była przeznaczona. Jesteś nie ponownego użycia, chyba że robisz coś naprawdę szalonego z nim.

W tym sensie ponowne użycie w prawdziwym świecie polega na ponownym przeznaczeniu rzeczy. Mogę ponownie użyć tych miejsc tutaj i zmienić ich położenie, tworząc ... łóżko! Niezbyt wygodne łóżko, ale mogę to zrobić. To nie jest ich główne zastosowanie. Używam ich ponownie poza pierwotną domeną zastosowania. [...] Jutro polecę do Wielkiej Brytanii. Ja nie ponowne samolotu. Wykorzystam go tylko do celu, do którego był przeznaczony, nie ma w tym nic wyszukanego ani ekscytującego.

- Kevlin Henney

fredoverflow
źródło
3
Ludzie uwierzą we wszystko, co zobaczą w druku. Kevlin Henney jest niepoprawny i oparł swoje rozumowanie na braku kontekstu historycznego i złej interpretacji semantycznej. Ponowne użycie kodu było podstawową zasadą programowania od czasów komputerów próżniowych UNIVAC i IBM. Ponowne użycie kodu nie polegało na ponownym przeznaczeniu go dla niektórych funkcji innych niż te, dla których planowano . Napisałeś i skompletowałeś (później skompilowałeś) swoje podprogramy w celu wygenerowania kodu obiektowego, który następnie został połączony z twoim programem. Ponowne użycie naprawdę oznacza to, co dziś powszechnie uważa się w branży.
Huperniketes
Jeśli napiszesz dwie funkcje, które robią dokładnie to samo, NIE używałeś kodu niezależnie od tego, ile razy go używałeś.
JeffO,
Analogia krzesła jest przyjemna i wszystko to, ale tylko jedno słowo: Lego.
biziclop 24.01.11
1

Zaryzykuję wyśmiewanie i przyznanie się, że używałem OOP dopiero niedawno. Nie przychodzi do mnie automatycznie. Większość mojego doświadczenia dotyczy relacyjnych baz danych, więc myślę w tabelach i złączeniach. Istnieją twierdzenia, że ​​lepiej jest uczyć się od samego początku, co pozwala uniknąć konieczności zmiany sposobu myślenia podczas programowania. Nie mam tego luksusu i nie chcę rezygnować z kariery w oparciu o teorię z kości słoniowej. Jak wszystko inne, wymyślę to.

Na początku myślałem, że cała koncepcja nie ma sensu. Wydawało się to po prostu niepotrzebne i stanowiło zbyt duży problem. Wiem, że to szalona rozmowa. Oczywiście potrzeba pewnego poziomu zrozumienia, aby docenić zalety czegokolwiek lub odrzucić je dla lepszych metod.

Ponowne użycie kodu wymaga chęci nie powtarzania kodu, zrozumienia, jak go osiągnąć, planowania z góry. Czy powinieneś unikać ponownego wykorzystywania kodu, gdy zdecydowałeś, że masz przypadek, w którym nie warto? I żaden język nie jest tak ściśle OO, że zgłasza błąd, gdy myśli, że powinieneś odziedziczyć kod z innej klasy. W najlepszym wypadku zapewniają środowisko sprzyjające jego wdrożeniu.

Myślę, że największą zaletą OOP jest ogólna akceptacja sposobu organizacji kodu. Cała reszta to sos. Zespół programistów może nie do końca uzgodnić strukturę wszystkich klas, ale powinien być w stanie znaleźć kod.

Widziałem wystarczająco dużo kodu proceduralnego, aby wiedzieć, że może być gdziekolwiek, a czasem wszędzie.

JeffO
źródło
„I żaden język nie jest tak ściśle OO, że zgłasza błąd, gdy myśli, że powinieneś odziedziczyć kod z innej klasy” - i tak jeszcze nie!
Steven A. Lowe,
1

OOP daje więcej możliwości ponownego wykorzystania kodu. To wszystko.

Steven A. Lowe
źródło
OOP promuje również ponowne użycie interfejsu i ponowne użycie projektu.
rwong
Daje mi znacznie mniej sposobów pisania ogólnego, wielokrotnego użytku, wysoce abstrakcyjnego kodu niż inne paradygmaty, takie jak programowanie funkcjonalne (curry umysłu, biblioteki kombinatora itp.) I metaprogramowanie. W rzeczywistości OOP wydaje się mieć poziom pucharu abstrakcji, gdy alternatywy wcale nie są ograniczone.
SK-logic
@ SK-logic: ortogonal.
Steven A. Lowe,
1

Ponowne wykorzystanie w poziomie: aspekty, cechy, przeszczepy

Klasyczne OO czasami nie pozwala na ponowne użycie kodu, szczególnie gdy oszalejesz w dziedziczeniu z powodu braku lepszego sposobu na dzielenie się rzeczywistą funkcjonalnością między klasami. Dla tego problemu stworzono poziome mechanizmy ponownego wykorzystania, takie jak AOP, cechy i przeszczepy.

Programowanie aspektowe

Uważam AOP za brakującą połowę pomarańczy OOP. AOP nie jest tak naprawdę znany, ale dotarł do kodu produkcyjnego.

Spróbuję to wyjaśnić prostymi słowami: wyobraź sobie, że możesz wstrzykiwać i filtrować funkcjonalność za pomocą specjalnej struktury zwanej aspektem, te aspekty mają „metody”, które określają, co i jak będzie miało wpływ na odbicie , ale w czasie kompilacji , proces ten nazywa się tkaniem .

Przykładem może być aspekt, który mówi „dla wszystkich metod niektórych klas, które zaczynają się od get, program zapisze w pliku dziennika dane, które zostały pobrane i czas, w którym zostały one uzyskane”.

Obejrzyj te dwa rozmowy, jeśli chcesz lepiej zrozumieć AOP:

Cechy i przeszczepy

Cechy to kolejna konstrukcja do definiowania kodu wielokrotnego użytku, który uzupełnia OOP, są one podobne do mixin , ale czystsze.

Zamiast ich wyjaśniać, istnieje świetny PHP RFC, który wyjaśnia oba . Cechy nadchodzą do PHP btw, są już one zaangażowane w trunk.

W podsumowaniu

Moim zdaniem OOP jest kluczem do modułowości i jak powszechnie wiemy dzisiaj, OOP jest wciąż niekompletny .

dukeofgaming
źródło
0

OOP Udostępnia zestaw przydatnych narzędzi, które umożliwiają pisanie kodu, którego można użyć w większej liczbie miejsc niż można bez nich. Jeśli napiszesz PrintItfunkcję, która pobiera dowolny stary obiekt i wywołuje .toString()go, ponownie użyjesz tego kodu, gdy tylko wywołasz go z więcej niż jednym typem obiektu. Dzięki tym narzędziom każdy wiersz kodu robi więcej.

Programowanie funkcjonalne jest teraz bardzo popularne wśród hipsterów. Zapewnia ci cały oddzielny zestaw narzędzi, dzięki którym każda linia kodu robi więcej. Prawdopodobnie nie jest lepszy lub działa, ale zapewnia inne narzędzie w przyborniku.

(Był szalony pomysł na cały dodatkowy poziom ponownego użycia obiektowego: Pomysł polegał na tym, że możemy zdefiniować jedną Customerklasę i używać jej w każdej napisanej przez nas aplikacji. Wtedy aplikacje byłyby tylko odrobiną kleju tu i tam. To nie działało. Ale to nie znaczy, że OO nie powiodło się, a nawet, że ponowne użycie nie powiodło się. Podstawowe typy ponownego użycia kodu w aplikacjach umożliwiły pisanie aplikacji, które zrobiły więcej, i pisanie ich szybciej).

Sean McMillan
źródło
0

Czytając powyższe posty, kilka uwag:

  • Wiele osób uważa, że ​​ponowne użycie kodu w OOP oznacza dziedziczenie. Nie zgadzam się. Interfejsy i umowy są podstawą ponownego wykorzystania kodu w systemach OOP. OOP jest szarą próbą stworzenia technologii komponentów.
  • Różnica między „frameworkami” specyficznymi dla domeny i ogólnymi jako przedmiotem ponownego użycia uważam za zbyt abstrakcyjny. Moim zdaniem element (zwięzła, minimalna umowa na interfejs wielokrotnego użytku i implementacja z tyłu) można wykonać tylko wtedy, gdy problem, który rozwiązuje, jest dobrze zrozumiany. Komponent specyficzny dla domeny, który pozwala ekspertom spoza domeny wykonywać swoją pracę z mniejszą wiedzą na temat domeny, jest (ponownie) przydatnym komponentem. Użytkownicy muszą zrozumieć interfejs, a tym bardziej zawiłości domeny problemowej.
  • Często zapominane poziomy ponownego użycia: ponowne użycie pomysłu, ponowne wykorzystanie specyfikacji, ponowne wykorzystanie architektury / projektu, ponowne użycie interfejsu, ponowne wykorzystanie przypadku testowego. Ponowne użycie kodu nie zawsze jest korzystne. Ale często oszczędzanie czasu wiąże się z konkretną architekturą w celu rozwiązania nowego, podobnego produktu.
  • Wzory projektowania OOP (Gamma i in.) W moich oczach rozwijały się raczej na taktycznych technikach implementacyjnych niż miały znaczenie w kontekście ponownego wykorzystania kodu na większą skalę. Pomagają napisać aplikację z elementami OOP, ale nie widziałbym ich jako rozwiązania pytania o ponowne użycie kodu poza jedną aplikacją.
  • Może to niesprawiedliwe: 20 lat doświadczenia w C / C ++ / C # i 6 miesięcy programowania funkcjonalnego (F #). Jednym z głównych elementów umożliwiających ponowne użycie jest: Ludzie muszą łatwo znaleźć „interfejs”, przestudiować go, zrozumieć, a następnie użyć. Czyste programowanie funkcjonalne nie ułatwia mi zobaczenia struktury, kandydatów do ponownego użycia lub miejsca, w którym wszystko się zaczyna i gdzie wszystko się kończy. Tak chwalony „cukier składniowy” często jest solą w moich oczach, uniemożliwiając mi łatwe dostrzeżenie, co się dzieje. Tak więc mniej prawdopodobne byłoby, że spróbuję ponownie użyć funkcji (co to jest - wiązka funkcji?), Która może mieć ukryte skutki uboczne, których nawet nie widzę (leniwa ocena, monady, ...). Nie zrozumcie mnie źle, programowanie funkcjonalne ma bardzo fajne strony, ale wszystkie mocne strony, które ogłosiłem, dostrzegam z dużą dozą wątpliwości.
  • Specyfikacja, projekt, wdrożenie są sprzężone, ale niełatwe do przejścia widoki na „to samo”. Znacznie bardziej istotne dla zwiększenia przyszłej produktywności niż nowy paradygmat programowania jest zmniejszenie luki, zwiększenie (automatyczne rozumowanie, identyfikowalność) wzajemnych korzyści między tymi poglądami. Sformalizowane języki specyfikacji, znormalizowane notacje testowe (np. Ttcn3) i języki programowania obsługujące weryfikację interfejsów i umów pod kątem specyfikacji bez wywoływania komentarzy mogą być tym, czego najbardziej potrzebujemy.
BitTickler
źródło
0

Problemem jest bardziej subtelne imho:

  1. OOP to świetna metoda strukturyzacji kodu ze zmiennym stanem . Poprzez enkapsulowanie stanu w obiekty, imperatywny stanowy kod staje się bardziej zrozumiały, ponieważ na przykład, jeśli fragment stanu jest wyrażony jako prywatne pole klasy, wiesz, że przynajmniej ten konkretny fragment stanu można zmodyfikować tylko metodami tego klasa. (I możesz łatwo złamać tę korzyść, nadużywając dziedziczenia, btw.) To już wystarczy, ale lepiej, żeby tego nie mieć.
  2. kod ze zmiennym stanem jest z natury trudny do ponownego użycia . Znacznie trudniejszy niż kod przy użyciu niezmiennych struktur danych.

Więc OOP sama w sobie nie jest złe z POV dokonywania kod wielokrotnego użytku , ale rodzaje kodu uzyskać napisane przy użyciu OOP są z natury trudne do ponownego użycia .

Ponadto programowanie funkcjonalne może skutkować kodem wielokrotnego użytku . Ale uzyskanie poprawności abstrakcji do napisania rozsądnego kodu funkcjonalnego podczas dotrzymywania terminu może nie być wykonalne. „Półprawidłowe” abstrakcje będą łatwiej wyrazić styl OOP. I nie będzie miało to skłonności do łatwiejszego ponownego wykorzystania kodu - wyższy poziom abstrakcji oznacza, że ​​zrozumienie kodu będzie wymagało wyższych inwestycji z uwagi na ograniczoną zdolność poznawczą programistów.

Jako praktyczny przykład: kod gry wiąże się z wieloma zmiennymi stanami, ponieważ jest to naturalny sposób myślenia o kodowaniu gry, chyba że jest to bardzo zagadkowa / algorytmiczna, więc oczywiście kończy się na strukturze OO. I oczywiście trudno jest ponownie użyć. Ale ten sam kod, zawierający tę samą wiedzę, byłby jeszcze trudniejszy do ponownego użycia bez OOP . A przepisanie go tak, aby był funkcjonalnym stylem, może wymagać całkowitej zmiany sposobu myślenia o tym kodzie i wiedzy, która się za nim kryje. Tak, wiedza wynikająca z tego kodu byłaby znacznie jaśniejsza po przepisaniu OO na FP, może ... ale koszt może być ogromny i może byćkoszty, które musieliby ponieść osoby, które chcą ponownie wykorzystać niewiarygodnie inteligentny i dobrze wyodrębniony kod, którym się ostatecznie posługujesz , więc paradoksalnie ludzie ostatecznie nie wykorzystaliby tego kodu, nawet jeśli technicznie jest to bardziej przydatne.

... co prowadzi do ostatniej subtelności: ponowne użycie kodu dotyczy interfejsu People | Code , a nie tylko kodu. OOP wykonuje przyzwoitą robotę, obsługując ten interfejs, ponieważ dobrze odwzorowuje to, ile osób myśli o wielu rodzajach pisanych obecnie kodów. FP może być lepszy do ponownego użycia kodu, ale imho nie do łatwego ponownego użycia kodu, który ludzie tak naprawdę potrzebują obecnie pisać. Zmieni się to jako rodzaj kodu, którego potrzebujemy do pisania zmian.

PS I jeśli ktoś chce powiedzieć, że „OO nie dotyczy stanu zmiennego, możesz również mieć OO ze stanem niezmiennym”… Nazywam to „FP za pomocą klas jako przestrzeni nazw”. Jest świetny, gdy działa dla Ciebie i pozwala uniknąć pewnych niedociągnięć w systemach modułów niektórych języków i może skutkować większą liczbą kodów wielokrotnego użytku. Ale to nie OO;)

Neuron Q
źródło