-
Notifications
You must be signed in to change notification settings - Fork 0
Functional patterns
Ik heb alles opgesplitst in modules om onderstaande regel te kunnen handhaven. Werkt ook fijner en maakt alles re-usable.
Ik heb vanaf het moment dat ik ben gaan werken met modules, ernaar gestreefd om elke functie zo kort en beknopt mogelijk te maken. Later heb ik nog.
module.exports = function getData(datasource, variable) { // get data from questionnaire file
return new Promise((resolve, reject) => {
const colors = datasource.filter(item => ({
[variable]: item[variable]
}))
resolve(colors)
})ook omgezet naar twee functies getData en filterData:
require('dotenv').config()
const fetch = require("node-fetch") // i've placed those here because of readability
module.exports = function getData() { // get data from questionnaire file via secret gist
return fetch(process.env.QUESTIONNAIRE_URL)
.then(res => res.json())
}module.exports = function filterData(data, variable) { // filter data from questionnaire file
return data.filter(item => ({
[variable]: item[variable]
}))
}En ja, ik weet dat dat in principe ook prima anonieme functies kunnen zijn maar ik vond het fijner lezen/werken als ik zowel in de filename als in de functie zelf zie over wat het gaat en wat het doet.
Ik gebruik veelal arrow functions, dit houdt in dat ik bijv m'n code gerefactored heb van basically:
module.exports = async function (variable) {
try {
return cleanColors = await getData() // wait for data
.then(function(data) {
return filterData(data, variable) // filter usable data
})
.then(function(data) {
return removeWhitespace(data, variable) // remove whitespace
})
.then(function(trimmed) {
return addHash(trimmed, variable) // add hashtag
})
.then(function(withHash) {
return wordToHex(withHash, variable) // convert text to hex
})
.then(function(allColors) {
return rgbToHex(allColors, variable) // convert rgb to hex
})
.then(function(cleanHex) {
return toUpperCase(cleanHex, variable) // make uppercase
})
} catch (err) {
console.error(err)
}
}naar:
module.exports = async (variable) => {
try {
return cleanColors = await getData(questionnaire, variable) // wait for data
.then(data => removeWhitespace(data, variable)) // remove whitespace
.then(trimmed => addHash(trimmed, variable)) // add hashtag
.then(withHash => wordToHex(withHash, variable)) // convert text to hex
.then(allColors => rgbToHex(allColors, variable)) // convert rgb to hex
.then(cleanHEX => toUpperCase(cleanHEX, variable)) // make uppercase
} catch (err) {
console.error(err)
}
}Ik werk telkens alleen met 'datasource' en 'variable'; hiermee kan ik in principe de geschreven functies voor iedere kolom in de dataset gebruiken.
Ik had volgens de regels van procedural programming, graag '1 input 1 output' willen gebruiken maar dan zou ik de waarde van 'variable' bij iedere functie opnieuw uit de data moeten halen, wat weer voor overbodig veel code zou zorgen.
Ik maak hier ook veelvuldig gebruik van; het 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()}
})
}Ik kom op een aantal plaatsen in de wiki nogmaals terug op mijn gebruik van Functional Patterns; zie bijvoorbeeld deze paragraaf voor meer toepassingen.