Con l’inizio dell’anno nuovo ho ripreso in mano Construct 3. Il mio buon proposito è di rilasciare un template ogni 15 giorni, circa. Però mi sono accorto di alcuni limiti, miei, della mia conoscenza di JavaScript, de del mio codice. Non sempre (eufemismo per mai!) il mio codice è facilmente leggibile e interpretabile. Ho deciso, quindi, di seguire il più possibile i consigli del libro che mi regalato la Iaia (Clean Code).
Uno dei consigli recita di non usare if/else oppure switch/case. Fosse facile, dico io.
Polimorfismo
Cercando in rete ho trovato alcun approcci. Il primo su un repository di frappacchio consiglia di sfruttare il polimorfismo:
Da evitare
const handleShape = (shape) => { console.log(shape.area()); }
class Shape {
constructor(type = "Circle", width = 2)
{
this.type = type;
this.width = width;
}
area() {
switch (this.type) {
case 'Square':
return this.width ** 2;
case 'Circle':
return Math.PI * (this.width / 2) ** 2;
default:
return 0;
}
}
}
const shape = new Shape("Square");
handleShape(shape);
Bene
const handleShape = (shape) => { console.log(shape.area()); }
class Shape {
constructor(width = 2) { this.width = width; }
area() { return 0; }
}
class Square extends Shape {
area() { return this.width ** 2; }
}
class Circle extends Shape {
area() { return Math.PI * (this.width / 2) ** 2; }
}
const shape = new Square();
handleShape(shape);
Matched & Match
Il secondo metodo, invece, l’ho trovato riportato da Hajime Yamasaki Vukelic su coderburst.io. In pratica prevede di implementare le funzioni match
e matched
const matched = x => ({
on: () => matched(x),
otherwise: () => x,
})
const match = x => ({
on: (pred, fn) => (pred(x) ? matched(fn(x)) : match(x)),
otherwise: fn => fn(x),
})
E poi implementare lo switch in una forma del tipo:
const handleShape = (shape) => { console.log(area(shape)); };
function area (type = "Circle", width = 2) {
return match(type)
.on(type => type === "Circle", () => Math.PI * (width / 2) ** 2)
.on(type => type === "Square", () => width ** 2)
.otherwise(type => () => 0);
};
handleShape("Square");
Jump Table
Il terzo approccio, presentato da Jamie Bullock sfrutta la possibilità di chiamare una funzione partendo da una jump table
:
const circle = (width = 2 ) => Math.PI * (width / 2) ** 2;
const square = (width = 2 ) => width ** 2;
const handleShape =
{
'Circle' : circle,
'Square' : square
};
const shape = "Square";
handleShape[shape]();
Personalmente non ho ancora capito quale metodo preferisco. Anche perché ognuno è adatto a un contesto diverso.