Skip to content

Functional Programming

Deanna Bosschert edited this page Nov 7, 2020 · 8 revisions

Functional programming

TL;DR: je houdt je variabelen binnen de functies, cluttered daarmee niet de global scope en zorgt er zo voor dat je code alleen bestaat uit blokken die al geprocessede info eruit yeeten.

= minder spaghetticode.

= minder 'onopvallende invloeden op andere stukken code'.

= minder bugs.

In a Nutshell

Currying

Het deels invullen van een formule zodat je β€˜m later volledig kan invullen (β€”> re-usable)

  • Bij declareren variabele: unbound
  • Bij gebruiken variabele (invullen): bound.

Object-oriented programming

Was top om zo met meerdere programmeurs samen te kunnen werken aan een programma.
Werd alleen steeds minder efficient naarmate de applicatie groter wordt.

Functional daarentegen:

β€’ Bugproof
β€’ Geautomatiseerd testen
β€’ Maakt gebruik van recursie
β€’ inFInItEloOps
β€’ Er bestaat geen state
β€’ Kost dan ook geen werkgeheugen (behalve bij het parsen)
β€’ Bij page refresh moet de hele f*****g structuur weer worden doorlopen bij OOP
β€’ Als je programma klaar is, is het klaar.
β€’ Functies doen in principe maar 1 ding en da's herbruikbaar
β€’ Doet niets buiten hun eigen scope
β€’ Makkelijk te begrijpen wat er gebeurt
β€’ Soort fabrieksstraat;lopendebandwerk waarbij elk machientje een functie is

Procedural programming

β€’ Zie je code als een soort boom die afgelopen wordt
β€’ Genereerde output dmv doorlopen van die boomstructuur
β€’ Blockscopes
--> functies aanroepen

Imperative: go-to statements (lineair je code doorlopen)

Wat mag wel?

β€’ Anonieme functies (middels arrowfunctions)
β€’ Functies hebben maximaal 1 argument en maximaal 1 returnwaarde(~argumentarray:return arguments) (unary function) β€’ Oneliners

MaakUser()      
MaakNaam()       
MaakGeboortejaar()      
MaakEmailadres()      
CheckEmailadres()      

Pure en impure functies

Impure:

function magSpelen(leeftijd) {
  return leeftijd >= PEGI
} 

(pakt externe data)

Pure:

function makeAdder(a) {
  return function (b) {
    return a + b
  }
}
const add42 = makeAdder(42)
Console.log(add42(4))

Higher-order functions

Dit is een functional pattern waarbij je een een functie als variabele gebruikt (en ook direct kan returnen). Als je bijv over een array heen mapt en daar een transformatie op loslaat, hoef je niet eerst iets te doen als

function removeWhitespace(data, variable) {
  const getrimdeVariabele = data.map((item) => {
    const trimmed = item[variabele].trim()
    return {[variable]: trimmed}
  })
  return getrimdeVariabele
}

maar kun je dat gewoon als volgt doen:

function removeWhitespace(data, variable) {
  return data.map((item) => {
    return {[variable]: item[variable].trim()}
  })
}

Immutability

Eigenlijk wil je niet continu de originele databron/input aanpassen, maar een nieuwe gemuteerde output geven. Als ik bijv een array met objecten heb:

const people = [
{
 naam: "Jan",
 mood: "boos"
},
{
 naam: "Nadie",
 mood: "blij"
},
{
 naam: "Levi",
 mood: "sad"
}
]

en daaraan de leeftijd wil toevoegen, dan wil ik niet die specifieke array editten. Ik wil dan de array gewoon aanroepen, deze modificeren door leeftijd te adden en vervolgens die array met naam+leeftijd+mood als nieuwe array hebben.

Interesting takes

Vanaf nu heten IIFE’s dog’s balls

β€”> runt 1 keer, valt daarna weg en valt niet meer te manipuleren

  • J. Sturkenboom

"Gooi anders ook eens Object.freeze om je functie heen en zie waar je fout zit."

Elk programma dat je schrijft is niet meer dan .map, .filter en .reduce
Schrijf eerst je filter;
β€’ Filter bijv wachtwoorden eruit
β€’ Map de achtergebleven gegevens naar een html-representatie
β€’ Reduce de output naar de browser als whateverweergave

Deze is mooi: https://medium.com/poka-techblog/simplify-your-javascript-use-map-reduce-and-filter-bd02c593cc2d

Je kunt beter lege items niet zomaar eruit jassen, maar opvullen (- Danny)

Hoe heb ik dit toegepast?

(en wat zou ik nog kunnen refactoren)
Ik heb zo veel mogelijk m'n filterfuncties opgedeeld in modules; zo bleef ik met steeds kleinere functies over.
De data wordt per kolom middels promise chaining in 1 file gedaan om zo alles goed gescheiden te houden.
Daarnaast heb ik geen global variables gebruikt, en gebruik ik alleen een soort for-loop binnen eleventy.

Momenteel geef ik wel twee variabelen mee; de input, en bijbehorende variabele/columnnaam. Dit kan ik tackelen door de columnnaam gewoon in de data te verwerken/de naam daaruit te halen. Heb ik alleen geen tijd meer voor gehad, en is niet extreem vuil als ik het laat zoals het is.

Verder ben ik in iedere functie eerst over de data aan het mappen; da's echt totaal niet functional en zou ik waarschijnlijk op kunnen lossen door in het begin van m'n promise chain te loopen en daarin door te gaan. Ook kan ik meer met arrowfunctions werken zodat ik niet continu returnreturnreturn gooi.

Ik ben/was wel van plan om alles verder door te refactoren waarbij ik oa dat fix, en uitkom op de filterfuncties van maar 1 input, en da's aangegeven in de code.

πŸ“‹ Project

πŸ—“ Logboek

🧹 Data cleaning

πŸ“‹ Surveydata

βš™πŸ“ Documentatie

πŸ–ŠοΈ Notes

πŸ“ˆ Evaluatie

Clone this wiki locally