Udostępnij za pośrednictwem


Programowanie funkcjonalne a programowanie imperatywne (LINQ to XML)

W tym artykule porównano i porównano programowanie funkcjonalne z bardziej tradycyjnym programowaniem imperatywnym (proceduralnym).

Programowanie funkcjonalne a programowanie imperatywne

Model programowania funkcjonalnego został jawnie utworzony w celu obsługi czystego funkcjonalnego podejścia do rozwiązywania problemów. Programowanie funkcjonalne to forma programowania deklaratywnego. Natomiast większość języków głównego nurtu, w tym języków programowania obiektowego (OOP), takich jak C#, Visual Basic, C++i Java, została zaprojektowana do obsługi głównie programowania imperatywnego (proceduralnego).

W przypadku podejścia imperatywnego deweloper pisze kod określający kroki, które komputer musi wykonać, aby osiągnąć ten cel. Jest to czasami nazywane programowaniem algorytmicznym . Natomiast podejście funkcjonalne polega na utworzeniu problemu jako zestawu funkcji do wykonania. Należy dokładnie zdefiniować dane wejściowe dla każdej funkcji i zwracać każdą funkcję. W poniższej tabeli opisano niektóre ogólne różnice między tymi dwoma podejściami.

Characteristic Podejście imperatywne Podejście funkcjonalne
Koncentracja programistów Jak wykonywać zadania (algorytmy) i jak śledzić zmiany w stanie. Jakie informacje są wymagane i jakie przekształcenia są wymagane.
Zmiany stanu Ważne. Nieistniejące.
Kolejność wykonywania Ważne. Niska ważność.
Sterowanie przepływem podstawowym Pętle, warunkowe i wywołania funkcji (metoda). Wywołania funkcji, w tym rekursja.
Podstawowa jednostka manipulowania Wystąpienia struktur lub klas. Funkcje jako obiekty pierwszej klasy i kolekcje danych.

Chociaż większość języków została zaprojektowana pod kątem obsługi określonego paradygmatu programowania, wiele języków ogólnych jest wystarczająco elastycznych, aby obsługiwać wiele paradygmatów. Na przykład większość języków zawierających wskaźniki funkcji może służyć do wiarygodnego obsługi programowania funkcjonalnego. Ponadto języki C# i Visual Basic zawierają jawne rozszerzenia języka do obsługi programowania funkcjonalnego, w tym wyrażenia lambda i wnioskowanie typów. Technologia LINQ jest formą deklaratywnego, funkcjonalnego programowania.

Programowanie funkcjonalne przy użyciu języka XSLT

Wielu deweloperów XSLT jest zaznajomionych z czystym podejściem funkcjonalnym. Najbardziej efektywnym sposobem opracowywania arkusza stylów XSLT jest traktowanie każdego szablonu jako izolowanej, komponowalnej transformacji. Kolejność wykonywania jest całkowicie de-podkreślona. XSLT nie zezwala na skutki uboczne (z wyjątkiem, że ucieczka mechanizmów wykonywania kodu proceduralnych może wprowadzać skutki uboczne, które powodują zanieczyszczenia funkcjonalne). Jednak chociaż XSLT jest skutecznym narzędziem, niektóre z jego cech nie są optymalne. Na przykład wyrażanie konstrukcji programowania w języku XML sprawia, że kod jest stosunkowo pełny i dlatego trudny do utrzymania. Ponadto duże poleganie na rekursji dla sterowania przepływem może spowodować, że kod jest trudny do odczytania. Aby uzyskać więcej informacji na temat XSLT, zobacz Przekształcenia XSLT.

Jednak XSLT udowodnił wartość użycia czystego funkcjonalnego podejścia do przekształcania kodu XML z jednego kształtu na inny. Czyste programowanie funkcjonalne z LINQ to XML jest podobne na wiele sposobów do XSLT. Jednak konstrukcje programowania wprowadzone przez LINQ to XML, C# i Visual Basic umożliwiają pisanie czystych przekształceń funkcjonalnych, które są bardziej czytelne i konserwowalne niż XSLT.

Zalety czystych funkcji

Główną przyczyną implementacji przekształceń funkcjonalnych jako czystych funkcji jest to, że czyste funkcje są komponowalne: czyli samodzielne i bezstanowe. Te cechy przynoszą szereg korzyści, w tym następujące:

  • Zwiększona czytelność i łatwość konserwacji. Wynika to z faktu, że każda funkcja została zaprojektowana w celu wykonania określonego zadania, biorąc pod uwagę jego argumenty. Funkcja nie opiera się na żadnym stanie zewnętrznym.
  • Łatwiejsze programowanie reiteracyjne. Ponieważ kod jest łatwiejszy do refaktoryzacji, zmiany projektu są często łatwiejsze do zaimplementowania. Załóżmy na przykład, że piszesz skomplikowaną transformację, a następnie zdajesz sobie sprawę, że jakiś kod jest powtarzany kilka razy w transformacji. Jeśli refaktoryzujesz za pomocą czystej metody, możesz wywołać czystą metodę bez martwienia się o skutki uboczne.
  • Łatwiejsze testowanie i debugowanie. Ponieważ czyste funkcje można łatwiej testować w izolacji, można napisać kod testowy, który wywołuje czystą funkcję z typowymi wartościami, prawidłowymi przypadkami krawędzi i nieprawidłowymi przypadkami krawędzi.

Ze względów opisanych powyżej programowanie funkcjonalne jest dobrze dostosowane do stylu architektury mikrousług.

Przechodzenie dla deweloperów OOP

W tradycyjnym programowaniu obiektowym (OOP) większość deweloperów jest przyzwyczajona do programowania w stylu imperatywnym/proceduralnym. Aby przełączyć się na rozwój w czystym stylu funkcjonalnym, muszą przejść do myślenia i podejścia do rozwoju.

Aby rozwiązać problemy, deweloperzy OOP projektują hierarchie klas, koncentrują się na odpowiedniej hermetyzacji i myślą o kontraktach klasowych. Zachowanie i stan typów obiektów są najważniejsze, a funkcje języka, takie jak klasy, interfejsy, dziedziczenie i polimorfizm, są udostępniane w celu rozwiązania tych problemów.

Natomiast programowanie funkcjonalne podchodzi do problemów obliczeniowych jako ćwiczenia w ocenie czystych przekształceń funkcjonalnych kolekcji danych. Programowanie funkcjonalne pozwala uniknąć stanu i modyfikowalnego danych, a zamiast tego podkreśla stosowanie funkcji.

Na szczęście języki C# i Visual Basic nie wymagają pełnego skoku w programowaniu funkcjonalnym, ponieważ obsługują zarówno podejścia imperatywne, jak i funkcjonalne. Deweloper może wybrać, które podejście jest najbardziej odpowiednie dla konkretnego scenariusza. W rzeczywistości programy często łączą oba podejścia.

Zobacz też