Existe-t-il des arguments objectifs et supportables en ingénierie logicielle pour ou contre la modification des valeurs des paramètres par valeur dans le corps d'une fonction?
Un problème récurrent (surtout pour le plaisir) sur mon équipe est de savoir si les paramètres passés par valeur doivent être modifiés. Quelques membres de l'équipe sont convaincus que les paramètres ne doivent jamais être attribués, de sorte que la valeur initialement transmise à la fonction peut toujours être interrogée. Je ne suis pas d'accord et maintiens que les paramètres ne sont rien de plus que des variables locales initialisées par la syntaxe d'appel de la méthode; si la valeur d'origine d'un paramètre par valeur est importante, une variable locale peut être déclarée pour stocker explicitement cette valeur. Je ne suis pas sûr que chacun de nous soutienne très bien notre position.
S'agit-il d'un conflit religieux non résolu ou y a-t-il de bonnes raisons objectives d'ingénierie logicielle dans les deux sens?
Remarque: La question de principe demeure indépendamment des détails de mise en œuvre de la langue particulière. En JavaScript, par exemple, où la liste des arguments est toujours dynamique, les paramètres peuvent être considérés comme du sucre syntaxique pour l'initialisation de variable locale à partir de l' arguments
objet. Même ainsi, on pourrait traiter les identificateurs déclarés par paramètres comme "spéciaux" car ils captent toujours le passage d'informations de l'appelant à l'appelé.
la source
Réponses:
J'adopte une troisième position: les paramètres sont comme des variables locales: les deux doivent être traités comme immuables par défaut. Les variables sont donc attribuées une seule fois puis lues uniquement, et non modifiées. Dans le cas des boucles,
for each (x in ...)
la variable est immuable dans le contexte de chaque itération. Les raisons en sont:Face à une méthode avec un tas de variables qui sont affectées puis ne changent pas, je peux me concentrer sur la lecture du code, plutôt que d'essayer de me souvenir de la valeur actuelle de chacune de ces variables.
Face à cette même méthode, cette fois avec moins de variables, mais qui changent tout le temps de valeur, je dois maintenant me souvenir de l'état actuel de ces variables, ainsi que travailler sur ce que fait le code.
D'après mon expérience, le premier est beaucoup plus facile pour mon pauvre cerveau. D'autres gens plus intelligents que moi n'ont peut-être pas ce problème, mais cela m'aide.
Quant à l'autre point:
contre
Exemples artificiels, mais à mon avis, il est beaucoup plus clair de savoir ce qui se passe dans le deuxième exemple en raison des noms de variables: ils transmettent beaucoup plus d'informations au lecteur que cette masse de données
r
dans le premier exemple.la source
for
boucles avec des variables immuables. Encapsuler la variable dans la fonction ne vous suffit pas? Si vous rencontrez des difficultés à suivre vos variables dans une simple fonction, vos fonctions sont peut-être trop longues.for (const auto thing : things)
est une boucle for, et la variable qu'elle introduit est (localement) immuable.for i, thing in enumerate(things):
ne mute pas non plus les habitantsC'est une chose que j'aime vraiment en C ++ (bien écrit): vous pouvez voir à quoi vous attendre.
const string& x1
est une référence constante,string x2
est une copie etconst string x3
est une copie constante. Je sais ce qui se passera dans la fonction.x2
sera modifié, car s'il ne l'était pas, il n'y aurait aucune raison de le rendre non constant.Donc, si vous avez un langage qui le permet , déclarez ce que vous allez faire avec les paramètres. Cela devrait être le meilleur choix pour toutes les personnes impliquées.
Si votre langue ne le permet pas, je crains qu'il n'y ait pas de solution miracle. Les deux sont possibles. La seule ligne directrice est le principe de la moindre surprise. Adoptez une approche et suivez-la dans toute votre base de code, ne la mélangez pas.
la source
int f(const T x)
etint f(T x)
ne sont différents que dans le corps fonctionnel.const int x
juste pour clarifier x n'est pas modifiée à l'intérieur? Cela ressemble à un style très étrange pour moi.const
supprimerait simplement la liste des paramètres si cela le gêne. Je ne pense donc pas que cela réponde à la question.Oui, c'est un "conflit religieux", sauf que Dieu ne lit pas les programmes (pour autant que je sache), donc il est déclassé en un conflit de lisibilité qui devient une question de jugement personnel. Et je l'ai certainement fait et vu fait dans les deux sens. Par exemple,
Donc ici, juste à cause du nom de l'argument t0 , je choisirais probablement de ne pas changer sa valeur. Mais supposons plutôt que nous ayons simplement changé le nom de cet argument en tNow , ou quelque chose comme ça. Ensuite, j'avais oublié plus que probablement une copie locale et j'écrivais simplement tNow + = dt; pour cette dernière déclaration.
Mais au contraire, supposons que je savais que le client pour lequel le programme a été écrit est sur le point d'embaucher de nouveaux programmeurs avec très peu d'expérience, qui liraient et travailleraient sur ce code. Ensuite, je craindrais probablement de les confondre avec la valeur par rapport à la référence, tandis que leurs esprits sont 100% occupés à essayer de digérer toute la logique métier. Donc, dans ce genre de cas, je déclare toujours une copie locale de tout argument qui sera modifié, qu'il soit plus ou moins lisible pour moi.
Les réponses à ces types de questions de style émergent avec l'expérience et ont rarement une réponse religieuse canonique. Quiconque pense qu'il y a une et une seule réponse (et qu'il le sait :) a probablement besoin de plus d'expérience.
la source