2 votes

Quand modifier une fonction ou quand en écrire une nouvelle... ?

/est n00b

Grâce au don de connaissances et d'expertise encodé ici, je fais de mon mieux pour éviter les erreurs de n00b alors que j'apprends les bases de la programmation.

J'utilise les fonctions lorsque je (pense) pouvoir le faire en PHP, et je les classe dans différents includes.

Le problème que je rencontre actuellement est celui des situations où les 4/5e d'une fonction existante répondent à un nouveau besoin. Il y a peut-être un ensemble d'entrées légèrement différent, ou un ou deux calculs supplémentaires dans la série, ou la sortie a besoin d'un format/structure différent... mais le cœur de la fonction est toujours applicable.

Existe-t-il une règle empirique permettant de déterminer quand il faut ajouter des éléments à une fonction originale et quand il faut (littéralement) copier et coller la plus grande partie de cette fonction dans une nouvelle fonction et l'adapter à la situation ?

D'une part, je me sens mal de dupliquer du code, d'autre part, je me sens mal d'encombrer une fonction existante avec des éléments qui ne sont pas toujours nécessaires...

5voto

Thomas Points 63635

Une bonne règle est de ne jamais faire de copier-coller.

Si les 4/5e des fonctions A et B sont identiques, divisez-les. Demandez-leur d'appeler toutes deux une nouvelle fonction C qui implémente la partie commune.

Si vous nous montrez le code dans lequel vous rencontrez ce problème, nous pourrons vous suggérer la meilleure façon de le diviser.

0voto

MadMurf Points 1529

Je suis d'accord avec @Thomas à condition qu'avant de séparer les éléments communs dans une nouvelle fonction que votre nouvelle fonction et l'ancienne fonction modifiée invoquent, vous devez faire une analyse d'impact.

Votre chef de projet, votre équipe de test et votre client ne vous remercieront pas si votre objectif de produire un code de qualité se fait au détriment de tests de régression importants sur des parties de l'application qui étaient auparavant hors du champ d'application.

Dans ces cas où le temps et l'argent manquent pour faire la "bonne" chose en matière de codage, je copierai et collerai à contrecœur ou écrirai une nouvelle fonction qui utilisera l'ancienne et compensera le 1/5e supplémentaire requis et l'entourera d'un commentaire.

>>>>>HACKCIDENT ZONE, 
>>>>>NEXT TIME THIS CODE IS CHANGED THE OPPORTUNITY SHOULD BE TAKEN TO CORRECT THIS HORROR
.....
.....
<<<<END OF HACKCIDENT ZONE - move on nothing more to see here

Ce n'est pas l'idéal, mais cela me permet de me sentir un peu mieux dans ma peau...

0voto

Johannes Rudolph Points 19845

Pourquoi vos fonctions font-elles les 4/5 du même travail ? Il est clair que vous ne disposez pas d'une bonne abstraction et d'une bonne séparation des responsabilités.

Une fonction doit toujours faire une chose, la faire correctement et la faire bien. Prenons l'exemple d'une fonction Average qui calcule la moyenne d'un tableau d'entiers. Une implémentation naïve additionnerait tous les éléments et les diviserait ensuite par le nombre d'éléments. Cette division a cependant un problème : elle sait comment additionner un tableau d'entiers. Cela viole la contrainte ci-dessus. Une meilleure implémentation consisterait à séparer la fonction Sum() de Average() et à faire en sorte que Average() utilise Sum() pour obtenir la somme d'un tableau d'entiers. L'expression "une fonction ne doit faire qu'une seule chose" peut se résumer ainsi : "une fonction ne doit savoir faire qu'une seule chose. Pour tout le reste, elle peut s'appuyer sur d'autres abstractions (par exemple, les fonctions)".

Quels sont les avantages d'une abstraction claire et d'une séparation des responsabilités ?

  • Meilleure composabilité de votre code, il est plus facile d'écrire de nouvelles fonctions
  • Pas de codage par copier-coller, propageant un code potentiellement bogué dans toute votre base de code.
  • Meilleure lisibilité, le lecteur n'est pas distrait par des détails de mise en œuvre pour des choses qui ne sont pas directement liées à ce que la fonction doit faire.
  • Permet des optimisations transparentes des performances

0voto

lane Points 724

Pensez SEC ou MEURTE -- Ne vous répétez pas et la duplication est diabolique !

Répartissez vos fonctions. Si vous copiez les 4/5 d'une fonction dans 5 fonctions différentes réparties dans 5 fichiers différents et que vous découvrez un bogue dans l'une d'entre elles, il y a de fortes chances que vous oubliiez de mettre à jour au moins l'une d'entre elles.

0voto

Josiah Points 1284

Il ne s'agit pas de savoir quel code de la fonction est identique, mais quel est l'objectif de la fonction, et s'il correspond à l'objectif de la fonction que vous essayez de créer.

Imaginez que vous ayez une fonction qui compte les widgets :

function count_widgets($widgets)
{
    // Counting functionality
}

et vous avez besoin d'une nouvelle fonction qui compte les whatsits, mais qui partage la fonctionnalité. Vous pourriez créer une fonction qui compte les widgets ou les whatsits :

function count_widgets_or_whatsits($thing)
{
   if( $thing instanceof Whatsit )
   {
     // Special whatsit stuff
   }
   // Counting functionality
}

Mais cela briserait la contrat de la fonction. Au lieu de cela, vous devriez créer une nouvelle fonction et en extraire la fonctionnalité commune :

function count_widgets($widgets)
{
    return count_things($widgets);
}

function count whatsits($whatsits)
{
    // Special whatsit stuff
    return count_things($widgets);
}

function count_things($things)
{
   // Counting functionality
}

Il s'agit de :

  1. Rendez votre code plus lisible pour quelqu'un d'autre. (Quelqu'un peut facilement deviner que count_whatsits() comptera les watsits)
  2. Fournit un solide contrat entre ce que l'on appelle et ce qui se passe. Si le processus de comptage des whatsits change, il suffit de modifier le paramètre count_whatsits() sans affecter la manière dont les widgets sont comptés.
  3. Vous épargnez des heures de problèmes de maintenance lorsque vous changez quelque chose qui affecte quelque chose d'autre.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X