poniedziałek, 13 listopada 2017

Domknięcie (closure), co to jest i z czym to się je?

Na stronie MDN jest taka definicja A closure is the combination of a function and the lexical environment within which that function was declared. Pamiętam, jak przeczytałam ją pierwszy raz. Jak to mawiała moja mama "mózg mi stanął w poprzek". Każde słowo z osobna wydawało mi się co najmniej znajome, nawet jeśli nie w 100% zrozumiałe. Ale wszystkie do kupy powodowały, że mi się odechciewało.

To było wiele lat temu. Wiele lat, w trakcie których wciąż od nowa odkrywałam definicję domknięcia. Wczoraj robiłam proste zadanko, podpięcie pod kolumnę z danymi numerycznymi sortowania po liczbach a nie alfabetycznie (żeby 70 było mniejsze niż 320). Metodę napisałam dość banalną:

function sort(a, b, order) {
  return order === 'desc' ?
    parseFloat(a.balance) - parseFloat(b.balance) :
    parseFloat(b.balance) - parseFloat(a.balance);
};

Zadowolona z wyniku wzięłam się za testowanie. Już po chwili odkryłam, że poza kolumną opisaną w zadaniu, w tabeli jest więcej sortowalnych kolumn z danymi numerycznymi. Moja metoda, która świetnie spełniała swoje zadanie, dla jednej konkretnej kolumny, nie będzie działać, dla dowolnej innej kolumny, ponieważ sortuję wartości ukryte we właściwości balance (a.balance i b.balance). Dla innych kolumn potrzebowałam bardziej elastycznego rozwiązania.

Najłatwiej byłoby dodać nazwę kolumny, do argumentów funkcji. Ale interface funkcji przewidywał 3 konkretne argumenty: pierwszą wartość do sortowania, drugą wartość do sortowania oraz kierunek sortowania. I tu właśnie na pomoc przyszło mi domknięcie.

Ponieważ nie mogę przekazać do mojej funkcji nazwy właściwości, która przechowuje wartość do sortowania, muszę sprawić, żeby moja funkcja została stworzona w środowisku, które już zna tę nazwę. Ten przykład jasno pokazuje o co mi chodzi:

var name = 'Ania';

function greeting() {
  console.log('hello ' + name);
}

Wewnątrz funkcji greeting użyta jest zmienna name utworzona na zewnątrz funkcji. Tego typu działanie nazywa się scope, wszystko to co jest stworzone na zewnątrz funkcji jest widoczne wewnątrz, ale jeśli coś zostało stworzone wewnątrz (z użyciem któregoś ze słów kluczowych var, let lub const) nie jest widoczne na zewnątrz.

Czyli potrzebuję stworzyć środowisko, w którym znana będzie nazwa właściwości która przechowuje wartość do sortowania. Do tego środowiska będę przekazywać tę nazwę (w każdej kolumnie będę korzystać z innej właściwości):

function sortByPropName(propName) {}

Środowisko już jest, wnętrze funkcji będzie znało wartość przekazanego tam argumentu propName, jednak ja do tabeli mam przekazać funkcję, która bedzie przyjmować 3 konkretne argumenty.

function sortByPropName(propName) {
  return function(a, b, order) {}
}

Coś zaczyna z tego wychodzić. Mam już funkcję z potrzebnymi danymi, która zwraca inną funkcję, która oczekuje argumenty wyspecyfikowane w interfejsie. Teraz wystarczy dodać samą logikę, która uwzględnia przekazaną nazwę właściwości przechowujacej wartość do sortowania:

function sortByPropName(propName) {
  return function(a, b, order) {
    return order === 'desc' ?
      parseFloat(a[propName]) - parseFloat(b[propName]) :
      parseFloat(b[propName]) - parseFloat(a[propName]);
  }
}

Wygląda nieźle, prawda? To teraz wystarczy przekazać wynik sortByPropName jako funkcję sortujacą dla kolumny (kod jsx):

<TableHeaderColumn dataField="balance" dataFormat={signedNumber} dataSort sortFunc={sortByPropName('balance')}>Balance</TableHeaderColumn>
<TableHeaderColumn dataField="total_amount" dataFormat={signedNumber} dataSort sortFunc={sortByNumericValue('total_amount')}>Total amount</TableHeaderColumn>

Powyższy kod używa HTML wewnątrz JS, ale nie jak ciągu tekstowego, a bardziej jak obiektów XML. To co jest najważniejsze, to sortFunc, do której przekazuję WYNIK działania sortByPropName. sortFunc oczekuje na funkcję sortującą, która będzie przyjmowała 3 argumenty, czyli dokładnie to, co zwraca sortByPropName.

A gdzie w tym wszystkim jest domknięcie?

Dokładnie w tym, co zwraca sortByPropName. Wartość argumentu propName jest znana tylko wewnątrz funkcji, gdzie jest tworzona kolejna funkcja, która z tej wartości korzysta. Tę funkcję zwracamy na zewnątrz, gdzie jest przypisana do nazwy sortFunc i wykorzystana wewnątrz komponentu TableHeaderColumn. Pomimo, że sortFunc jest używana w zupełnie innym środowisku, ma dostęp do zmiennych ze środowiska, w którym została stworzona. To jest właśnie domknięcie.

wtorek, 22 sierpnia 2017

Oferty szybkiej nauki programowania - przestroga

Przeglądając maile natrafiłam na reklamę "coders lab", szkoły programowania. Jako, ze mój syn w sposób dość intensywny pracuje nad swoimi umiejętnościami w zakresie programowania w JavaScript z dużym zainteresowaniem przejrzałam stronę. Marketing mają niezły, ofertę wpisującą się w moje potrzeby, ale... diabeł tkwi w szczegółach.

Na studiach psychologicznych każdy student wcześniej czy później styka się z teorią krzywej uczenia się. Otóż ta teoria zakłada, że uczenie się jest PROCESEM i, jak każdy proces, wzmaga CZASU. Procesem składającym się z kilku faz. Najważniejsze są dwie: faza zdobywania nowej wiedzy i faza utrwalania (tzw plateau), kiedy krzywa jest zupełnie płaska, bo podczas utrwalania nie jesteśmy w stanie realnie nauczyć się niczego nowego, bo zdobywamy doświadczenie w nowo zdobytej wiedzy. Realnie krzywa ma kształt najbardziej zbliżony do schodów.

Znając teorie uczenia się, posuwamy się z Młodym, w nauce, pozornie żółwim tempem. Na tę chwilę wciąż jesteśmy na etapie czystego JS. Żadnych bibliotek, same zasady kierujące językiem, który poznaje. Typy danych i wbudowane obiekty mamy omówione. W ramach utrwalania tej wiedzy (faza plateau) Młody przerabia metody należące do prototypu różnych obiektów. I tak wiem, ze więcej nie zrobi, więc niech zdobywa doświadczenie w zakresie nowo poznanej wiedzy. Na tę chwilę trwa to już kilka tygodni, ale Młody ma wiedzę utrwalona. Pytania o to, jak działa scope czy jak zmienić kontekst w jakim wykonywana jest funkcja nie stanowią już dla niego wyzwania. Wiedza utrwaliła się.

Coders lab niestety hołduje zasadzie im szybciej tym lepiej. Jednym z interesujących mnie kursów z ich oferty jest "JavaScript developer: React". Kurs trwa 30 dni, w opisie stoi: "Kurs od podstaw odpowiedni dla tych, którzy wcześniej nie mieli styczności z programowaniem. Spodoba się osobom, które lubią zagadki logiczne i wolą skupić się na tym, jak coś działa niż na tym, jak wygląda[...]". Gdzieś w tym momencie przestałam rozumieć ofertę. Kurs oferuje naukę od podstaw, dla osób, które nigdy wcześniej nie miały styczności z programowaniem. Zgodnie z tytułem jest to kurs JavaScript rozszerzony o bibliotekę react. I trwa 30 dni. Nauka samego JavaScriptu to kilka miesięcy. React to też co najmniej kilka następnych tygodni. Bo przecież nie chodzi o samą znajomość składni czy używanych metod, a o zrozumienie, JAK i DLACZEGO to działa.

Hasłem przewodnim strony jest: "W Coders Lab zmieniamy edukację – w ciągu 3 miesięcy zostaniesz junior developerem". Junior developer nie musi mieć doświadczenia (stąd junior), nie musi znać zaawansowanych przypadków użycia, opracować rozwiązań skomplikowanych problemów. Junior MUSI rozumieć język i technologie, w których pracuje. Musi mieć podstawy umożliwiające mu rozwijanie wiedzy. React jest biblioteką napisaną w czystym JS. Jest tylko biblioteką, żeby react zadziałał, programista sam musi napisać kod, który skorzysta z reacta i wynikiem działania napisanego kodu będzie to, co programista chciał osiągnąć. React jest NARZĘDZIEM, którego używa się za pośrednictwem JavaScriptu, wiec żeby zostać junior developerem kandydat musi znać co najmniej bardzo dobrze JavaScript. Musi rozumieć jak działa interpreter (w przeglądarce i na serwerze - nodejs), jak JS buduje scope, czym jest kontekst. Musi znać i swobodnie używać metod obiektów wbudowanych (tablice, plain obiekty, Date, JSON). Musi widzieć dlaczego null jest specjalny i jak i kiedy go używać.

Powyższe zagadnienia są poruszane podczas rozmów kwalifikacyjnych, na stanowiska związane z JS. Bibliotek można szybko się nauczyć, a to są podstawy samego języka i są wymagane, żeby w ogóle zacząć pracę z bibliotekami.

W szczegółach kursu stoją technologie, które wchodzą w jego skład: HTML, CSS, JavaScript, jQuery, React, Gulp, Sass, RWD. Dobór trochę z Księżyca. Skoro kurs skupia się na logice a nie na prezentacji (jak jest opisane) to po co CSS, SASS i RWD? Po co komu jQuery do reacta? I co z tym wszystkim ma wspólnego gulp? I dlaczego nie ma webpacka i babel? I gdzie jest ES6/7/8?

Podsumowując. Te, i wszystkie podobne im szkolenia, muszą być dokładnie przejrzane przez kogoś, kto ma rozległą wiedzę z tematu. I cały czas należy pamiętać, że nie da się przyswoić większej ilości wiedzy w krótkim czasie, tak by ta wiedza została i służyła. Dlatego nauka w szkole trwa 12 lat a nie 4, mimo, ze dzieci uczą się szybciej. Zdobywanie wiedzy polega również na powtarzaniu i używaniu świeżo zdobytych umiejętności, wiec powracanie do wcześniej przerobionego materiału jest niezbędne. A to wszystko wymaga czasu.

czwartek, 20 lipca 2017

example how and what for to use anonymous functions

I wrote some short introduction to anonymous function here, some time ago. I wrote some simple example, but no example for real life situation. Today I decided to write down an example which could be very useful on technical interview.

This is a very simple code example. We have a loop and inside this loop we create an array of functions. Every of functions logs i on the console. Then in the end we are calling the first function from the array.

var i = 0;
var funcArray = [];
for (; i < 20; i += 2) {
  funcArray.push(function() {
    console.log('i inside function', i);
  };
});

funcArray[0]();

What we want to achieve here is, to have an array of functions, to use inside of function a value of i. We cannot use index of function in array, as i is incremented by 2. This implementation looks like the easiest solution for our need.

So what would display on console as a result of this line funcArray[0]();? We expect it to be 0, but unfortunately it is... 20... WHY??

The answer is very easy - the scope. The thing which makes JavaScript harder to learn. But is very logic. Scope exists on function level (ES5) or on block level (ES6+). In this case inside of loop the function which uses scope variable i is created. But the function is called outside the loop, where i has a value 20 (the first value, which didn't meet the requirement, so there was no more incrementation of i).

So it doesn't matter which index would be called, the i outside of loop is always equal the first value, which didn't pass the condiition. It means we have to change the way how we create the scope for our function. And here the anonymous function will come with help.

What should be done, then? We have to create immediately invoked anonymous function, which will create the scope and will return the function which will be assigned to array element. As a parameter to anonymous function i will be passed to make it available inside the scope.

funcArray.push(( // immediately invoked function
// anonymous function, which gets i from scope as index
  function (index) {
    return function() { // returns a our function
      console.log('index inside function', index);
    }
  }
)(i)); // i passed to immediately invoked function

środa, 12 lipca 2017

pojęcie o zawodzie programisty wśród młodzieży

Ostatnio na Facebook trafiłam na taką wypowiedź:

Chciałabym poznać opinię. Zaczęłam się interesować samorozwojem i stwierdziłam że branża it jest najwlasciwsza dla mnie. No i super rozeznanie w terenie co jak po co. Sprawdzałam wyksztalcenie, doświadczenie, wiek no wszystko co trzeba. Stwierdziłam że może maturę będę potrzebować więc dałam zapytanie na lokalnej grupie o maturę w uk jak tu zdac, warunki etc. Koleżanka która pomaga czasem innym w sprawach counsil/ revenue/ inne urzędy poradziła mi gdzie się udać i zabiła mnie pytaniem .... A nie lepiej dla Ciebie jakbyś się wzięła za fryzjerstwo czy paznokcie??? ... No kurde. Ja jej mówię o tym że chce programować strony komputerowe, pisać aplikację, generalnie branża no wiadomo, A ta wypala o ee paznokciach? Wlosach? Jak ja kurde miałam raz tipsy na rękach z 8 lat temu a o makijażu mam takie pojęcie że otynkowanie zaczynamy od fluidu pudru czy czegoś. Czy ja przesadzam czy mi się wydaje?

Napisałam panience, że niestety wykształcenie, jeśli nie ma odpowiedniego doświadczenia, jest niezbędne. W odpowiedzi dostałam link do holenderskiej oferty dla juniora frontendowca bez wymagań związanych z wykształceniem/doświadczeniem oraz taki tekst:

Zresztą nie będę wiedzieć jeśli nie sprobuje. Nikt i nic mnie nie zniechęci Bo "gdzieś tam potrzebują szkoly". Do firmy kolegi na stanowisko junior chcieli wziąć chłopaka po 4 tyg kursie za który sami zaplacili. Także ten. I już sama nie wiem, czy to powszechne podejście do zawodu programisty? Pracowałam już z ludźmi, dla których hasło "złożoność obliczeniowa" było zbędnym i wymyślonym na siłę problemem, nad którym nie warto się pochylić...

deadline'y...

Pracuję sobie w firmie, takim prawie prawdziwym startupie. Prawie, bo mamy bogatą firmę-matkę, która łoży na nasze utrzymanie.

Piszemy aplikację WWW, backend dostarcza nam trzecia firma. Ja zajmuję się dość krytyczną częścią, bo zapisem danych wprowadzonych przez przyszłego klienta. Tworzę z mozołem DTO, które mam później pchnąć do backendu i odkrywam, że czegoś nie wiem.

Pierwsze pytanie do naszego konsultanta z firmy trzeciej, który siedzi z nami w open space. Pada odpowiedź - nie da się, już rozmawiałem z działem wdrożeniowym i tej funkcjonalności na razie nie ma.

Nogi się pode mną ugięły. Jak to nie ma? Toż to krytyczna funkcjonalność... Idź do XYZ i z nim pogadaj dostaję dobrą radę i konsultant zakłada słuchawki.

Idę, ale do S, naszego product ownera, i mówię, że mamy bloker. Już nawet się oparłam dodania, że to kolejny. No co ty nie powiesz krzywi się S i uderza do konsultanta, który odsyła go do XYZ.

S właśnie wrócił do mnie z wiadomością, że it is not in scope. A soft launch mamy w pierwszej połowie sierpnia, to ciekawie kiedy trafi do implementacji?