Deux, c’est bien, mais un, c’est mieux!
Un petit article sur un détail important mais qui, je crois, n’a pas été beaucoup discuté; le nombre d’appels sur des objets dans une ligne de code.
Prenons par exemple la ligne de code suivante, ou employe est un paramètre de méthode:
int assignements = employe.GetHoraire().GetAssigments(this.jourEnCours).Length;
Elle peut paraître exagérée pour certains, mais elle représente plusieurs cas que j’ai vu et que j’ai fait. Beaucoup auront prévu le coup; en production l’erreur suivante est lancée:
Object reference not set to an instance of an object.
*musique dramatique* béât devant son courriel d’erreur (car bien sûr le programmeur fautif s’est sagement envoyé le stack trace ainsi que le nom de l’utilisateur connecté, la page visualisée et la date). On a deux cas possible:
1) Le code était en mode Release
Étendu sur une ligne ou sur huit, on a pas la ligne de code de toute façon, alors les bonnes pratiques font “ding”: toujours vérifier si les valeurs attendues sont nulles! Quoique ce n’est pas toujours facile lorsqu’on va chercher un sous-sous-sous-sous objet. Morale: éviter de traîner de trop grosses structures (pas toujours facile).
2) Le code était en mode Debug (oublions que c’était en production)
C’est la que cet article dit ce qu’il a à dire: on a la ligne de code (après tout on s’attend à avoir des bogues, sinon on ne serait pas en mode debug) et on est prêts à… oh non. On a aucune idée de la variable qui est nulle! On a plusieurs choix ici.
– De l’instrumentation manuelle (peut-être fastidieux!)
– Des logiciels d’instrumentation automatique (tels qu’AVIcode, que je n’ai pas encore eu l’occasion d’essayer)
– Vérifier les valeurs nulles au début (bonne pratique!)
– Décomposer les appels complexes.
Ce dernier est une pratique simple et efficace. Pourquoi?
– Plus facile de faire “Next” en mode débug et suivre le monceau de code
– On a immédiatement la ligne de code dans le stack trace, et on sait automatiquement quel objet était nul
– Plus facilement lisible
– Possibilité d’insérer des conditions ou des appels supplémentaires sans avoir à décomposer le code
– On visualise plus facilement et rapidement les types auxquels on a affaire. Ça force aussi l’utilisation du “using”. De cette manière, on peut plus facilement voir quels sont les modules réellements impliqués dans une classe.
– Le nombre de lignes de code est plus représentatif de l’application
Si on reprend l’exemple de tout à l’heure, on a:
Horaire h = employe.GetHoraire();
Assignement[] as = h.GetAssignements(this.jourEnCours);
int assignements = ((as==null)?0:as.Length);
Il devient aisé d’insérer les vérifications d’objets nuls à mesure, et le tout est plus lisible.
Les cons pouvant survenir sont surtout la performance (une référence est créée et conservée), quoique selon moi complètement transparente (à vérifier avec un profiler), et la longueur du code. Il s’agira ici de simplifier le code si on voir qu’on doit décomposer des monstres!
En bref, décomposer les appels imbriqués est selon moi une pratique simple, facile à faire et très efficace. Utilisez là!