Optimisation

L’optimisation en informatique est quelque chose de crucial ! Mais on n’y pense pas toujours.
On nous dit et répète qu’il ne faut pas faire d’optimisation avant que le programme fonctionne complètement et répond aux spécifications fonctionnelles. Puis, une fois que le programme fonctionne, comme on est souvent pressé par le temps dans le monde de l’entreprise, la phase de réfactoring et d’optimisation ne sera pas faite…

Prennons un exemple de ce qui peut arriver. Nous allons faire une petite application de gestion des salaires des employés de toutes les SSII françaises.

Cas d’utilisation n°1 : Pour une année donnée, je veux afficher le salaire d’un employé.

Ok, ok, je me lance, je crée une classe Employe qui va contenir la logique du calcul du salaire d’un employé.

  1. public class Employe {
  2.    …
  3.    public Double calculerSalaireAnnuel(int annee) {
  4.         // faire une requete SQL pour aller chercher le salaire
  5.         // de cet employé pour l'année demandée
  6.         return salaire;
  7.    }
  8. }

Cas d’utilisation n°2 : Pour une année donnée, je veux afficher la masse salariale d’une entreprise

C’est facile, il suffit de créer une classe Entreprise. Elle aura la liste de tous ses employés et comme nous avons déjà fait le travail une fois, nous appelerons la méthode calculerSalaireAnnuel que nous venons de faire pour chacun de ses employés.

  1. public class Entreprise {
  2.     private List<Employe> employes;
  3.     …
  4.     private void chargerListeEmploye() {
  5.           this.employes = … ; // appel à la couche service pour charger la liste d'employés
  6.     }
  7.  
  8.     public Double calculerMasseSalariale(int annee) {
  9.           chargerListeEmploye();
  10.  
  11.           Double masseSal = 0.0;
  12.           for(Employe e : employes) {
  13.                   masseSal += e.calculerSalaireAnnuel( annee );
  14.           }
  15.           return masseSal;
  16.     }
  17. }

Cas d’utilisation n°3 : Pour une année donnée, je veux afficher la masse salariale de toutes les entreprises

Donc je veux itérer sur toutes les entreprises connues de mon application et afficher dans un tableau les masses salariales de chacune.
Là encore, je récupère la liste des entreprises et je parcours la liste pour appeler calculerMasseSalariale.
(je vous fais grâce du code)

Ca marche ! Peut-être, mais il faut jeter !

Fonctionnellement, ce programme va marcher. Il répond aux spécifications. Vous avez même fait des tests unitaires pour tester chacune de vos méthodes, super !
Mais on oublie vite que la méthode initiale calculerSalaireAnnuel fait une requête SQL à chaque appel.

Si nous avons 10 entreprises, que chaque entreprise possède 100 employés, l’affichage de la liste des masses salariales des entreprises nous oblige à faire :

  • 1 requête pour récupérer la liste des entreprises
  • pour chaque entreprise, 1 requête pour charger la liste des employés
  • pour chaque employé, 1 requête pour calculer le salaire annuel

Soit : 1 + 10 + 10 * 100 = 1011 requêtes !

Et ce qu’on oublie aussi, c’est que nous sommes en environnement de développement. En production ce ne sera pas 10 entreprises mais peut être 1000 ou plus et que chaque entreprise aura beaucoup plus que 100 employés ! Vous imaginez alors le nombre de requêtes SQL nécessaire à l’affichage de votre page de synthèse ? A chaque fois que l’utilisateur cliquera sur le bouton, il aura le temps d’aller prendre un café avant d’avoir son rapport.

La solution ? Optimiser

Dans le cas d’utilisation n°2, il faudrait réécrire la méthode calculerMasseSalariale pour qu’elle n’ait plus besoin de charger la liste des employés et n’ait plus besoin de parcourir cette liste pour appeler calculerSalaireAnnuel : une seule requête SQL avec des jointures et une somme devrait faire l’affaire.

Dans le cas d’utilisation n°3, il faudrait réécrire la méthode pour qu’elle ne fasse qu’une seule et unique requête : des jointures, une somme, un group by.

Et là, pouf comme par magie, le rapport devrait s’afficher en un rien de temps !

La programmation objet c’est bien, il ne faut pas réinventer la roue, si vous avez déjà codé quelque chose qui marche, il faut le réutiliser. (Le copier coller c’est mal). Mais lorsqu’on écrit un algorithme complexe, il faut toujours garder à l’esprit que ce que nous faisons doit servir un utilisateur final. Cet utilisateur passera ses journées devant nos écrans, et il aura bien autre chose à faire que de prendre des pauses cafés toute la journée. Alors pensez à optimiser votre code !

Surtout que ça sera bénéfique pour vous aussi, si il y a une anomalie sur cet écran, vous serez obligé de l’afficher pour constater l’anomalie et vous aussi aurez le temps d’aller boire des litres de café ! Puis de l’afficher encore et encore jusqu’à avoir corriger complétement cette anomalie.

Le commentaires sont fermés.