Първоначално публикувано в ifelse.io на 27 януари 2015 г.

tl;dr

  • повечето от нашите програми са по-сложни, отколкото трябва да бъдат
  • функционалните подходи обикновено водят до код, който:
  • е по-лесен за четене има по-малко изходни редове е по-прост поставя по-малко изисквания към програмиста
  • простотата е наистина трудна
  • гледайте това, използвайте lodash, научете haskell (или друг функционален език)

Мммм… Функционално

През последните няколко месеца имах малко функционален ритъм и наистина харесвам начина, по който по-функционалният подход ми помогна да разсъждавам и да подобря кода си. Няма да навлизам в дълъг спор за това защо функционалното програмиране има значение - което случайно е името на известен документ за CS, който е много по-полезен по темата; намерете го тук.

Достатъчно е да се каже, че обикновено позволява на разработчиците да разсъждават по-добре чрез системи, които не непременно трябва да въвеждат цялото променливо състояние, което често се въвежда (което не означава, че никога няма време за променливо състояние , просто го използваме твърде често). Например:

var i, result = []; for (i = 0; i < someArray.length; i++) { var someThing = someArray[i]; if (someThing.isAwesome === true) { result.push(someArray[i]); } }

Доста ясно, нали? Виждам такива неща през цялото време. И в много случаи използването на цикли е напълно приемливо. Например, прилагането на алгоритъм за сортиране чрез вмъкване обикновено изисква да използваме някаква комбинация от вложени цикли. В по-голямата си част обаче наистина нямаме абсолютна необходимост да въведем всички тези променливи. И след като започнем да се занимаваме с изискванията за асинхронизация и потенциала за ада на обратното извикване, цялото това състояние може да стане трудно за проследяване.

Това е особено вярно, когато влезете в наистина сложно приложение и не просто преминавате през някакъв наистина прост масив. Можете да използвате страхотна функционална библиотека като lodash, за да направите нещо като:

var result = _.filter(someArray, function(someThing) { 
    return someThing.isAwesome === true; 
})

Но можете също (и вероятно трябва) да използвате някои от вградените функции, които JavaScript има:

// returns an array of things that passed a test function 
var result = foo.filter(someArray, function(someThing) { return someThing.isAwesome === true; }); 
// returns a new array that you did stuff to var result = foo.map(someArray, function(someThing) { return someThing.isAwesome(); }); 
// calls a function on every item in an array var result = foo.forEach(someArray, function(someThing) { return ~~someThing; }); 
// Applies a function against an accumulator and each value of the array has to reduce it to a single value. 
var result = foo.reduce(someArray, function(someThing, anotherSomething) {      
     return someThing + anotherSomething;  
});

За други случаи на употреба lodash и подчертаването на предшественика му могат да ви дадат по-забавни методи за игра. Отидете на npm, инсталирайте ги. Според моя опит, когато направите всичко по силите си, за да премахнете състояние, където е подходящо и възможно, ще завършите и ще погледнете кода си и ще бъдете като...

Сложност || Простота

Освен обикновеното намаляване на размера на вашия код, има още един аспект за поддържане на функционалността на нещата, който трябва да имате предвид: сложността. Проследяването на състоянието всъщност е много сложно нещо, както за нас, така и за машината. Това не означава, че непременно е трудно (особено не за машината, която всъщност не я интересува, докато не изчерпи паметта), а само че всъщност има много неща, които влизат в жизнения цикъл на променливото състояние. Разпределение, постоянство, настройка, получаване, проверка на типа и др. Искам да кажа, че дори в най-простия възможен цикъл for в JavaScript в крайна сметка въвеждате поне една допълнителна променлива, само за да се случи цикълът – това не се брои други видове проследяване, които сте настроили.

Наистина харесвам начина, по който Рич Хики описва сложността като „колко изкривено е едно нещо“. Това е страхотен начин да го опишем, защото напълно изоставя всяка представа за трудност, правилност или неправилност - това е просто структурен анализ. Това е страхотно, защото не само задоволява прекрасната бръснач на Окам, но може да ви помогне в нещо като преглед на код → не е „Вашият код е нечетлив и ужасен“, а „кодът ви е прекалено сложен и може да бъде радикално опростен“; нещата могат да бъдат по-фокусирани и по-малко лични.

И без значение колко брилянтен може да е даден разработчик, има основни ограничения на човешкия мозък, с които ще се сблъска. Можете да запомните само толкова много методи, имена на променливи и структури наведнъж и вашата краткосрочна памет е много по-ограничена при проследяване на нещата (7±2 неща във всеки един момент).

Защо не опростите нещата и не избегнете основните ограничения, с които всеки разработчик ще се сблъска? Можете дори да използвате това като фактор при преценката кога и как да преработите. Другият аспект на сложността на битката е, че в крайна сметка те прави по-наистина гъвкав. Доста лесно е да вземете копие на frameworkX, но какво ще кажете, когато спецификациите се променят и нямате нужда от frameworkX или нуждите ви надхвърлят то? Или по-лошо, какво ще стане, ако свалите frameworkX до едно нещо, когато може да направи 1000?*кашлица jquery кашлица*. Всеки може да извади frameworkX — много по-трудно е да се създаде нещо просто и елегантно. Истинската простота е най-трудната работа, но работата с възможно най-голяма печалба. Нека приключим с някои добрини на Rich Hickey:

„Простотата е трудна работа. Но има огромна печалба. Човекът, който има наистина по-проста система - система, съставена от наистина прости части, ще може да повлияе на най-голямата промяна с най-малко работа. Той ще ви срита задника. Той ще прекарва повече време в опростяване на нещата отпред и в дългосрочен план ще избърше табелата с вас, защото ще има тази способност да променя нещата, когато вие се мъчите да бутате слонове наоколо. Богат Хики

ДА.

Неща за гледане/използване/научаване:

Страхотни неща, които можете да създадете:

Страхотен разговор от конференцията @scale за това как функционалното реактивно програмиране се използва в Netflix за радикално опростяване на асинхронните проблеми:

Първоначално публикувано в ifelse.io на 27 януари 2015 г.