Programowanie funkcjonalne a OOP [zamknięte]

93

Ostatnio dużo mówiłem o używaniu języków funkcjonalnych, takich jak Haskell. Jakie są duże różnice, zalety i wady programowania funkcjonalnego w porównaniu z programowaniem obiektowym?

GSto
źródło
27
Jeden nie odrzuca drugiego.
mbq
1
@mbq Rozumiem, że nie wykluczają się wzajemnie, ale chciałem tylko lepiej zrozumieć różnicę między tymi dwoma podejściami.
GSto
Świetne pytanie. Też się nad tym zastanawiałem.
JohnFx,
Programowanie funkcjonalne i programowanie obiektowe są względem siebie ortogonalne. Możesz mieć oba w tym samym języku. Przykłady: Scala, F #, OCaml itp. Może miałeś na myśli funkcjonalny vs imperatywny, jak sugerował Jonas ?
missingfaktor 16.10.10
4
Prawdziwa odpowiedź brzmi - nie ma między nimi „kontra”. Sprawdź to pytanie na StackOverflow .
missingfaktor 18.10.10

Odpowiedzi:

67

Powiedziałbym, że jest bardziej Programowanie funkcyjne vs Imperatyw Programowanie .

Największa różnica polega na tym, że programowanie imperatywne dotyczy przepływu sterowania, podczas gdy programowanie funkcjonalne dotyczy przepływu danych . Innym sposobem jest powiedzenie, że programowanie funkcjonalne używa tylko wyrażeń, podczas gdy w programowaniu imperatywnym używane są zarówno wyrażenia, jak i instrukcje .

Na przykład w imperatywnym programowaniu zmienne i pętle są powszechne podczas obsługi stanu, podczas gdy w programowaniu funkcjonalnym stan jest obsługiwany przez przekazywanie parametrów, co pozwala uniknąć efektów ubocznych i przypisań.

Pseudo-kod imperatywny dla funkcji do obliczania sumy listy (suma jest przechowywana w zmiennej):

int sumList(List<int> list) {
    int sum = 0;
    for(int n = 0; n < list.size(); n++) {
        sum = sum + list.get(n);
    }

    return sum;
}

Funkcjonalny pseudo-kod dla tej samej funkcji (suma jest przekazywana jako parametr):

fun sumList([], sum) = sum
 |  sumList(v::lst, sum) = sumList(lst, v+sum)

Polecam prezentację Taming Effects with Functional Programming autorstwa Simona Peytona-Jonesa, która stanowi dobre wprowadzenie do koncepcji funkcjonalnych.

Jonas
źródło
12
Należy wspomnieć, że wersja funkcjonalna jest rekurencyjna, a zatem zoptymalizowana, aby uniknąć przepełnienia stosu. (Niektórzy ludzie mogą zobaczyć rekurencję i sądzić, że programowanie funkcjonalne jest z tego powodu złe)
alternatywny
3
+1 za opisanie najważniejszego aspektu trybu rozkazującego vs. funkcjonalnego: przepływ sterowania a przepływ danych. Muszę dodać, że paradygmat funkcjonalny i paradygmat OO nie wykluczają się wzajemnie; możesz użyć paradygmatu OO do modelowania interakcji między obiektem (danymi), a paradygmatu funkcjonalnego do transformacji (manipulacji) tego obiektu.
Lie Ryan,
1
Co ciekawe, można modelować dane jako kontrolę i kontrolę jako dane, a także do mieszania. FP może używać strzałek i funkcji pierwszego rzędu, aby przekazywać przepływ kontroli i manipulować nim jak z danymi. OOP wykorzystuje różne wzorce projektowe do wykorzystania obiektów do zmiany przepływu sterowania.
CodexArcanum
Myślę, że warto również zauważyć, że główna różnica nie polega na tym, że piszesz ten sam program, ale tworzysz rekurencyjne wywołania metod w pętli. jest znacznie większy
sara
Twój funkcjonalny przykład wykorzystuje dopasowanie parametrów do wzorca. Nie dotyczy to wyłącznie programowania funkcjonalnego, podobnie funkcjonalne programy mogą używać monad, a nawet konstrukcji imperatywnych, bez konieczności formułowania każdego algorytmu iteracyjnego jako algorytmu rekurencyjnego.
Dai
16

Programowanie funkcjonalne oparte jest na modelu deklaratywnym i wywodzi się z rachunku lambda. Oferuje wiele świetnych koncepcji, które można wypożyczyć z bardziej imperatywnych języków, takich jak C ++ i C #.

Niektóre przykłady obejmują przejrzystość referencyjną, funkcje lambda, funkcje pierwszej klasy, leniwe i chętne oceny oraz niezmienność.

Jeśli na nic innego uczenie się programowania funkcjonalnego jest przydatne dla zawartych w nim pojęć. Zmieni to sposób programowania i myślenia o programowaniu. Sądzę, że w przyszłości programowanie funkcjonalne będzie równie ważne, jak programowanie obiektowe.

Aby rozpocząć, możesz użyć czysto funkcjonalnego języka, takiego jak Haskell, lub możesz użyć języka hybrydowego, takiego jak F # .

Większość dobrych uniwersytetów będzie zajmować się programowaniem funkcjonalnym, a jeśli pójdziesz do szkoły, bardzo sugeruję, abyś wybrał ten kurs.


Jakie są duże różnice, zalety i wady programowania funkcjonalnego w porównaniu z programowaniem obiektowym?

Dobrze zorientowane obiektowo programowanie jest dobre, ponieważ pozwala modelować złożony problem w hierarchie, dzięki czemu można uprościć problem. Ale staje się bardzo trudne, gdy zaczynasz rozważać programowanie wielowątkowe podczas korzystania ze zmiennych obiektów. W takich przypadkach musisz intensywnie korzystać z obiektów synchronizacji, a doskonalenie dużej aplikacji jest prawie niemożliwe.

W tym miejscu pojawia się programowanie funkcjonalne. Z powodu niezmienności programowanie funkcjonalne naprawdę upraszcza programy wielowątkowe. To sprawia, że ​​prawie w prosty sposób można zrównoleglić coś, gdy wiesz, że dane wejście X do funkcji zawsze będzie generować Y. Ponadto wiesz, że zmienna (lub wartość w programowaniu funkcjonalnym) nie może zmienić środka użycia z innego wątku.

Brian R. Bondy
źródło
2
Dla jasności Schemat nie jest w żadnym wypadku czystym językiem funkcjonalnym.
Jonathan Sterling
5
Twój ostatni akapit jest całkowicie bs. OO nie stwarza żadnych problemów w wielowątkowości, zmienność tak. Wydaje się, że mylisz programowanie imperatywne z programowaniem obiektowym. Czy tak jest w przypadku?
missingfaktor
5
@missingfaktor: Nie, nie mylę pojęć. Obiekt zazwyczaj ma akcesory, modyfikatory, elementy danych i funkcje elementów. Tak, nie wszystkie obiekty muszą mieć modyfikatory i można je zaimplementować jako niezmienne. Ale jeśli spojrzysz na dowolny dowolny program OO, prawie na pewno będzie miał kilka obiektów, które mają modyfikatory, a mimo to nadal są używane przez wiele wątków. Tj. W paradygmacie OOP rzadko zdarza się mieć wszystko niezmienne.
Brian R. Bondy
Powinieneś przeczytać odpowiedzi na to pytanie: stackoverflow.com/questions/3949618/fp-and-oo-orthogonal/…
missingfaktor
Sprawdź także odpowiedź Franka Shearara tutaj: programmers.stackexchange.com/questions/12423/…
missingfaktor
8

(Ta odpowiedź jest dostosowywana z odpowiedzi na pytanie zamknięte w StackOverflow .)

Jedną z dużych różnic między programowaniem funkcjonalnym a programowaniem obiektowym jest to, że każdy z nich jest lepszy w różnego rodzaju ewolucji oprogramowania:

  • Języki zorientowane obiektowo są dobre, gdy masz ustalony zestaw operacji na rzeczach , a wraz z rozwojem kodu dodajesz przede wszystkim nowe rzeczy. Można to osiągnąć przez dodanie nowych klas, które implementują istniejące metody, a istniejące klasy pozostawia się w spokoju.

  • Języki funkcjonalne są dobre, gdy masz stały zestaw rzeczy , a wraz z ewolucją kodu dodajesz przede wszystkim nowe operacje na istniejących rzeczach. Można to osiągnąć przez dodanie nowych funkcji, które obliczają z istniejącymi typami danych, a istniejące funkcje są pozostawione same sobie.

Kiedy ewolucja idzie w złym kierunku, masz problemy:

  • Dodanie nowej operacji do programu obiektowego może wymagać edycji wielu definicji klas w celu dodania nowej metody.

  • Dodanie nowego rodzaju rzeczy do programu funkcjonalnego może wymagać edycji wielu definicji funkcji, aby dodać nowy przypadek.

Problem ten jest dobrze znany od wielu lat; w 1998 roku Phil Wadler nazwał to „problemem ekspresji” . Chociaż niektórzy badacze uważają, że problem z ekspresją można rozwiązać za pomocą takich cech językowych, jak mixiny, powszechnie akceptowane rozwiązanie nie znalazło się jeszcze w głównym nurcie.

Norman Ramsey
źródło
Uwielbiam twoją odpowiedź, słowo mądrości tutaj. Spotkałem go kilka miesięcy temu i spędziłem 30 minut na szukaniu go, ponieważ nie dodałem go do zakładek. Tylko najlepsze wyjaśnienie OOP vs. FP dla tych, którzy rozumieją przewagę rozumienia pojęć zamiast technik. Fantastyczny jest także artykuł na temat problemu ekspresji. Bardzo dziękuję za podzielenie się spostrzeżeniami, moja opinia jest bardzo niedoceniana.
tobiak777
4

Nie ma prawdziwego kontra. Mogą się doskonale uzupełniać. Istnieją języki FP, które obsługują OOP. Ale społeczności różnią się sposobem obsługi modułowości.

Użytkownicy języków FP mają tendencję do osiągania modułowości dzięki prawom matematyki. I wolą dowody potwierdzające zgodność z ich przepisami.

W trybie bezwzględnym użytkownicy OOP mają tendencję do rejestrowania zachowania obiektu w przypadkach testowych, które mogą być uruchomione ponownie, jeśli obiekt się zmienił i uzyskują w ten sposób modułowość.

To tylko mały aspekt, ale myślę, że warto o tym wspomnieć.

Edgar Klerks
źródło
2

Analogia:

Otrzymałeś podanie o pracę. Podajesz swoje imię i nazwisko, dane kontaktowe i historię pracy. Po zakończeniu nie będziesz już mieć pustej aplikacji.

Zamiast tego wyobraź sobie, że przed napisaniem nałóż ją na przezroczystą warstwę celofanu. Piszesz swoje imię Dodajesz kolejny arkusz celofanu. Podajesz swoje dane kontaktowe. Więcej celofanu. Piszesz swoją historię pracy. Po zakończeniu nadal pozostaje pusta aplikacja. Masz również trzy arkusze celofanu, z których każdy uchwycił efekt pojedynczej, dyskretnej zmiany.

Pierwszy (OOP) popiera pomysł zmiany rzeczy na miejscu, podczas gdy drugi (FP) odrzuca go. Oba są paradygmatami zarządzania stanem. Obie mogą, stosując różne strategie, uchwycić efekt wypełnienia podania o pracę. OOP zmienia instrument początkowy bezpośrednio, podczas gdy FP nakłada się na to, co było wcześniej, aby wpłynąć na pojawienie się zmiany .

Mario T. Lanza
źródło
piękna analogia, dzięki !! czy miałbyś coś przeciwko (jeśli to możliwe) rozszerzenie tej analogii o zalety i wady w tych dwóch podejściach?
Rahul Agarwal