Question

J'analysais mon code avec PHP Mess Detector lorsque PHPMD a signalé que certains de mes codes avaient une complexité NPath élevée.Un exemple serait:

function compareDates($date1, $date2){
    if($date->year < $date2->year){
        return -1;
    }
    if($date->year > $date2->year){
        return 1;
    }
    if($date->month < $date2->month){
        return -1;
    }
    if($date->month > $date2->month){
        return 1;
    }
    if($date->day < $date2->day){
        return -1;
    }
    if($date->day > $date2->day){
        return 1;
    }
    // etc.. same for hour, minute, second.
    return 0;
}

Le résultat serait que cette fonction a une complexité NPath très élevée.Existe-t-il une méthode générique de codage pour réduire ces structures de contrôle et la complexité de NPath?

Code source: http://code.google.com/p/phpraise/source/browse/trunk/phpraise/core/datetime/RaiseDateTime.php#546

Était-ce utile?

La solution

Votre code est en fait relativement simple, mais mal structuré. Je recommanderais de créer une sous-fonction qui prend deux paramètres et gère le retour de -1/1, puis l'itération dans un tableau de champs à vérifier, car ce serait un peu plus facile, mais quelques choses à noter:

  1. Votre chemin est OK. Ce n'est pas propre, mais c'est clair et si cela fonctionne, il n'est pas nécessaire de le changer - tout programmeur qui le regarde sera en mesure de comprendre ce que vous faites, même s'il se moque de votre implémentation.

  2. La complexité n'est pas un Saint Graal. C'est important, et en tant que programmeur qui fait beaucoup de programmation de maintenance, je pense qu'il est vraiment important que les personnes qui écrivent le code que je maintiens connaissent la complexité, mais vous ne pouvez pas éviter entièrement la complexité et parfois le complexe (utilisant la complexité de McCabe) est la plus facile à lire.

Le seul changement que je vous recommanderais vraiment de faire est d'avoir un seul retour d'appel. Faites quelque chose comme:

$compare_val = 0;

En haut de votre fichier, puis modifiez vos appels if ultérieurs à elseifs et au lieu de renvoyer la valeur, mettez simplement à jour $ compare_val et renvoyez-le à la fin de votre fonction.

Autres conseils

C'est une idée fausse courante que les fonctions de tri doivent renvoyer -1,0,1.Vous pouvez faire

function compareDates($date1, $date2)
{
    return strtotime("{$date1->year}-{$date1->month}-{$date1->day}")
         - strtotime("{$date2->year}-{$date2->month}-{$date2->day}");
}

Notez que si la limite d'entiers est un problème, vous pouvez utiliser DateTime, qui n'a pas cette limitation, par exemple

function compareDates($date1, $date2)
{
    return new DateTime("{$date1->year}-{$date1->month}-{$date1->day}")
         < new DateTime("{$date2->year}-{$date2->month}-{$date2->day}");
}

Quant à la réduction de la complexité NPath en général: vous devez réduire le nombre de chemins d'exécution possibles.Pour commencer, consultez le chapitre sur la Simplifying Conditional Expressions du livre Refactoring de Fowler.

En passant, je me demande quels sont les avantages de ce truc RaiseDateTime?Peut-il faire quelque chose que l'API DateTime native ne peut pas faire?Sinon, pourquoi voudrais-je l'utiliser?

Je suis nouveau dans PHP, ce code ne fait-il pas la même chose mais est-il simple?

function compareDates($date1, $date2){
if(($date->year < $date2->year) || ($date->month < $date2->month) || ($date->day < $date2->day) {
    return -1;
}
 if($date->year > $date2->year) || ($date->month > $date2->month) || ($date->day > $date2->day) {
    return 1;
}
// etc.. same for hour, minute, second.
return 0;
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top