Co to Closure?

0

Jw. czym dokładnie jest Closure i po co i kiedy stosować?

2

Closure to funkcja anonimowa, która dodatkowo przenosi kontekst uruchomienia, przykład masz tutaj https://3v4l.org/aonDS.

Jak sam widzisz w lambda nie przenosi ze sobą kontekstu w którym została zdefiniowana, natomiast domknięcie jak najbardziej. W PHP masz na to osobną składnię, która pozwala Ci zdefiniować które wartości zostaną "zachowane" w kontekście. Przykładem gdzie jest to przydatne jest gdy chcesz programować bardziej funkcyjnie, i powiedzmy, że chcesz mieć funkcję przyjmującą wartość i zwraca funkcję przyjmującą tablicę, która zwraca tylko elementy większe niż podana wartość, z użyciem domknięcia jest to proste:

# https://3v4l.org/lF1NK

function greater_than($needle) {
  return function($array) use ($needle) {
    return array_filter($array, function($item) use ($needle) {
      return $item > $needle;
    });
  };
}

$filter = greater_than(5);

var_dump($filter([1,2,3,4,5,6,7,8,9,10]));

Artykuł: https://www.culttt.com/2013/03/25/what-are-php-lambdas-and-closures/

1

Domknięcie to najprościej mówiąc funkcja wraz ze środowiskiem w którym została zdefiniowana. Przykład:

function f(x) {
    function g(y) {
        return x + y;
    };
};

Teraz niech var nasza_funkcja = f(2). nasza_funkcja jest teraz domknięciem w którym funkcja (g(y)) jest związana ze środowiskiem w którym x jest równe 2.
Co byłoby gdyby tak nie było? Zmienna mogłaby być wiązana dynamicznie, tzn. nasza_funkcja mogłoby dawać różne wyniki w zależności od środowiska w którym funkcja jest wywoływana.
Po co? Np. po to by wygodnie korzystać z lokalnie definiowanych funkcji. Nie musimy przekazywać wszystkich parametrów, bo część jest już wygodnie związana w domknięciu.

1

Domknięcie to pojęcie z półki generycznego programowania, pozwala na tworzenie konkretnych wariantów funkcji (bardziej uszczegółowionych) na podstawie ogólnego zapisu funkcji bazowej.

Ważne pytanie to po co w ogóle tworzyć taki ogólny kod? Czy źle robię pisząc wprost konkretną funkcję?

Ogólny kod pozwoli Ci łatwiej zaimplementować pewne znane wzorce projektowe na poziomie języka np. dekorator [0], iterator [1], wstrzykiwanie zależności [2], context manager [3] no i właściwie z paru prostszych funkcji możesz złożyć jedną złożoną [4]. Tym samym rozdrobnisz kod na mniejsze kawałki przez co kod stanie się bardziej adaptywny [5] i jednocześnie będzie 1000 razy prostszy w testowaniu jednostkowym.

Brzmi super, prawda?

Niestety pisząc ogólny kod można baaardzo łatwo przegiąć. Z roku na rok coraz bardziej myślę, że taki kod powinno się naprawdę rzadko pisać, oto powody z jakimi najczęściej się zderzam:

  • pisanie ogólnego kodu zabiera więcej czasu
  • jest bardziej złożone (najczęściej w przypadku, gdy ktoś utrzymuje kod po Tobie)
  • dla wielu ludzi lepsza w czytaniu i modyfikowaiu jest funkcja na 200 lini niż zapis funkcyjny na 10-20 lini (zwróć uwagę, że programiści JS to częściej debile więc nie utrudniaj im życia)
  • więcej czasu zajmuje debugowanie

Dlatego najlepiej jest zachować balans. Tzn pisać możliwie prosto (bez niepotrzebnych abstrakcji), a gdy w pewnych miejscach projektu prymitywny kod okaże się żmudny dla zespołu wówczas można go zrefaktoryzować korzystając z ogólnych zapisów np. wzorce, po to by nadać mu więcej abstrakcji, żeby tym kodem jednak łatwiej się operowało. Np. może być to krok w kierunku testowalności, czy samej rozszerzalności.

[0] - https://www.sitepoint.com/javascript-decorators-what-they-are/
[1] - https://developer.mozilla.org/pl/docs/Web/JavaScript/Guide/Iterators_and_Generators
[2] - https://dzone.com/articles/dependency-injection-and
[3] - https://brianschiller.com/blog/2017/09/20/python-style-context-managers-in-js
[4] - https://medium.com/javascript-scene/master-the-javascript-interview-what-is-function-composition-20dfb109a1a0
[5] - https://helion.pl/ksiazki/adaptywny-kod-zwinne-programowanie-wzorce-projektowe-i-solid-ne-zasady-wydanie-ii-gary-mclean-hall,adakod.htm

1 użytkowników online, w tym zalogowanych: 0, gości: 1