Programowanie funkcyjne jest drugim, obok obiektowego, z najważniejszych paradygmatów języka JavaScript. W podejściu obiektowym zrozumienie kodu uzyskuje się m.in. dzięki hermetyzacji zmieniających elementów. Programowanie funkcyjne ułatwia zrozumienie kodu dzięki minimalizowaniu liczby takich elementów. Dzięki podziałowi zadań na proste funkcje oraz mniejszej złożoności kodu, wpływa na poprawę jakości kodu, pozwala uzyskać rozszerzalną i przejrzystą strukturę aplikacji oraz umożliwia wielokrotne wykorzystywanie kodu.

Zacznij myśleć funkcyjnie

Celem programowania funkcyjnego nie jest podział programu na funkcje. Celem jest abstrakcyjne ujęcie operacji na danych za pomocą funkcji, tak aby uniknąć efektów ubocznych i ograniczyć modyfikacje stanu w aplikacji. Programowanie funkcyjne jest powszechnie wykorzystywane, a jego elementy spotkać możemy korzystając np. z biblioteki React.

Dlatego warto przyswoić sobie podstawowe terminy związane z programowaniem funkcyjnym, co najlepiej zrobić na przykładach.

Programowanie funkcyjne jest deklaratywne

W przypadku programowania deklaratywnego opisujemy co chcemy osiągnąć (jakie warunki musi spełniać rozwiązanie końcowe). Uzyskuje się to m.in. poprzez unikanie imperatywnych struktur sterujących (pętli), które są trudne do ponownego wykorzystania i scalania z innymi operacjami. Co ważne, podejście deklaratywne wpływa na minimalizację skutków ubocznych, co z kolei przekłada się na mniejszą ilość błędów.

Przykład kodu imperatywnego:

var array = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];

for (let i = 0; i < array.length; i++) {
  array[i] = Math.pow(array[i], 2);
}

Przykład kodu deklaratywnego:

const numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];

const squareNumber = num => Math.pow(num, 2);

numbers.map(squareNumber);

Funkcje powinny być czyste

Czyste funkcje to funkcje, które nie wykonują zmian poza swoim zasięgiem. Ich wynik zależy od danych wejściowych, a nie zewnętrznego stanu. Funkcja taka zwraca ten sam wynik dla tych samych danych wejściowych. O takich funkcjach mówimy, że są przejrzyste referencyjnie.

Przykład funkcji, która nie jest przejrzysta referencyjnie:

let counter = 0;

function increment() {
  return ++counter;
}

Przykład funkcji przejrzystej referencyjnie:

function increment(counter) {
  return counter++;
}

Niemodyfikowalność danych

Niemodyfikowalne dane to takie, które nie mogą być zmieniane po ich utworzeniu. Dzięki takiemu podejściu zmniejszamy ryzyko pojawiania się błędów oraz niepożądanych skutków ubocznych.

Przykład mutacji danych:

const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];

const sortDesc = arr => {
  return arr.sort((a, b) => b - a);
};

sortDesc(arr); //-> [9,8,7,6,5,4,3,2,1]
arr; //-> [9,8,7,6,5,4,3,2,1]

Sortowanie bez mutacji danych:

const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];

const sortDesc = arr => {
  return [...arr].sort((a, b) => b - a);
};

sortDesc(arr); //-> [9, 8, 7, 6, 5, 4, 3, 2, 1]
arr; //-> [1, 2, 3, 4, 5, 6, 7, 8, 9]

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *