Código espagueti vs no espagueti

Ejemplo práctico de mejora de código en Javascript

Espagueti

Este es un ejemplo evidente de código espagueti. Simplemente leelo para experimentar por vos mismo las consecuencias:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
const people = [
  { name: 'John', age: 24 },
  { name: 'Jane', age: 10 },
  { name: 'BOB', age: 65 },
  { name: 'mary', age: 17 }
];

// Spaghetti code

function process(list) {
  table = {};
  for (let i = 0; i < people.length; i++) {
    table[people[i].name.charAt(0)] ||= 0;
    table[people[i].name.charAt(0)]++;
  }
  let max = 0, resini = undefined;
  for (let initial in table) {
    if (table[initial] > max) {
      max = table[initial];
      resini = initial;
    }
  }
  return resini;
}

for (let i = 0; i < people.length; i++) {
  if (people[i].age < 18) {
    people[i].young = true;
  } else {
    people[i].young = false;
  }
  people[i].name = people[i].name.toLowerCase();
}
let ini = process(people);

console.log(ini);
console.log(people);

No espagueti

Ahora veremos la reproducción exacta de la funcionalidad anterior pero escrita siguiendo buenas prácticas y estructurando bien el código:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
const people = [
  { name: 'John', age: 24 },
  { name: 'Jane', age: 10 },
  { name: 'BOB', age: 65 },
  { name: 'mary', age: 17 }
];

// Non-spaghetti code

function setYouth(person) {
  person.young = person.age < 18;
  return person;
}

function normalizeName(person) {
  person.name = person.name.toLowerCase();
  return person;
}

function getPersonInitial(person) {
  return person.name.charAt(0);
}

function incrementInitial(context, initial) {
  context.acc[initial]||=0;
  context.acc[initial]++;
}

function trackMaxInitial(context, initial) {
  if (context.acc[initial] > context.maximum) {
    context.maximum = context.acc[initial];
    context.initial = initial;
  }
}

function initialCounterReducer(context, person) {
  const initial = getPersonInitial(person);
  incrementInitial(context, initial);
  trackMaxInitial(context, initial);
  return context;
}

const context = { acc: {}, maximum: 0 };
const peopleFixed = people.map(setYouth).map(normalizeName);
const initial = peopleFixed.reduce(initialCounterReducer, context).initial;

console.log(initial);
console.log(peopleFixed);

El proceso de refactorización consistió en extraer unidades lógica de procesamiento en funciones con nombres descriptivos. Se puede apreciar que el código en el cuerpo de estas funciones es mayormente idéntico al del código original.

Luego en dos líneas se puede obtener el resultado buscado utilizando un estilo declarativo aunque no realmente immutable.