SnowCode

L'importance des tests unitaires et conseils d'optimisation

Pendant les vacances ici pendant deux semaines, j'ai passé mon temps sur le projet de math pour mes cours. Le projet de math consiste à implémenter trois algorithmes en Java, un pour identifier les ensembles de sommets d'un graphe connecté, un autre pour la coloration des sommets d'un graphe, et un dernier qui met ensemble les deux pour colorer les zones d'une image (comme d'une carte par exemple).

Et j'ai beaucoup galérer à optimiser les choses à partir d'un certain point par ce que j'avais commencé à implémenter des collections custom (comme une Fibonacci Heap ou une Bucket Queue améliorée) mais j'ai retenus quelques choses importantes à propos de cette expérience :

Pour optimiser un programme (Java en particulier), mes conseils sont :

  • Toujours préférer les types primitifs (tel que int, string, [], etc) aux collections et aux classes (ArrayList, HashMap, Integer, etc)
  • Souvent il vaut mieux faire des compromis sur la performance par rapport à la facilité d'implémentation car ce n'est pas par ce que l'on passe beaucoup de temps à implémenter une collection compliquée qu'elle en sera meilleure
  • Faire très attention à la complexité temporelle (et aussi un peu spaciale) des implémentations et des opérations sur les collections
  • Faire du TDD est très très TRÈS utile pour implémenter des algorithmes sans risquer de passer milles ans à debugger des problèmes

Faire du TDD

Le TDD ou Test-Driven Developpement, est une méthodologie d'Extreme Programming qui permet de créer des programmes fiables et propres tout en étant plus serain et confiant lors de l'implémentation.

Le processus va comme suivi :

  1. Pour un but donné, lister différents cas de tests (cas d'erreurs tel que l'absence de valeur, argument invalide, cas alternatifs, cas typique, différentes opérations dans différents ordres, etc). Une description est typiquement décrite comme "Étant donné {situation}, quand {action} alors {conséquences}"i
  2. Ecrire le squelette de la/les classe(s) avec les méthodes publiques et la documentation
  3. Choisir un test de la liste, celui le plus basique et simple et l'écrire et s'assurer que celui-ci rate
  4. Implémenter la solution minimale qui peut satisfaire ce test de façon à maximiser le coverage
  5. Recommencer à l'étape 3 jusqu'a ce que tous les cas de tests soit satisfaits
  6. Tester en conditions réelles, si il y a des bugs, tenter de savoir pourquoi et les reproduire en test et ainsi recommencer à l'étape 3
  7. Enregistrer les changements (commit) et refactor la classe de façon à rendre le code plus propre (éviter la duplication, les méthodes trop longues, les classes trop longues, l'intendation trop grande, etc) et toujours s'assurer que les tests passent toujours.