Това е втората глава от поредица от статии за практическите парадигми на функционалното програмиране. Ако не сте чели предишните глави, можете да започнете от тук.

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

Какво означава неизменност? Дефиницията, която можете да видите в Wikipedia, гласи, че неизменен обект е този, чието състояние не може да бъде променено след създаването му. Или с други думи някаква променлива, която не може да промени стойността си.

Първият път, когато срещнах неизменността, прочетох определението повече от веднъж, за да се уверя, че съм го прочел правилно. Как мога да програмирам с променливи, които никога не променят стойностите си? За мен това беше невероятно контраинтуитивно.

В днешно време трябва да се фокусираме все повече и повече върху изживяването на разработчиците. С това имам предвид, че кодът трябва да бъде написан по такъв начин, че да бъде лесно разбран от следващия разработчик. И точно тук започва неизменността.

Колкото повече четях за функционалното програмиране, толкова повече разбирах, че това е действителната цел. Ако се замислите, хората пишат програми от доста време и солидна част от тях са написани по нефункционален начин.

Шансовете са, че ако сте уеб разработчик, ще срещнете повече програми, написани без използването на FP практики. Така че защо трябва да инвестирате време в изучаване на тази езотерична парадигма на програмиране?

Целта на функционалното програмиране е да ни позволи да мислим по-малко и да пишем повече описателен код.

Вероятно сте попадали в ситуация, в която сте проследявали променлива по редовете на JavaScript файл, отчаяно опитвайки се да намерите точния ред, на който тя се превръща в undefined.

Това имах предвид, когато казах, че FP ни позволява да мислим по-малко. Когато една променлива е дефинирана, тя получава някаква стойност и тази стойност никога няма да се промени. Месечен цикъл.

Това също ще намали продължителността на живота на вашите отделни променливи. Това е броят на редовете, в които се използва променлива от нейната декларация.

Подобно на това, което обсъждахме в предишната глава с чистите функции — няма да можете да оставите всички наши променливи неизменни и това е добре.

Функционалното програмиране не е нещо, което трябва да поставяте пред качеството на вашия код. Целта на FP е да ни помогне да напишем по-добър и по-чист код, така че ако вашият код ще бъде много по-чист и по-лесен за разбиране, ако промените променлива, така да бъде.

В останалата част от статията ще разгледаме как можем да приложим това на практика в модерни програми, написани с JavaScript.

Вие сте използвали неизменност

Когато говорим за неизменност, наблягаме твърде много на променливата страна на нещата. Как не трябва да преназначаваме стойности. Макар че всъщност трябва да обръщаме повече внимание на нашите функции и да ги пишем с мисъл за неизменността.

Целта на тази поредица от статии е да посочи как функционалните модели на програмиране се използват в. Всъщност вие сте срещали неизменност във вашето ежедневно JavaScript кодиране, но вероятно не сте му обръщали толкова много внимание. Нека разгледаме някои от вградените функции в езика.

Както можете да видите, тези функции не променят извикващия функцията. Всяка от тези функции връща изцяло нова стойност, без да променя обекта, на който са извикани. Същото поведение може да се наблюдава при много други функции в езика.

Първият път, когато се сблъсках с това, всъщност бях малко разочарован. Какъв беше смисълът да извикам тази функция на масив например, ако тя всъщност не променя масива, на който извиках я?! Винаги забравях това и това беше единствената цел за цял куп грешки в моите програми. Честно казано, отне ми повече време, отколкото би трябвало, за да разбера предимствата на този подход.

Декларативно срещу итеративно

Някои от най-основните алгоритми, които ще пишете като програмист, включват преминаване през данни и модифицирането им по някакъв начин. Може би искате да го филтрирате или да промените стойностите.

Ортодоксалният начин, на който всички ни учат, е да използваме цикли и да променяме обекти. В това няма нищо лошо, повечето хора така го правят и ще го правят още дълго време. Този подход се счита за задължителен. Като правим нещата по този начин, ние даваме на програмата изрични инструкции как да прави нещата, от които се нуждаем.

Функционалното програмиране от друга страна е предназначено да бъде декларативно. Какво означава това? Помните ли как вградените функции винаги връщат нов екземпляр? Това ни позволява да ги свържем с други подобни функции, за да правим това, което обикновено правим с цикли, но с много по-малко код.

Моментът, в който това щракна за мен, беше моментът, в който спрях да пиша цикли. Честно казано, не мога да си спомня последния път, когато написах цикъл в JavaScript. Използването на този модел ми помогна да напиша по-кратък, по-чист и по-добре структуриран код.

Разбира се, това е най-основният от основните примери, които ще видите навсякъде. Никой не пише програми за умножаване на числа, но въпросът е да разберете колко много работа могат да ви спестят FP и неизменността.

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

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

Всеки път, когато пишете цикъл, помислете дали ще разберете какво сте написали след година. Сега погледнете този код — без значение когато го погледнете, е доста ясно какво прави и в какъв ред го прави.

Нещо по-практично?

ако все още не сте убедени колко овластяваща може да бъде неизменността, нека насочим очите си към React. По-конкретно това е интеграция с Redux. Ако не сте запознати с Redux, може първо да прочетете малко за това.

Единственият източник на истина в приложенията на Redux е магазинът. Това е обект, който съдържа текущото състояние на вашето приложение и вашите компоненти ще черпят информация от него. Но състоянието на вашето приложение се променя през цялото време. Потребителите предприемат действия на вашата страница, които изискват постоянно да променяте потребителския си интерфейс.

Мантрата на Redux обаче е никога да не се променя състоянието! Вместо това във вашите редуктори винаги трябва да връщате нов обект, който да заеме мястото на предишното състояние.

В този пример добавяме списък с данни за времето към състоянието на приложението, така че те да могат да бъдат изброени от нашите компоненти. Забележете, че редукторът не просто задава свойство на състоянието, а вместо това връща изцяло нов обект. Предишното състояние се разгъва с помощта на оператора ... и новите свойства се добавят след това. По този начин те ще презапишат тези от обекта на текущото състояние.

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

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

Това обаче позволява една от най-мощните функции в разработката на Redux – отстраняване на грешки при пътуване във времето. Тъй като във всеки един момент състоянието на вашето приложение може да бъде наподобявано като обект с определени свойства, ако го разменим с друг обект, който се придържа към същия интерфейс, бихме могли напълно да променим потребителския интерфейс на нашето приложение.

Отстраняването на грешки при пътуване във времето ви позволява да следите всички предишни състояния на вашето приложение и бързо да променяте потребителския си интерфейс с едно щракване — то просто разменя обектите.

Имам

С въвеждането на ES6 получихме ключовата дума const. С него можем да създаваме променливи, на които не може да се присвоява друга стойност. Всъщност, ако инстанциирате променлива с помощта на const и след това се опитате да й дадете различна стойност, ще получите грешка.

Но нямаше да е JavaScript, ако нямаше нещо странно в това, нали? Дори и да не можете да промените изцяло стойността, пак можете да я промените.

Това е нещо, което трябва да имате предвид, когато работите с масиви. Не можете директно да променяте съдържанието на променливата, но можете да манипулирате нейното съдържание по този начин. За да избегнете ненужно главоболие, накарайте екипа си да се установи на променлива конвенция и да се придържа към нея.

Благодаря ви, ако прочетохте досега. Задръжте бутона за пляскане, ако сте намерили нещо интересно в тази статия!

Следва

След това ще разгледаме състава на функциите и ще обясним някои от по-сложните концепции за функционално програмиране, като къри и частично приложение. Останете на линия!