Czy programowanie funkcjonalne zastępuje wzorce projektowe GoF?

1047

Odkąd zacząłem uczyć się F # i OCaml w zeszłym roku, przeczytałem ogromną liczbę artykułów, które twierdzą, że wzorce projektowe (szczególnie w Javie) są obejściem brakujących funkcji w imperatywnych językach. Jeden artykuł, który znalazłem, zawiera dość silne twierdzenie :

Większość ludzi, których spotkałem, przeczytała książkę Design Patterns autorstwa Gang of Four (GoF). Każdy szanujący się programista powie ci, że książka jest niezależna od języka, a wzorce dotyczą ogólnie inżynierii oprogramowania, niezależnie od tego, jakiego języka używasz. To szlachetne roszczenie. Niestety jest to dalekie od prawdy.

Języki funkcjonalne są niezwykle ekspresyjne. W języku funkcjonalnym nie trzeba wzorców projektowych, ponieważ język jest prawdopodobnie tak wysoki, że kończy się programowanie w koncepcjach, które całkowicie eliminują wzorce projektowe.

Główne cechy programowania funkcjonalnego (FP) obejmują funkcje jako wartości pierwszej klasy, curry, wartości niezmienne itp. Nie wydaje mi się oczywiste, że wzorce projektowe OO zbliżają którąkolwiek z tych cech.

Dodatkowo w językach funkcjonalnych, które obsługują OOP (takich jak F # i OCaml), wydaje mi się oczywiste, że programiści używający tych języków używają tych samych wzorców projektowych, które są dostępne dla każdego innego języka OOP. W rzeczywistości teraz używam F # i OCaml każdego dnia i nie ma uderzających różnic między wzorami używanymi w tych językach a wzorami używanymi podczas pisania w Javie.

Czy istnieje jakaś prawda w twierdzeniu, że programowanie funkcjonalne eliminuje potrzebę wzorców projektowych OOP? Jeśli tak, to czy możesz zamieścić przykładowy typowy wzorzec projektowy OOP i jego funkcjonalny odpowiednik?

Julia
źródło
18
Możesz zajrzeć do artykułu Steve'a Yegge'a ( steve-yegge.blogspot.com/2006/03/… )
Ralph
27
„książka jest niezależna od języka, a wzorce dotyczą ogólnie inżynierii oprogramowania” - należy zauważyć, że książka nie zgadza się z tym twierdzeniem, w tym sensie, że niektóre języki nie muszą wyrażać pewnych rzeczy, takich jak wzorce projektowe: „Nasze wzorce zakładamy, że funkcje języka na poziomie Smalltalk / C ++, a wybór ten określa, co można i czego nie można łatwo wdrożyć [...] CLOS ma wiele metod, na przykład, które zmniejszają potrzebę wzorca takiego jak Visitor (Strona 331). " (strona 4)
Guildenstern
6
Należy również pamiętać, że wiele wzorców projektowych nie jest nawet potrzebnych w językach imperatywnych o wystarczająco wysokim poziomie.
R. Barzell,
3
@ R.Barzell Czym są „imperatywne języki wystarczająco wysokiego poziomu”? Dzięki.
cibercitizen1
5
@ cibercitizen1 języki kaczych typów z obsługą funkcji wyższego rzędu i funkcji anonimowych. Funkcje te zapewniają dużą moc, którą miało zapewnić wiele wzorów.
R. Barzell,

Odpowiedzi:

1076

Cytowany post na blogu jest nieco zawyżony. FP nie eliminuje potrzeby tworzenia wzorów. Termin „wzorce projektowe” po prostu nie jest powszechnie używany do opisania tego samego w językach FP. Ale istnieją. Języki funkcjonalne mają wiele zasad najlepszych praktyk w formie „gdy napotkasz problem X, użyj kodu, który wygląda jak Y”, co jest w zasadzie wzorcem projektowym.

Prawdą jest jednak, że większość wzorców projektowych specyficznych dla OOP jest praktycznie nieistotna w językach funkcjonalnych.

Nie sądzę, że powinno to być szczególnie kontrowersyjna powiedzieć, że wzorce projektowe w ogóle istnieć tylko załatać braki w języku. A jeśli inny język może rozwiązać ten sam problem w sposób trywialny, ten inny język nie będzie potrzebował wzorca projektowego. Użytkownicy tego języka mogą nawet nie zdawać sobie sprawy, że problem istnieje , ponieważ cóż, w tym języku nie jest to problem.

Oto, co Gang of Four ma do powiedzenia na ten temat:

Wybór języka programowania jest ważny, ponieważ wpływa na własny punkt widzenia. Nasze wzorce zakładają funkcje języka na poziomie Smalltalk / C ++, a wybór ten określa, co można, a czego nie można łatwo wdrożyć. Gdybyśmy przyjęli języki proceduralne, moglibyśmy uwzględnić wzorce projektowe zwane „Dziedziczeniem”, „Enkapsulacją” i „Polimorfizmem”. Podobnie, niektóre z naszych wzorców są obsługiwane bezpośrednio przez mniej popularne języki obiektowe. CLOS ma na przykład wiele metod, które zmniejszają potrzebę wzorca, takiego jak Visitor. W rzeczywistości istnieje wystarczająca różnica między Smalltalk i C ++, aby oznaczać, że niektóre wzorce można wyrazić łatwiej w jednym języku niż w drugim. (Zobacz na przykład Iterator.)

(Powyższy cytat z książki Wprowadzenie do wzorców projektowych, strona 4, akapit 3)

Główne cechy programowania funkcjonalnego obejmują funkcje jako wartości pierwszej klasy, curry, niezmienne wartości itp. Nie wydaje mi się oczywiste, że wzorce projektowe OO zbliżają którąkolwiek z tych cech.

Jaki jest wzorzec poleceń, jeśli nie przybliżenie funkcji pierwszej klasy? :) W języku FP wystarczy przekazać funkcję jako argument do innej funkcji. W języku OOP musisz zawinąć funkcję w klasę, którą możesz utworzyć, a następnie przekazać ten obiekt do innej funkcji. Efekt jest taki sam, ale w OOP nazywa się to wzorcem projektowym i zajmuje o wiele więcej kodu. A jaki jest abstrakcyjny wzór fabryki, jeśli nie curry? Przekaż parametry do funkcji po trochu, aby skonfigurować, jaka wartość będzie wyrzucana, gdy w końcu ją wywołasz.

Tak więc, kilka wzorców projektowych GoF jest nadmiarowych w językach FP, ponieważ istnieją bardziej wydajne i łatwiejsze w użyciu alternatywy.

Ale oczywiście nadal istnieją wzorce projektowe, których nie rozwiązują języki FP. Jaka jest równowartość FP singletona? (Pomijając przez chwilę to, że singletony są na ogół okropnym wzorem do użycia.)

I działa to w obie strony. Jak powiedziałem, FP ma również swoje wzorce projektowe; ludzie zwykle nie myślą o nich jako o takich.

Być może natknąłeś się na monady. Co to jest, jeśli nie wzór do „radzenia sobie ze stanem globalnym”? Jest to problem tak prosty w językach OOP, że nie istnieje tam równoważny wzorzec projektowy.

Nie potrzebujemy wzorca projektowego do „zwiększania zmiennej statycznej” lub „odczytu z tego gniazda”, ponieważ jest to tylko to, co robisz .

Mówienie, że monada jest wzorcem projektowym, jest równie absurdalne, jak twierdzenie, że liczby całkowite z ich zwykłymi operacjami, a element zerowy jest wzorcem projektowym. Nie, monada to wzór matematyczny , a nie wzór projektowy.

W (czystych) językach funkcjonalnych efekty uboczne i stan mutable są niemożliwe, chyba że obejdziesz je z monadowym „wzorcem projektowym” lub innymi metodami pozwalającymi na to samo.

Ponadto w językach funkcjonalnych, które obsługują OOP (takich jak F # i OCaml), wydaje mi się oczywiste, że programiści używający tych języków używają tych samych wzorców projektowych, które są dostępne dla każdego innego języka OOP. W rzeczywistości teraz używam F # i OCaml codziennie i nie ma uderzających różnic między wzorami używanymi w tych językach a wzorami używanymi podczas pisania w Javie.

Może dlatego, że nadal myślisz imperatywnie? Wiele osób, które przez całe życie miały do ​​czynienia z imperatywnymi językami, z trudem rezygnuje z tego nawyku, próbując języka funkcjonalnego. (Widziałem kilka dość zabawnych prób na F #, gdzie dosłownie każda funkcja była tylko ciągiem instrukcji „let”, zasadniczo tak, jakbyś wziął program C i zastąpił wszystkie średniki słowem „let”. :))

Ale inną możliwością może być to, że po prostu nie zdajesz sobie sprawy, że rozwiązujesz problemy w sposób trywialny, które wymagałyby wzorców projektowych w języku OOP.

Kiedy używasz curry lub przekazujesz funkcję jako argument innemu, zatrzymaj się i pomyśl o tym, jak zrobiłbyś to w języku OOP.

Czy istnieje jakaś prawda w twierdzeniu, że programowanie funkcjonalne eliminuje potrzebę wzorców projektowych OOP?

Tak. :) Kiedy pracujesz w języku FP, nie potrzebujesz już wzorów projektowania specyficznych dla OOP. Nadal jednak potrzebujesz ogólnych wzorców projektowych, takich jak MVC lub inne rzeczy niezwiązane z OOP, a zamiast tego potrzebujesz kilku nowych „wzorców projektowych” specyficznych dla FP. Wszystkie języki mają swoje wady, a wzorce projektowe są zwykle takie, jak je omawiamy.

W każdym razie może być interesujące wypróbowanie swoich „czystszych” języków FP, takich jak ML (mój osobisty ulubiony, przynajmniej do celów edukacyjnych) lub Haskell , gdzie nie masz kuli OOP, na której można polegać , gdy napotyka coś nowego.


Zgodnie z oczekiwaniami kilka osób sprzeciwiło się mojej definicji wzorców projektowych jako „łatanie niedociągnięć w języku”, więc oto moje uzasadnienie:

Jak już powiedziano, większość wzorców projektowych jest charakterystyczna dla jednego paradygmatu programowania, a czasem nawet jednego określonego języka. Często rozwiązują problemy, które istnieją tylko w tym paradygmacie (patrz monady dla FP lub abstrakcyjne fabryki dla OOP).

Dlaczego abstrakcyjny wzór fabryczny nie istnieje w FP? Ponieważ problem, który próbuje rozwiązać, nie istnieje.

Tak więc, jeśli istnieje problem w językach OOP, który nie występuje w językach FP, to oczywiście jest to wada języków OOP. Problem można rozwiązać, ale twój język tego nie robi, ale wymaga od ciebie garstki kodu do obejścia. Idealnie byłoby, gdyby nasz język programowania w magiczny sposób rozwiązał wszystkie problemy. Jakikolwiek problem, który nadal występuje, jest w zasadzie wadą języka. ;)

jalf
źródło
73
Wzorce projektowe opisują ogólne rozwiązania podstawowych problemów. Ale to samo robią języki programowania i platformy. Dlatego używasz wzorców projektowych, gdy używane języki i platformy nie są wystarczające.
yfeldblum
135
S.Lott: Tak, opisują rozwiązania problemów występujących w danym języku. Nie ma wzorca projektowania poleceń w językach FP, ponieważ problem, który próbuje rozwiązać, nie istnieje. Co oznacza, że ​​rozwiązują problemy, których sam język nie jest w stanie rozwiązać. Oznacza to, że braki w języku
jalf
38
Monada jest pojęciem matematycznym i rozciągasz ją swoją klasyfikacją. Jasne, możesz postrzegać funkcje, monoidy, monady, macierze lub inne pojęcia matematyczne jako wzorce projektowe, ale są one bardziej podobne do algorytmów i struktur danych ... podstawowe pojęcia, niezależne od języka.
Alexandru Nedelcu
41
Jasne, monady są pojęciem matematycznym, ale są też wzorem. „Wzór FP” monad różni się nieco od matematycznej koncepcji monad. Pierwszy z nich to wzorzec używany do obejścia pewnych „ograniczeń” w czystych językach FP. Ta ostatnia jest uniwersalną koncepcją matematyczną.
czerwca
69
Zauważ, że monady w Haskell są używane do innych celów niż stan zmienny, na przykład do wyjątków, kontynuacji, list, zrozumienia, parsowania, programowania asynchronicznego i tak dalej. Ale wszystkie te zastosowania monad można prawdopodobnie nazwać wzorami.
JacquesB
152

Czy istnieje jakaś prawda w twierdzeniu, że programowanie funkcjonalne eliminuje potrzebę wzorców projektowych OOP?

Programowanie funkcjonalne to nie to samo, co programowanie obiektowe. Obiektowe wzorce projektowe nie dotyczą programowania funkcjonalnego. Zamiast tego masz funkcjonalne wzorce projektowe programowania.

Do programowania funkcjonalnego nie będziesz czytać wzorców projektowych OO; przeczytasz inne książki o wzorach projektowych FP.

język agnostyczny

Nie całkiem. Jedynie niezależny od języka w odniesieniu do języków OO. Wzory projektowe w ogóle nie dotyczą języków proceduralnych. Nie mają one sensu w kontekście projektowania relacyjnych baz danych. Nie mają zastosowania przy projektowaniu arkusza kalkulacyjnego.

typowy wzór projektowy OOP i jego funkcjonalny odpowiednik?

Powyższe nie powinno istnieć. To tak, jakby poprosić o kawałek kodu proceduralnego przepisanego jako kod OO. Ummm ... Jeśli przetłumaczę oryginalny Fortran (lub C) na Javę, nie zrobiłem nic poza tłumaczeniem. Jeśli całkowicie przepisam go na paradygmat OO, nie będzie już wyglądał jak oryginalny Fortran lub C - będzie nierozpoznawalny.

Nie ma prostego mapowania od projektu OO do projektu funkcjonalnego. Są bardzo różne sposoby patrzenia na problem.

Programowanie funkcjonalne (jak wszystkie style programowania) ma wzorce projektowe. Relacyjne bazy danych mają wzorce projektowe, OO ma wzorce projektowe, a programowanie proceduralne ma wzorce projektowe. Wszystko ma wzory, nawet architekturę budynków.

Wzory projektowe - jako koncepcja - to ponadczasowy sposób budowania, niezależnie od technologii czy dziedziny problemowej. Jednak określone wzorce projektowe dotyczą określonych domen i technologii problemowych.

Każdy, kto myśli o tym, co robi, odkryje wzorce projektowe.

S.Lott
źródło
12
MVC nie jest projektem OO. To projekt architektoniczny - ten wzór stosuje się dość szeroko.
S.Lott,
1
@Princess: programowanie funkcjonalne niekoniecznie jest prostsze. W twoim przykładzie tak. W przypadku innych rzeczy jury wciąż nie istnieje. Ale odrzuciłeś wzór projektowy Java OO i przyjąłeś wzór projektowy FP.
S.Lott
1
+1: Wolę tę odpowiedź od powyższej odpowiedzi Jalfa. Chociaż niektóre wzorce projektowe usuwają braki w języku, nie wszystkie to robią. Na przykład, nie powiedziałbym, że wzorzec projektowy „odwiązanie węzła rekurencyjnego” rozwiązuje problem braku języka, jest to po prostu użyteczny idiom do rozluźnienia zależności.
Jon Harrop,
9
Java 8 będzie zawierać zamknięcia, czyli anonimowe funkcje, takie jak wyrażenia lambda. Spowoduje to, że wzorzec projektowania poleceń stanie się przestarzały dla Java. To jest przykład niedociągnięć językowych, prawda? Dodali brakującą funkcję, a teraz nie potrzebujesz wzoru.
Todd Chaffee
2
+1 za zdanie końcowe. Wzorce projektowe mają uprościć programowanie i zwiększyć wydajność powstałych programów, zgodnie z ich przeznaczeniem.
Sorter
46

Komentarze Briana na temat ścisłego powiązania języka z wzorcem są takie, że

Brakującą częścią tej dyskusji jest koncepcja idiomu. Ogromny wpływ miała tu książka Jamesa O. Coplien'a „Advanced C ++”. Na długo przed odkryciem Christophera Alexandra i kolumny bez imienia (i nie można też rozsądnie mówić o wzorach bez czytania Aleksandra), mówił o znaczeniu opanowania idiomów w prawdziwej nauce języka. Jako przykład posłużył się tekstem w C, while(*from++ = *to++);możesz to zobaczyć jako bandaid dla brakującego języka (lub biblioteki), ale tak naprawdę liczy się to, że jest to większa jednostka myśli lub wyrażenia niż jakakolwiek jego części.

Właśnie takie wzorce i języki starają się zrobić, abyśmy mogli bardziej zwięźle wyrazić nasze intencje. Im bogatsze jednostki myśli, tym bardziej złożone myśli możesz wyrazić. Posiadanie bogatego, wspólnego słownictwa w różnych skalach - od architektury systemu po kręcenie się - pozwala nam na bardziej inteligentne rozmowy i przemyślenia na temat tego, co powinniśmy robić.

Możemy również, jako jednostki, uczyć się. Co jest celem całego ćwiczenia. Każdy z nas może zrozumieć i korzystać z rzeczy, o których nigdy nie moglibyśmy myśleć o sobie. Języki, frameworki, biblioteki, wzorce, idiomy itd. Mają swoje miejsce w dzieleniu się bogactwem intelektualnym.

Peter Mortensen
źródło
8
Dziękuję Ci! o to właśnie chodzi w wzorach - „dzieleniu pojęć” w celu zmniejszenia obciążenia poznawczego.
Randall Schulz
Funkcjonalne i Monady zdecydowanie należy do tej dyskusji.
Greg
@RandallSchulz: cechy języka (i oczywiście ich idiomatyczne użycie) również dobrze pasowałyby do kategorii „fragmentacji pojęciowej w celu zmniejszenia obciążenia poznawczego”.
Roy Tinker,
39

Książka GoF wyraźnie wiąże się z OOP - tytuł to Design Patterns - Elements of Wielorazowe oprogramowanie obiektowe (moje wyróżnienie ).

jasny
źródło
26

Oto kolejny link omawiający ten temat: http://blog.ezyang.com/2010/05/design-patterns-in-haskel/

W swoim blogu Edward opisuje wszystkie 23 oryginalne wzorce GoF w kategoriach Haskell.

folone
źródło
4
Artykuł nie wydaje się tak naprawdę pokazywać wzorów projektowych w Haskell, ale pokazuje, w jaki sposób Haskell zaspokaja te potrzeby bez wspomnianych wzorów.
Fresheyeball
3
@Fresheyball: Zależy od twojej definicji wzorów. Czy mapowanie funkcji na liście jest wariantem wzorca użytkownika? Generalnie myślałem, że odpowiedź brzmi „tak”. Wzorce powinny wykraczać poza określoną składnię. Zastosowana funkcja może być zawinięta jako obiekt lub przekazana jako wskaźnik funkcji, ale dla mnie koncepcja jest taka sama. Nie zgadzasz się
srm
20

Kiedy spróbujesz spojrzeć na to na poziomie „wzorców projektowych” (ogólnie) i „FP kontra OOP”, odpowiedzi, które znajdziesz, będą co najwyżej mroczne.

Przejdź jednak poziom głębiej na obu osiach i zastanów się nad konkretnymi wzorami projektowymi i specyficznymi cechami językowymi, a rzeczy staną się wyraźniejsze.

Na przykład niektóre określone wzorce, takie jak Odwiedzający , Strategia , Polecenie i Obserwator zdecydowanie zmieniają się lub znikają podczas używania języka z algebraicznymi typami danych i dopasowaniem wzorców , zamknięciami , funkcjami pierwszej klasy itp. Niektóre inne wzorce z książki GoF wciąż „trzymać się”.

Ogólnie rzecz biorąc, powiedziałbym, że z czasem określone wzorce są eliminowane przez nowe (lub po prostu rosnące w popularności) funkcje językowe. To naturalny kurs projektowania języka; gdy języki stają się coraz bardziej zaawansowane, abstrakcje, które wcześniej można było wywołać tylko w książce na przykładach, teraz stają się aplikacjami określonej funkcji językowej lub biblioteki.

(Na bok: oto niedawno napisany blog , który zawiera inne linki do dalszych dyskusji na temat FP i wzorców projektowych.)

Brian
źródło
Jak możesz powiedzieć, że wzór „znika”? Czy nie zmienia się to po prostu z „Utwórz interfejs użytkownika za pomocą kilku metod odwiedzin” w „używaj typów unii i dopasowywania wzorców”?
Gabe,
22
Tak, ale zmieniło się to ze wzoru, który jest pomysłem projektowym, o którym czytasz w książce i stosuje się do twojego kodu, na „tylko kod”. Czyli „typy wykorzystanie unijnych i pasujące do wzorca” jest po prostu jak zwykle rzeczy kod w takim języku. (Analogia: jeśli żaden język nie ma forpętli, a wszystkie mają po prostu whilepętle, wówczas „For” może być wzorem iteracji. Ale kiedy forjest to konstrukcja obsługiwana przez język i sposób, w jaki ludzie normalnie kodują, to nie jest to wzorzec - nie nie potrzebuje wzorca, to tylko kod, człowieku.)
Brian
4
Innymi słowy, być może niezłym testem lakmusowym dla „czy to wzór” jest: obecny kod napisany w ten sposób studentowi drugiego roku na kierunku CS z rocznym doświadczeniem w programowaniu w Twoim języku. Jeśli pokażesz im kod, a oni mówią „to sprytny projekt”, to jest to wzór. Jeśli pokażesz im kod, a oni idą „no cóż, duh!”, To nie jest to wzór. (A jeśli pokażesz tego „gościa” każdemu, kto zrobił ML / F # / Haskell przez rok, pójdą „dobrze, duh!”)
Brian
1
Brian: Myślę, że mamy po prostu różne definicje „wzorca”. Uważam, że każda możliwa do zidentyfikowania abstrakcja projektu jest wzorem , podczas gdy ty bierzesz pod uwagę tylko nieoczywiste abstrakcje jako wzór . Tylko dlatego, że C # ma, foreacha Haskell mapMnie oznacza, że ​​nie mają wzorca iteratora. Nie widzę problemu z powiedzeniem, że wzorzec Iteratora jest zaimplementowany jako ogólny interfejs IEnumerable<T>w C # i krój pisma Traversablew Haskell.
Gabe
Być może nieoczywiste wzorce są przydatne dla inżynierów oprogramowania, ale wszystkie wzorce są przydatne dla projektantów języków. Tj. „Jeśli tworzysz nowy język, pamiętaj o podaniu czystego sposobu wyrażania wzorca iteratora”. Nawet oczywiste wzorce są interesujące, gdy zaczynamy zadawać pytanie: „Czy istnieje lepsza składnia do wyrażania tego pomysłu?” W końcu to właśnie prowadzi kogoś do tworzenia foreach.
srm
16

Prezentacja Norviga nawiązuje do dokonanej przez nich analizy wszystkich wzorców GoF i mówią, że 16 z 23 wzorców miało prostsze implementacje w językach funkcjonalnych lub po prostu było częścią tego języka. Prawdopodobnie co najmniej siedem z nich było a) równie skomplikowanych lub b) nieobecnych w języku. Niestety dla nas nie są one wymienione!

Myślę, że jest jasne, że większość wzorców „kreacyjnych” lub „strukturalnych” w GoF to tylko sztuczki, aby zmusić prymitywne systemy typów w Javie lub C ++ do robienia tego, co chcesz. Ale reszta jest warta rozważenia bez względu na język, w którym programujesz.

Jednym może być Prototyp; Chociaż jest to podstawowe pojęcie JavaScript, musi być zaimplementowane od podstaw w innych językach.

Jednym z moich ulubionych wzorów jest wzorzec Null Object: reprezentuje brak czegoś jako obiektu, który nie robi odpowiedniego rodzaju niczego. To może być łatwiejsze do modelowania w funkcjonalnym języku. Jednak prawdziwym osiągnięciem jest zmiana perspektywy.

Peter Mortensen
źródło
2
Co za dziwna analiza, odkąd wzorce GoF zostały specjalnie zaprojektowane dla klasowych języków OOP. To trochę jak analiza, czy klucze do rur nadają się do wykonywania prac elektrycznych.
hojny
@munificent: Niezupełnie. Orientacja obiektowa zapewnia polimorfizm; programowanie funkcjonalne zasadniczo zapewnia polimorfizm.
Marcin
@Marcin programista OO oznacza coś zupełnie innego przez polimorfizm niż programista funkcjonalny.
AndrewC
@AndrewC Nie zgadzam się. Programista OO może myśleć, że mają na myśli coś innego, ale tak nie jest.
Marcin
3
@Marcin Z mojego doświadczenia wynika, że ​​programista OO zazwyczaj odnosi się do polimorfizmu podtypu (często po prostu za pomocą Object), wykorzystując rzutowania do jego osiągnięcia lub polimorfizmu ad-hoc (przeciążenie itp.). Kiedy funkcjonalny programista mówi o polimorfizmie, ma na myśli polimorfizm parametryczny (tj. Działa dla dowolnego rodzaju danych - Int, funkcji, listy), co być może bardziej przypomina ogólne programowanie OO, niż jest czymś, co programiści OO zwykle nazywają polimorfizmem.
AndrewC
15

Powiedziałbym, że jeśli masz język taki jak Lisp z obsługą makr, możesz zbudować własne abstrakcje specyficzne dla domeny, abstrakcje, które często są znacznie lepsze niż ogólne rozwiązania idiomowe.

Anders Rune Jensen
źródło
Jestem całkowicie zagubiony. Wzmocnić coś abstrakcjami ... Co to znaczy?
tuinstoel
2
Możesz budować abstrakcje specyficzne dla domeny (nawet te osadzone) bez makr. Makra pozwalają tylko je upiększyć, dodając niestandardową składnię.
Jon Harrop,
2
Możesz myśleć o Lisp jako zestawie Legos do budowania języków programowania - jest to język, ale jest to również język metalowy. Co oznacza, że ​​dla każdej problematycznej domeny możesz zaprojektować język, który nie ma żadnych oczywistych braków. Będzie to wymagało wprawy, a Kurt Gödel może się nie zgodzić, ale warto spędzić trochę czasu z Lispem, aby zobaczyć, co przynosi na stół (podpowiedź, makra).
Greg
9

I nawet rozwiązania wzorców projektowych OO są specyficzne dla języka.

Wzorce projektowe są rozwiązaniem typowych problemów, których Twój język programowania nie rozwiązuje dla Ciebie. W Javie wzorzec Singleton rozwiązuje problem jednego (uproszczonego).

W Scali masz konstrukcję najwyższego poziomu o nazwie Object oprócz Class. Jest on leniwie utworzony i jest tylko jeden. Nie musisz używać wzoru Singleton, aby otrzymać Singleton. To część języka.

Peter Mortensen
źródło
8

Wzorce są sposobami rozwiązywania podobnych problemów, które pojawiają się wielokrotnie, a następnie są opisywane i dokumentowane. Więc nie, FP nie zastąpi wzorów; FP mogą jednak tworzyć nowe wzorce i sprawić, że niektóre obecne wzorce „najlepszych praktyk” staną się „przestarzałe”.

Edwin Buck
źródło
4
Wzorce GoP są sposobami rozwiązania problemu ograniczeń określonego typu języka programowania. Na przykład „Chcę pośrednio na zajęciach i kazać im tworzyć obiekty” -> „Nie możesz, ale możesz tworzyć obiekty podobne do metaklasy zwane fabrykami”. „Chcę wielokrotnej wysyłki” -> „Nie możesz, ale istnieje labirynt, który możesz zaimplementować, zwany Wzorem Odwiedzającego”. Itd. Żaden ze wzorów nie ma sensu, jeśli nie jesteś w języku OOP z konkretnymi ograniczeniami.
Kaz
1
Nie wiem, czy „żaden” z nich nie ma sensu w innych językach, ale zgodzę się, że wiele z nich nie ma sensu w innych językach. Adapter i Bridge wydają się mieć więcej możliwości wielojęzycznych, zmniejszając nieco dla odwiedzających, a może nieco mniej dla słuchaczy. Jednak wzorce między językami zawsze będą cierpieć z powodu tego, jak „operować językiem X w języku Y”, wspierając naturalne granice języka. Doskonałym przykładem był wzór Singleton, czyli w zasadzie, jak uzyskać globały C w OOP? (na co odpowiem, nie powinieneś).
Edwin Buck,
1
Drugi Kaz: Wzorzec nie jest „sposobem rozwiązywania podobnych problemów, które pojawiają się od nowa”, ale „sposobem rozwiązywania podobnych problemów, które pojawiają się od nowa i ORAZ trzeba je przepisywać wielokrotnie, ponieważ język nie pozwala napisz to tylko raz ". Innymi słowy, jeśli język umożliwił wyodrębnienie / wyodrębnienie wzorca w bibliotece / klasie / module itp., Przestaje on być wzorcem, ale staje się biblioteką / klasą / modułem. W FP o wiele łatwiej jest wyodrębnić / wyodrębnić nieco kodu do funkcji, dlatego też „wzorzec” jest łatwiej przekształcany w kod wielokrotnego użytku, dzięki czemu nie są wzorem.
mb14
1
Twoja interpretacja jest mile widziana, ale książka GoF była jasna, aby zdefiniować wzór, a jeśli czytasz rozdziały wprowadzające, nie mówi nic o językach ani słabościach języka. Z pewnością niektóre języki mają obszary, które sprawią, że będą częściej wykorzystywać niektóre wzorce, ale czy napiszesz go dziesięć razy (wytnij i wklej), czy zaimplementujesz raz z dziesięcioma realizacjami (podklasowanie), czy też masz strukturę skonfigurowaną tak, aby zrobić to dziesięć nieco na różne sposoby, jest tylko szczegół implementacji odsłoniętego wzorca.
Edwin Buck
1
Wracając do tej rozmowy po latach, myślę, że wiele osób kojarzy Patterns z konkretnym językiem programowania lub określonym paradygmatem programowania. Można ich używać w takim kontekście, ale istniały one przed programowaniem. „Ponadczasowy sposób budowania” omawia wzorce architektury budowlanej i planowania społeczności. Oznacza to, że techniki zorientowane na wzorzec mogą być używane poza „ograniczeniami języka”, chyba że chcesz nazwać budowanie językiem programowania :)
Edwin Buck
8

Jak powiedzieli inni, istnieją wzorce specyficzne dla programowania funkcjonalnego. Myślę, że kwestia pozbycia się wzorców projektowych to nie tyle kwestia przejścia na funkcjonalność, co kwestia cech językowych .

Spójrz, jak Scala eliminuje „wzorzec singletonu”: po prostu deklarujesz obiekt zamiast klasy. Kolejna funkcja, dopasowywanie wzorów, pomaga uniknąć niezręczności wzoru odwiedzającego. Zobacz porównanie tutaj: Scala's Pattern Matching = wzór gościa na sterydach

A Scala, podobnie jak F #, jest połączeniem funkcji OO. Nie wiem o F #, ale prawdopodobnie ma tego rodzaju funkcje.

Zamknięcia są obecne w języku funkcjonalnym, ale nie muszą być do nich ograniczone. Pomagają we wzorcu delegowania.

Jeszcze jedna obserwacja. Ten fragment kodu implementuje wzorzec: jest tak klasyczny i tak elementarny, że zwykle nie uważamy go za „wzorzec”, ale z pewnością jest to:

for(int i = 0; i < myList.size(); i++) { doWhatever(myList.get(i)); }

Języki imperatywne, takie jak Java i C #, przyjęły coś, co jest zasadniczo funkcjonalnym konstruktem, aby sobie z tym poradzić: „foreach”.

Niemiecki
źródło
Powiedziałbym, że Scala obejmuje pierwszorzędne wsparcie dla wzorca singletonu. Wzorzec nadal tam jest, ale kod szablonu niezbędny do zastosowania wzorca jest znacznie zmniejszony w porównaniu z Javą.
JacquesB
Jeśli opinie byłyby jak *******, cóż ... Spójrz na resztę odpowiedzi. „po prostu deklarujesz obiekt zamiast klasy” jest tak prawdziwe, nazwałbym to jednak dosłownie obiektem (tj. var singleton = {};). Podoba mi się również wzmianka o wzorze foreach. Niestety wygląda na to, że większość osób, które odpowiedziały / skomentowały to pytanie, nie rozumie programowania funkcjonalnego i wolałaby uzasadnić stosowanie wzorców projektowych OOP. +1 za podanie konkretnych przykładów, gdybym mógł, dałbym więcej.
Evan Plaice,
@JacquesB Nie mogę komentować Scali / Haskell, ale w JavaScript (tj. Hybrydowy funkcjonalny / imperatywny) absolutnie nie ma podstawki, po prostu dostosowujesz sposób deklarowania obiektów za pomocą kombinacji składni literału obiektu, funkcji anonimowych, przekazywania funkcji jako pierwszych członków klasy i zezwalając na wielokrotne dziedziczenie (eliminując potrzebę umów interfejsu).
Evan Plaice,
8

Wzory projektowe GoF kodują obejścia przepisów dla języków OO, które są potomkami Simula 67 , takich jak Java i C ++.

Większość „dolegliwości” leczonych przez wzorce projektowe jest spowodowana:

  • klasy o typie statycznym, które określają obiekty, ale same nie są obiektami;
  • ograniczenie do pojedynczej wysyłki (tylko lewy argument jest używany do wyboru metody, pozostałe argumenty są traktowane tylko jako typy statyczne: jeśli mają typy dynamiczne, to metoda może rozwiązać to z zastosowaniem metod ad-hoc);
  • rozróżnienie między zwykłymi wywołaniami funkcji a obiektowymi wywołaniami funkcji, co oznacza, że ​​funkcji zorientowanych obiektowo nie można przekazywać jako argumentów funkcjonalnych, w których spodziewane są funkcje regularne i odwrotnie; i
  • rozróżnienie między „typami podstawowymi” i „typami klas”.

Nie ma jednego z tych wzorców projektowych, który nie zniknie we wspólnym systemie obiektowym Lisp, nawet jeśli rozwiązanie jest zbudowane zasadniczo w taki sam sposób, jak w odpowiednim wzorcu projektowym. (Co więcej, ten system obiektowy poprzedza książkę GoF znacznie ponad dekadę. Common Lisp stał się standardem ANSI w tym samym roku, w którym po raz pierwszy opublikowano tę książkę.)

Jeśli chodzi o programowanie funkcjonalne, to czy wzorce mają do niego zastosowanie, zależy od tego, czy dany funkcjonalny język programowania ma jakiś system obiektowy i czy jest modelowany na podstawie systemów obiektowych, które korzystają z wzorców. Tego rodzaju orientacja obiektowa nie łączy się dobrze z programowaniem funkcjonalnym, ponieważ mutacja stanu znajduje się z przodu i na środku.

Konstrukcja i niezmutowany dostęp są kompatybilne z programowaniem funkcjonalnym, więc mogą mieć zastosowanie wzorce, które mają związek z dostępem abstrakcyjnym lub konstrukcją: wzorce takie jak Fabryka, Fasada, Serwer proxy, Dekorator i Gość.

Z drugiej strony wzorce behawioralne, takie jak stan i strategia, prawdopodobnie nie mają bezpośredniego zastosowania w funkcjonalnym OOP, ponieważ mutacja stanu leży u ich podstaw. To nie znaczy, że nie mają zastosowania; być może w jakiś sposób mają zastosowanie w połączeniu z wszelkimi dostępnymi sztuczkami do symulacji stanu zmiennego.

Kaz
źródło
2
„Wzorce projektowe GoF kodują przepisy dotyczące obejścia” to po prostu fałszywe stwierdzenie.
John Peters,
7

Chciałbym podłączyć kilka doskonałych, ale nieco gęstych dokumentów Jeremy'ego Gibbonsa: „Projektuj wzorce jako programy generyczne dla typów danych wyższego rzędu” i „Istota wzorca Iterator” (oba dostępne tutaj: http: // www. comlab.ox.ac.uk/jeremy.gibbons/publications/ ).

Oba opisują, w jaki sposób idiomatyczne konstrukcje funkcjonalne pokrywają teren objęty określonymi wzorami projektowymi w innych (obiektowych) ustawieniach.

sclv
źródło
6

Nie można prowadzić tej dyskusji bez wywoływania systemów typów.

Główne cechy programowania funkcjonalnego obejmują funkcje jako wartości pierwszej klasy, curry, niezmienne wartości itp. Nie wydaje mi się oczywiste, że wzorce projektowe OO zbliżają którąkolwiek z tych cech.

To dlatego, że te funkcje nie dotyczą tych samych problemów, co OOP ... są alternatywą dla programowania imperatywnego. Odpowiedź FP na OOP leży w systemach typów ML i Haskell ... w szczególności typów sum, abstrakcyjnych typów danych, modułów ML i klas Haskell.

Ale oczywiście nadal istnieją wzorce projektowe, których nie rozwiązują języki FP. Jaka jest równowartość FP singletona? (Pomijając przez chwilę, że singletony są na ogół okropnym wzorem do użycia)

Pierwszą rzeczą, jaką robią typy, jest wyeliminowanie potrzeby singletonów.

Możesz przejrzeć listę 23 i wyeliminować więcej, ale nie mam teraz na to czasu.

Jason Ganetsky
źródło
6
W jaki sposób klasy znaków (odpowiednik interfejsów OOP dla FP) eliminują potrzebę singletonów (odpowiednik stanu globalnego FP)?
Gabe,
4

Myślę, że tylko dwa wzorce projektowe GoF zostały zaprojektowane w celu wprowadzenia logiki programowania funkcjonalnego do naturalnego języka OO. Myślę o strategii i dowodzeniu. Niektóre inne wzorce projektowe GoF można modyfikować za pomocą programowania funkcjonalnego, aby uprościć projekt i zachować cel.

CyaNnOrangeHead
źródło
4
Chodzi o to, że głównym celem wielu wzorców jest wykorzystanie polimorfizmu do robienia rzeczy, na które przyzwoite wsparcie dla koncepcji FP mogłoby automatycznie pozwolić. (Większość inkarnacji, które widziałem na przykład w Builderze, to po prostu pół-osaczone curry.) Gdy możesz łatwo traktować funkcje jako wartości, wzorce często upraszczają się do tego stopnia, że ​​są trywialne. Stają się one „przekazać callback” lub „mają słownik callbacków” - na przykład różne klasy konstruktorów mogą prawie zniknąć. IMO wzorzec przestaje być wzorzec, gdy jest wystarczająco trywialny, aby być po prostu sposobem działania , a nie czymś, co trzeba wdrożyć.
cHao
3

Programowanie funkcjonalne nie zastępuje wzorców projektowych. Wzorów projektowych nie można zastąpić.

Wzory po prostu istnieją; pojawiły się z czasem. Książka GoF sformalizowała niektóre z nich. Jeśli pojawią się nowe wzorce, gdy programiści używają funkcjonalnych języków programowania, to jest ekscytujące rzeczy i być może zostaną też napisane o nich książki.

kingle
źródło
1
Wzorów projektowych nie można zastąpić? Myślę, że to trochę zamknięte. Prawdopodobnie wszyscy możemy się zgodzić, że wzorce projektowe mają na celu rozwiązanie problemów programistycznych, a przynajmniej chciałbym mieć nadzieję, że pewnego dnia rozwiążemy te problemy bez wzorców projektowych.
Metropolis
3
Każdy konkretny wzór może być wymienny, ale koncepcja wzorów nie może. Pamiętaj, że termin „wzór” pojawił się w dziedzinie architektury .
Frank Shearar
1
Wzorce nie mają na celu rozwiązywania problemów programistycznych. Wzory to sposoby programowania. Dokumentacja wzorów ma pomóc w rozwiązywaniu problemów programistycznych.
Torbjørn
3
@ Torbjørn: Wzory to sposoby, w jakie programujemy, gdy przeszkadza nam język . Istnieją one z powodu pewnego niedopasowania między pożądanym zachowaniem programu a wbudowanymi możliwościami języka, gdzie wymagania i umiejętności nie są dobrze odwzorowane lub niejednoznaczne. Gdyby nie to, nie byłoby wzoru; miałbyś jedną implementację, która dokładnie tak się robi , a inne implementacje nie byłyby warte rozważenia.
cHao
1
Tyle że wzorce naprawdę istnieją tylko po to, aby ułatwić komunikację. Nie ma innego celu. We wszystkich spotkaniach projektowych, w których uczestniczyłem przez lata, ważna była dyskusja na temat algorytmu , a nie wzorzec. Wzór rzadko tłumaczył, co naprawdę dzieje się w jakimkolwiek sensownym sensie. Czy wyjaśnia dokładnie wpływ O (n) na O (n Log (n))? Nie. Czy to wyjaśnia, jak łatwo będzie pasować do istniejącej architektury? Nie. Dyskusje na temat algorytmów na pełną skalę. Nie twierdzę, że wzory powinny być same w sobie wycofane, ale gdyby tak było, prawie nic by nie ucierpiało.
3

W nowej książce z 2013 roku zatytułowanej „Functional Programming Patterns- in Scala and Clojure” autor Michael.B. Linn wykonuje przyzwoitą pracę, porównując i zastępując w wielu przypadkach wzorce GoF, a także omawia nowsze wzorce funkcjonalne, takie jak „rekurencja ogona”, „zapamiętywanie”, „leniwa sekwencja” itp.

Ta książka jest dostępna na Amazon. Uznałem, że jest to bardzo pouczające i zachęcające, gdy pochodzę z kilkudziesięcioletniego doświadczenia w OO.

maniakalny
źródło
3

Wzorce OOP i GoF dotyczą stanów. OOP modeluje rzeczywistość, aby baza kodu była jak najbardziej zbliżona do podanych wymagań rzeczywistości. Wzorce projektowe GoF to wzorce zidentyfikowane w celu rozwiązania problemów rzeczywistych atomów. Podchodzą do problemu państwa w sposób semantyczny.

Ponieważ w rzeczywistym programowaniu funkcjonalnym nie istnieje żaden stan, nie ma sensu stosowanie wzorców GoF. Nie istnieją funkcjonalne wzorce projektowe w taki sam sposób, jak wzorce projektowe GoF. Każdy wzór funkcjonalny jest sztuczny w przeciwieństwie do rzeczywistości, ponieważ funkcje są konstrukcjami matematyki, a nie rzeczywistości.

Funkcje nie mają pojęcia czasu, ponieważ zawsze zwracają tę samą wartość bez względu na aktualny czas, chyba że czas jest częścią parametrów funkcji, co naprawdę utrudnia przetwarzanie „przyszłych żądań”. Języki hybrydowe mieszają te koncepcje, dzięki czemu języki te nie są prawdziwymi funkcjonalnymi językami programowania.

Języki funkcjonalne rosną tylko z jednego powodu: obecnych naturalnych ograniczeń fizyki. Dzisiejsze procesory mają ograniczoną szybkość przetwarzania instrukcji ze względu na prawa fizyczne. Widoczna jest stagnacja częstotliwości zegara, ale rozszerzenie rdzeni przetwarzających. Dlatego równoległość instrukcji staje się coraz ważniejsza, aby zwiększyć szybkość nowoczesnych aplikacji. Ponieważ programowanie funkcjonalne z definicji nie ma stanu i dlatego nie ma skutków ubocznych, bezpieczne jest równoległe przetwarzanie funkcji.

Wzorce GoF nie są przestarzałe. Są one co najmniej niezbędne do modelowania rzeczywistych wymagań. Ale jeśli używasz funkcjonalnego języka programowania, musisz przekształcić je w ich hybrydowe odpowiedniki. Wreszcie nie masz szansy tworzyć programów funkcjonalnych, jeśli używasz wytrwałości. W przypadku elementów hybrydowych Twojego programu konieczne jest stosowanie wzorców GoF. Dla każdego innego elementu, który jest czysto funkcjonalny, nie ma potrzeby używania wzorców GoF, ponieważ nie ma stanu.

Ponieważ wzorce GoF nie są konieczne do prawdziwego programowania funkcjonalnego, nie oznacza to, że nie należy stosować zasad SOLID. Zasady SOLID wykraczają poza paradygmat języka.

oopexpert
źródło
2
FP może mieć stan - po prostu brak stanu globalnego, współdzielonego lub zmiennego.
vt5491
2

W programowaniu funkcjonalnym wzorce projektowe mają inne znaczenie. W rzeczywistości większość wzorców projektowych OOP jest niepotrzebna w programowaniu funkcjonalnym ze względu na wyższy poziom abstrakcji i wartości HOF wykorzystywane jako elementy składowe.

Zasada HOF oznacza, że ​​funkcje mogą być przekazywane jako argumenty do innych funkcji. i funkcje mogą zwracać wartości.

Ali Bayat
źródło
1

Zgodnie z przyjętą odpowiedzią, OOP i FP mają swoje specyficzne wzorce.

Istnieją jednak pewne wzorce, które są tak powszechne, że powinny istnieć wszystkie platformy programistyczne, o których myślę. Oto (niekompletna) lista:

  • Adapter. Nie mogę sobie wyobrazić użytecznej platformy programistycznej, która jest tak kompleksowa (i samospełniająca się), że nie musi rozmawiać ze światem. Jeśli ma to zrobić, zdecydowanie potrzebny jest adapter.

  • Fasada. Wszelkie platformy programistyczne, które mogą obsługiwać duży kod źródłowy, powinny mieć możliwość modularyzacji. Jeśli chcesz utworzyć moduł dla innych części programu, będziesz chciał ukryć „brudne” części kodu i nadać mu ładny interfejs.

  • Interpretator. Ogólnie rzecz biorąc, każdy program wykonuje dwie czynności: analizuje dane wejściowe i dane wyjściowe wydruku. Dane wejściowe myszy muszą zostać przeanalizowane, a widżety okien wydrukowane. Dlatego posiadanie wbudowanego interpretera daje programowi dodatkową moc dostosowywania.

Zauważyłem też, że w typowym języku FP, Haskell, istnieje coś podobnego do wzorców GoF, ale o różnych nazwach. Moim zdaniem sugeruje to, że oni tam byli, ponieważ istnieją pewne typowe problemy do rozwiązania zarówno w językach FP, jak i OOP.

  • Transformator i dekorator monady. Pierwszy służy do dodawania dodatkowej zdolności do istniejącej monady, drugi do dodawania dodatkowej zdolności do istniejącego obiektu.
Silnik Ziemi
źródło
1

Myślę, że każdy paradygmat służy innemu celowi i jako taki nie może być porównywany w ten sposób.

Nie słyszałem, że wzorce projektowe GoF mają zastosowanie do każdego języka. Słyszałem, że mają zastosowanie do wszystkich języków OOP . Jeśli używasz programowania funkcjonalnego, dziedzina problemów, które rozwiązujesz, jest inna niż języki OO.

Nie użyłbym języka funkcjonalnego do napisania interfejsu użytkownika, ale jeden z języków OO, takich jak C # lub Java, ułatwiłby to zadanie. Gdybym pisał funkcjonalny język, nie rozważałbym używania wzorców projektowych OO.

Vincent Ramdhanie
źródło
1

OOP i FP mają różne cele. OOP ma na celu hermetyzację złożoności / ruchomych części komponentów oprogramowania, a FP ma na celu zminimalizowanie złożoności i zależności komponentów oprogramowania.

Jednak te dwa paradygmaty niekoniecznie są w 100% sprzeczne i można je zastosować razem, aby uzyskać korzyści z obu światów.

Nawet w języku, który nie obsługuje natywnie programowania funkcjonalnego, takiego jak C #, możesz napisać kod funkcjonalny, jeśli rozumiesz zasady FP. Podobnie możesz zastosować zasady OOP za pomocą F #, jeśli rozumiesz zasady, wzorce i najlepsze praktyki OOP. Dokonałbyś właściwego wyboru na podstawie sytuacji i problemu, który próbujesz rozwiązać, niezależnie od używanego języka programowania.

Dogu Arslan
źródło
1

Niektóre wzorce są łatwiejsze do wdrożenia w języku wspierającym FP. Na przykład strategię można wdrożyć, ładnie wykorzystując zamknięcia. Jednak w zależności od kontekstu możesz preferować implementację strategii przy użyciu podejścia klasowego, powiedzmy tam, gdzie same strategie są dość skomplikowane i / lub udostępniaj strukturę, którą chcesz modelować przy użyciu metody szablonu.

Z mojego doświadczenia rozwijającego się w języku z wieloma paradygmatami (Ruby), implementacja FP działa dobrze w prostych przypadkach, ale tam, gdzie kontekst jest bardziej skomplikowany, podejście oparte na OF GoF jest lepsze.

Podejście FP nie zastępuje podejścia OOP, ale je uzupełnia.

ComDubh
źródło
0

Najważniejszą cechą programowania funkcjonalnego, IMHO, jest to, że programujesz tylko za pomocą wyrażeń - wyrażeń w wyrażeniach w wyrażeniach, które wszystkie oceniają do ostatniego, końcowego wyrażenia, które „ogrzewa maszynę podczas oceny”.

Najważniejszą cechą programowania obiektowego, IMHO jest to, że programujesz z obiektami o stanie wewnętrznym. Nie można mieć stanu wewnętrznego w czystych funkcjach - obiektowe języki programowania potrzebują instrukcji, aby coś się stało. (W programowaniu funkcjonalnym nie ma instrukcji).

Porównujesz jabłka do pomarańczy. Wzorce programowania obiektowego nie mają zastosowania do programowania funkcji, ponieważ programowanie funkcjonalne to programowanie wyrażeniami, a programowanie obiektowe to programowanie ze stanem wewnętrznym.

Jim Flood
źródło
Hmm, powinienem był zauważyć, że pytanie miało jedenaście lat, zanim odpowiedziałem. :-)
Jim Flood
0

Przygotuj się.

Zirytuje to wielu, słysząc, jak twierdzę, że zastąpiłem wzorce projektowe i obaliłem SOLID i SUCHO. Jestem nikim. Niemniej jednak poprawnie modelowałem architekturę współpracy (produkcji) i opublikowałem zasady budowania procesów online wraz z kodem i nauką stojącą za tym na mojej stronie internetowej http://www.powersemantics.com/ .

Moim argumentem jest to, że wzorce projektowe starają się osiągnąć to, co produkcja nazywa „masową personalizacją”, formą procesu, w której każdy krok może zostać przekształcony, ponownie skomponowany i rozszerzony. Możesz myśleć o takich procesach jak nieskompilowanych skryptach. Nie zamierzam tutaj powtarzać mojego (internetowego) argumentu. Krótko mówiąc, moja architektura masowego dostosowywania zastępuje wzorce projektowe, osiągając tę ​​elastyczność bez zbędnej semantyki. Byłem zaskoczony, że mój model działał tak dobrze, ale sposób, w jaki programiści piszą kod, po prostu nie znosi tego, jak produkcja organizuje współpracę.

  • Produkcja = każdy etap współdziała z jednym produktem
  • OOP = każdy krok współdziała ze sobą i innymi modułami, przekazując produkt od punktu do punktu jak bezużyteczni pracownicy biurowi

Ta architektura nigdy nie wymaga refaktoryzacji. Istnieją również zasady dotyczące centralizacji i dystrybucji, które wpływają na złożoność. Ale aby odpowiedzieć na twoje pytanie, programowanie funkcjonalne jest kolejnym zestawem semantyki przetwarzania, a nie architekturą dla masowych procesów niestandardowych, w których 1) routing źródłowy istnieje jako (skryptowy) dokument, który właściciel może przepisać przed odpaleniem, a 2) moduły mogą być łatwo i dynamicznie dodawane lub usuwane.

Można powiedzieć, że OOP jest paradygmatem „procesu na sztywno” i że wzorce projektowe są sposobami na uniknięcie tego paradygmatu. Ale na tym polega masowa personalizacja. Wzory projektowe ucieleśniają dynamiczne procesy w postaci niechlujnego twardego kodu. Po prostu nie ma sensu. Fakt, że F # pozwala na przekazywanie funkcji jako parametru oznacza, że zarówno języki funkcjonalne, jak i języki OOP próbują same dokonać masowej personalizacji.

Jak bardzo jest to mylące dla czytelnika, który stanowi kod, który reprezentuje skrypt? Wcale nie, jeśli uważasz, że konsumenci twojego kompilatora płacą za takie funkcje, ale dla mnie takie funkcje są marnotrawstwem semantycznym. Są bezcelowe, ponieważ celem masowego dostosowywania jest uczynienie samych procesów dynamicznymi , a nie tylko dynamicznymi dla programisty posługującego się Visual Studio.

RBJ
źródło
0

Robi to, ponieważ wysokopoziomowy funkcjonalny PL (jak OCaml, z klasami, modułami itp.) Z pewnością zastępuje imperatywne języki OOP pod względem wszechstronności typów i siły wyrażania. Abstrakcje nie przeciekają, większość swoich pomysłów możesz wyrazić bezpośrednio w programie. Dlatego tak, zastępuje wzorce projektowe, które w większości są absurdalnie uproszczone w porównaniu do wzorców funkcjonalnych.

exa
źródło