Unset my life
Publié le 2023-10-30 par DarkChyper
Un rapide billet pour parler d'un bug, à première vue totalement improbable, au bureau.
Le contexte est la gestion des jours de fractionnement d'un établissement public, dont les congés sont donc gérés de janvier à décembre. Pour rappel, un jour de fractionnement est accordé s'il y au moins 3 périodes de 5 jours de congés consécutifs sur la période de référence, et que les jours déposés sont bien comptabilisés dans la période de référence.
Par exemple, en 2023, si vous avez 5 jours consécutifs en mars 2023, en juin et septembe 2023, vous "gagnez" 1 jour de fractionnement (de congé quoi).
Par contre, si vous n'aviez pas soldé vos congés l'année précédente, il se peut que des congés de votre 1re période de 5 jours soient comptabilisés l'année précédente, et vous n'avez donc plus droit à ce congé de fractionnement. Je sais, c'est un peu compliqué, j'en viens au souci dans le code.
J'étais dans le cas indiqué précédemment et un congé de fractionnement étais tout de même accordé, à tort. Voici grossièrement comment fonctionne le code.
PHP<?php // periods est un tableau d'indice numérique et chaque case contient x jours de congés consécutfs $periods = retrieveConsecutivePeriods(); $fiteredPeriods = checkPeriodsWithMinimumDays($periods); // cette méthode renvoie la date à laquelle on acquiert le congé de fractionnement, null sinon $dayOfSplitting = getDayOfSplitting($fiteredPeriods); // si la variable n'est pas nulle le traitement se poursuit ?>
En testant un peu, tout fonctionne bien jusque dans la méthode getDayOfSplitting.
PHP<?php public function getDayOfSplitting(array $fiteredPeriods): int { if (isset($fiteredPeriods[2])) { // on fait le traitement // dans cet exemple j'ai mis en dur le 2 mais en vrai c'est une variable, qui dans mon cas, donnait 2 } } ?>
Le tableau passé en paramètre ne contenait que 2 éléments et pourtant, il trouve bien l'indice 2 (donc troisième élément du tableau) et réalise le traitement à tort. Si vous êtes un dev avec un peu d'expérience, vous vous doutez sûrement problème, il se situe dans la méthode checkPeriodsWithMinimumDays :
PHP<?php public function checkPeriodsWithMinimumDays(array periods) : array { foreach ($periods as $key => $period) { if (count($period) < 5) { unset($periods[$key]); // houuu ca c'est moche } } [...] } ?>
Le unset a bien supprimé l'élément de mon tableau, mais il n'a pas modifié les indices, donc on se retrouve avec des "trous" dans la suite de chiffres et pour peu que l'élément d'indice 2 persiste, le code produira un beau bug.
Je n'aime pas l'utilisation du unset dans une boucle pour cette raison, je préfère recréer un tableau qui doit contenir les valeurs à conserver, cela évite bien des erreurs :
PHP<?php $newTab = []; foreach ($periods as $key => $period) { if (count($period) >= 5) { $newTab[] = $period; } } [...] ?>`