Etat mutable et boucles. Vous n’avez presque jamais besoin d’eux, et vous obtenez presque toujours un meilleur code sans eux.
Par exemple, cela provient directement d'un thread StackOverflow:
// ECMAScript
var thing, things_by_type = {};
for (var i = 0; i < things.length; i++) {
thing = things[i];
if(things_by_type[thing.type]) {
things_by_type[thing.type].push(thing);
} else {
things_by_type[thing.type] = [thing];
}
}
# Ruby
things_by_type = {}
things.each do |thing|
(things_by_type[thing.type] ||= []) << thing
end
Ils font tous les deux la même chose. Mais je n'ai aucune idée de ce qu'ils font. Heureusement, la question explique en fait ce qu’ils font, alors j’ai pu les réécrire comme suit:
// ECMAScript
things.reduce(function (acc, thing) {
(acc[thing.type] || (acc[thing.type] = [])).push(thing);
return acc;
}, {});
# Ruby
things.group_by(&:type)
// Scala
things groupBy(_.type)
// C#
from thing in things group thing by thing.Type // or
things.GroupBy(thing => thing.Type);
Il n'y a pas de boucles et pas d'état mutable. Bon, d'accord, pas de boucles explicites ni de compteurs de boucles.
Le code est devenu beaucoup plus court, beaucoup plus simple, et ressemble beaucoup plus à une description de ce qu’il est censé faire (en particulier dans l’affaire Ruby, il est dit directement "grouper les choses par type"), et beaucoup moins sujet aux erreurs. Il n'y a pas de risque de fuite à la fin du tableau, d'erreurs poteau clôturé ou d'erreurs décalées avec les indices de boucle et les conditions de terminaison, car il n'y a pas d' indices de boucle et de conditions de terminaison.