Une fonction peut-elle être trop courte?


125

Chaque fois que je me retrouve à écrire la même logique plusieurs fois, je la colle habituellement dans une fonction, de sorte qu'il n'y a qu'un seul endroit dans mon application où je dois conserver cette logique. Un effet secondaire est que je finis parfois avec une ou deux fonctions de ligne telles que:

function conditionMet(){
   return x == condition;
}

OU

function runCallback(callback){
   if($.isFunction(callback))
     callback();
}

Est-ce paresseux ou une mauvaise pratique? Je demande seulement parce que cela entraîne un plus grand nombre d'appels de fonction pour de tout petits morceaux de logique.


3
Non, pas trop court. En C #, je ferais «condition remplie» comme une propriété, qui est élégante, et envisagerait d'utiliser Assert.AreEqual<int>(expected, actual, message, arg1, arg2, arg3, ...);. Le second est bien tel quel. Je pourrais éventuellement inclure un drapeau bool optionnel qui dicterait s'il fallait lever une exception / etc. dans le cas où le rappel n'est pas une fonction.
Job

38
Oui, seulement dans un cas: function myFunction () {}
Spooks

5
def yes(): return 'yes'
dietbuddha

3
@Spooks - Je coupe les cheveux ici, mais les fonctions vides sont valables pour au moins les classes d'adaptateur, par exemple MouseMotionAdapter dans download.oracle.com/javase/6/docs/api/java/awt/event/… . Bien sûr, cela n’est qu’un moyen de contourner les limitations linguistiques.
Aleksi Yrttiaho le

3
@dietbuddha: La configuration requise vient de changer - il doit maintenant prendre en charge deux langues pour une démonstration la semaine prochaine. Le type qui a écrit "def yes ()" était très heureux de l'avoir remplacé par "def yes (: (IsFrench ()? 'Oui': 'Yes'))"
Andrew Shepherd le

Réponses:


167

Hé hé, oh M. Brown, si seulement je pouvais persuader tous les développeurs que je rencontre de garder leurs fonctions aussi petites que cela, croyez-moi, le monde du logiciel serait un meilleur endroit!

1) La lisibilité de votre code augmente de dix fois.

2) Si facile à comprendre le processus de votre code en raison de la lisibilité.

3) SEC - Ne te répète pas - Tu t'y conforme très bien!

4) testable. Les fonctions minuscules sont un million de fois plus faciles à tester que les méthodes à 200 lignes que nous voyons trop souvent.

Oh, et ne vous inquiétez pas du "saut de fonction" en termes de performances. Les versions "Release" et les optimisations du compilateur s'en occupent très bien, et les performances représentent 99% du temps ailleurs dans la conception des systèmes.

Est-ce paresseux? - Bien au contraire!

Est-ce une mauvaise pratique? - Absolument pas. Mieux vaut utiliser cette méthode de fabrication que les boules de goudron ou les "Objets divins" qui sont trop communs.

Continuez le bon travail mon collègue artisan;)


40
Vous ne répondez pas à la question, vous prêchez seulement la règle dont les applications les plus extrêmes sont mises en question ici.

4
Ce n'est pas très souvent que je trouve frustrante la limitation d'un vote positif. Mais, pour cette réponse, +1 ne semble pas lui rendre justice.
Bevan

4
+5 ... oh ne peut faire que +1, oh bien! Et pour soutenir MeshMan, je suggère le livre suivant de Robert C. Martin Clean code . Ce livre change vraiment la façon dont je programme maintenant.
Eric-Karl le

10
Très sympathique réponse, mais je suis en désaccord avec l'essentiel: 1) Les fonctions extrêmement petites génèrent davantage de code, en raison de toute la tuyauterie nécessaire à chaque fonction. Cela peut réduire la lisibilité, en particulier pour un très gros projet. En outre, dépend de la langue. 2) Dépend entièrement du point 1 et n'a donc rien à voir avec la question. 3) quoi? runCallback répète le "rappel" quatre fois, et trois fois fait référence à la même variable pour exécuter une seule fonction. 4) Les méthodes de plus de 200 lignes ne sont bien sûr pas testables, mais il y a un long chemin à parcourir pour atteindre une seule ligne.
l0b0

10
-1: La chose la plus effrayante ici est le nombre de votes positifs accordés à cette réponse.
Luca

64

Je dirais qu'une méthode refactorisée est trop courte si:

  • Il duplique une opération primitive dans le seul but d'en faire une méthode:

Ex:

boolean isNotValue() {
   return !isValue();
}

ou...

  • Le code n'est utilisé qu'une seule fois et son objectif est facile à comprendre d'un coup d'œil.

Ex:

void showDialog() {
    Dialog singleUseDialog = new ModalDialog();
    configureDialog(singleUseDialog);
    singleUseDialog.show();
}

void configureDialog(Dialog singleUseDialog) {
    singleUseDialog.setDimensions(400, 300);
}

Cela pourrait être un modèle valide, mais je voudrais simplement intégrer la méthode configureDialog (), dans cet exemple, à moins que je ne souhaite le remplacer ou réutiliser ce code ailleurs.


7
Séparer une méthode à une seule ligne dans le second cas peut être utile pour maintenir la cohérence du niveau d'abstraction des méthodes appelantes. L'exemple fourni est sur la clôture si ce raisonnement est utilisé: la largeur et la hauteur de pixels exactes sont-elles trop détaillées pour afficher une boîte de dialogue?
Aleksi Yrttiaho le

2
La méthode "isNotValue ()" est mal nommée et doit être refactorisée pour nommer la question du domaine.

4
@ Aleksi: je ne suis pas d'accord; les détails sont déjà cachés dans la méthode showDialog () dans cet exemple; il n'y a pas besoin de double-refactor it L'exemple est destiné à montrer un cas d'utilisation isolé; Si un motif est nécessaire avec différentes configurations de dialogue dans différents cas, il serait logique de revenir en arrière et de refactoriser une fois le motif établi.
RMorrisey

1
@Thorbjorn: Je peux voir un cas, lorsque vous répondez à une question du domaine commercial dont la logique peut ne pas être évidente. Je souligne simplement qu'il y a quelques cas où il y a trop de travail.
RMorrisey

3
C’est peut-être une mauvaise idée, mais je dirais que dans vos exemples, le problème n’est pas que la fonction est trop courte, mais qu’ils n’ajoutent pas de valeur descriptive.
keppla

59

Une fonction peut-elle être trop courte? En général non.

En fait, le seul moyen de s'assurer que:

  1. Vous avez trouvé toutes les classes dans votre conception
  2. Vos fonctions ne font qu'une chose.

Est de garder vos fonctions aussi petites que possible. Ou, en d'autres termes, extrayez des fonctions de vos fonctions jusqu'à ce que vous ne puissiez plus en extraire. J'appelle ça "Extrait jusqu'à ce que tu tombes".

Pour expliquer cela: une fonction est une étendue avec des blocs de fonctionnalités qui communiquent par des variables. Une classe est également une étendue avec des morceaux de fonctionnalités qui communiquent par des variables. Ainsi, une fonction longue peut toujours être remplacée par une ou plusieurs classes avec une petite méthode.

En outre, une fonction suffisamment grande pour vous permettre d’en extraire une autre, fait plus d’une chose par définition . Donc , si vous pouvez extraire une fonction d' une autre, vous devez extraire cette fonction.

Certains craignent que cela ne mène à une prolifération de fonctions. Ils ont raison. Ce sera. C'est en fait une bonne chose. C'est bien parce que les fonctions ont des noms. Si vous faites attention à choisir de bons noms, ces fonctions agissent comme des panneaux de signalisation qui guident les autres personnes dans votre code. En effet, des fonctions bien nommées au sein de classes bien nommées au sein d'espaces de noms bien nommés constituent l'un des meilleurs moyens de s'assurer que vos lecteurs NE se perdent PAS.

Il y a beaucoup plus à ce sujet dans l'épisode III de Clean Code sur cleancoders.com


5
Oncle Bob! Ravi de vous voir à bord ici. Comme prévu, des conseils fantastiques. Je n’avais jamais entendu le terme «Extrait jusqu’à la chute» et je l’utiliserai sûrement autour du bureau lundi;).
Martin Blore

1
Seriez-vous prêt à développer votre point n ° 1? Expliquer cela par exemple serait formidable.
Daniel Kaplan

53

Wow, la plupart de ces réponses ne sont pas très utiles du tout.

Aucune fonction dont l'identité est sa définition ne devrait être écrite . Autrement dit, si le nom de la fonction est simplement le bloc de code de la fonction écrit en anglais, ne l'écrivez pas en tant que fonction.

Considérez votre fonction conditionMetet cette autre fonction, addOne(pardonnez-moi pour mon JavaScript rouillé):

function conditionMet() { return x == condition; }

function addOne(x) { return x + 1; }

conditionMetest une définition conceptuelle appropriée; addOneest une tautologie . conditionMetest bon parce que vous ne savez pas ce que cela conditionMetimplique simplement en disant "condition satisfaite", mais vous pouvez voir pourquoi addOneest idiot si vous le lisez en anglais:

"For the condition to be met is for x to equal condition" <-- explanatory! meaningful! useful!

"To add one to x is to take x and add one." <-- wtf!

Pour l'amour de tout ce qui pourrait encore être sacré, n'écrivez pas de fonctions tautologiques!

(Et pour la même raison, n'écrivez pas de commentaires pour chaque ligne de code !)


Certaines des constructions de langage les plus complexes peuvent être inconnues ou difficiles à lire, ce qui en fait une astuce utile.

3
D'accord, ce qui devrait être transformé en une fonction dépend en grande partie du langage dans lequel il est écrit. Une fonction comme addOne serait utile si vous étiez dans un langage tel que VHDL, où vous définissez en fait la signification de l'ajout d'un niveau binaire ou théorie des nombres. J'aimerais penser qu'aucune langue n'est si cryptée qu'il est difficile à lire, même pour les programmeurs expérimentés (peut-être brainf # ck), mais si tel est le cas, la même idée serait valable, car la fonction est en réalité une traduction de l'anglais à cette langue - de sorte que le nom n'est pas la même chose que la définition.
Rei Miyasaka le

1
Je parle des fonctions d'identité de la bibliothèque standard Haskell - je ne pense pas que vous puissiez être plus "tautologiques" que ça :)
hugomg

1
@missingno Bah, c'est de la triche: D
Rei Miyasaka

5
Si vous nommez les fonctions par leur fonction plutôt que par leur contenu, elles cessent immédiatement d'être ridicules. Ainsi, vos exemples pourraient être, par exemple, être function nametoolong() { return name.size > 15; }ou function successorIndex(x) { return x + 1; } Alors le problème avec vos fonctions est en réalité juste qu'elles s'appellent mal.
Hans-Peter Störr

14

Je dirais que si vous pensez que l'intention d'un code peut être améliorée en ajoutant un commentaire, alors plutôt que d'ajouter ce commentaire, extrayez le code dans sa propre méthode. Peu importe la taille du code.

Ainsi, par exemple, si votre code devait ressembler à ceci:

if x == 1 { ... } // is pixel on?

faites le ressembler à ceci à la place:

if pixelOn() { ... }

avec

function pixelOn() { return x == 1; }

Ou en d'autres termes, il ne s'agit pas de la longueur de la méthode, mais du code auto-documenté.


5
Mon estimé collègue fait remarquer que vous pourriez aussi écrire if x == PIXEL_ON. L'utilisation d'une constante peut être aussi descriptive que l'utilisation d'une méthode et est un peu plus brève.
Tom Anderson

7

Je pense que c'est exactement ce que vous voulez faire. À l'heure actuelle, cette fonction peut ne comporter qu'une ou deux lignes, mais avec le temps, elle pourrait se développer. De plus, avoir plus d'appels de fonction vous permet de lire les appels de fonction et de comprendre ce qui se passe à l'intérieur. Cela rend votre code très sec (ne vous répétez pas) ce qui est beaucoup plus facile à gérer.


4
Alors, qu'est-ce qui ne va pas avec la prise en compte plus tard, quand vous pouvez prouver que vous en avez besoin, au lieu de maintenant, alors que ce n'est que du poids mort?
dsimcha

Les fonctions ne se développent pas d'elles-mêmes. IMHO les exemples sont moche. conditionMetest un nom trop générique, et ne prend aucun argument, il teste donc un état? (x == xCondition) est dans la plupart des langues et situations aussi expressive que 'xConditition'.
utilisateur inconnu

Oui, et c'est pourquoi vous souhaitez que votre code comporte plus de 75% de frais généraux? La doublure simple écrite en 3 lignes correspond en réalité à 300%.
Coder

5

Je suis d'accord avec tous les autres messages que j'ai vus. C'est bon style.

La surcharge d'une méthode aussi petite peut être nulle, car l'optimiseur peut optimiser l'appel à distance et le code en ligne. Un code simple comme celui-ci permet à l'optimiseur de faire de son mieux.

Le code doit être écrit pour plus de clarté et de simplicité. J'essaie de limiter une méthode à l'un des deux rôles suivants: prendre des décisions; ou effectuer un travail. Cela peut générer des méthodes à une ligne. Plus je réussis à le faire, meilleur je trouve mon code.

Un tel code a tendance à avoir une cohésion élevée et un couplage faible, ce qui est une bonne pratique de codage.

EDIT: Une note sur les noms de méthodes. Utilisez un nom de méthode qui indique ce que la méthode ne fait pas. Je trouve que verb_noun (_modifier) ​​est un bon schéma de nommage. Cela donne des noms comme Find_Customer_ByName plutôt que Select_Customer_Using_NameIdx. Le second cas est susceptible de devenir incorrect lorsque la méthode est modifiée. Dans le premier cas, vous pouvez échanger la mise en œuvre complète de la base de données client.


+1 pour avoir mentionné l'inline, la principale considération dans les performances et les fonctions courtes.
Garet Claborn le

4

Refactoriser une ligne de code dans une fonction semble excessif. Il peut y avoir des cas exceptionnels, tels que des lignes ou des expansions très compliquées, mais je ne le ferais pas à moins de savoir que la fonction se développera dans le futur.

et votre premier exemple suggère l'utilisation de globals (qui peuvent ou ne peuvent pas parler d'autres problèmes dans le code), je le reformulerais plus avant et ferais ces deux variables comme paramètres:

function conditionMet(x, condition){
   return x == condition;
}
....
conditionMet(1,(3-2));
conditionMet("abc","abc");

L' conditionMetexemple peut être utile si la condition est longue et répétitive, telle que:

function conditionMet(x, someObject){
   return x == ((someObject.valA + someObject.valB - 15.4) / /*...whole bunch of other stuff...*/);
}

1
Son premier exemple ne fait pas allusion à des globaux. En fait, c'est une méthode cohérente dans une classe très cohérente où la plupart des variables sont sur l'objet.
Martin Blore le

7
Cette conditionMetfonction est juste un ==opérateur prolixe . Ce n'est probablement pas utile.

1
Je n'utilise certainement pas de globals. @MeshMan, c'est exactement d'où provient l'exemple ... une méthode sur une classe.
Mark Brown

1
@Mark Brown: @MeshMan: Ok, je suppose que l'exemple de code était trop vague pour en être sûr ...
FrustratedWithFormsDesigner

Je sens un conditionMet (x, relation condition) {ici, où vous passez x, '==' et relation. Ensuite, vous n'avez pas besoin de répéter le code pour '<', '>', '<=', '! =' Et ainsi de suite. De l'autre côté - la plupart des langages ont ces constructions intégrées comme des opérateurs (x == condition) le font exactement. Fonctions pour les déclarations atomiques est un pas de trop.
utilisateur inconnu

3

Considère ceci:

Une simple fonction de détection de collision:

bool collide(OBJ a, OBJ b)
{
    return(pow(a.x - b.x, 2) + pow(a.y - b.y, 2) <= pow(a.radius + b.radius, 2));
}

Si vous écriviez cette "simple" ligne dans votre code tout le temps, vous pourriez éventuellement faire une erreur. De plus, il serait très pénible d’écrire cela encore et encore.


Si nous avons affaire à C ici, nous pourrions simplement en abuser #define;)
Cole Johnson

Vous voudrez peut-être même échanger ceci contre l' hypot lent, mais à l'épreuve des débordements, si vos tailles ou vos distances deviennent très grandes. C'est évidemment beaucoup plus facile à faire une fois.
Matt Krause

2

Non, et c'est rarement un problème. Maintenant, si quelqu'un estime qu'aucune fonction ne devrait être plus longue qu'une ligne de code (si seulement cela pouvait être aussi simple), ce serait un problème et, à certains égards, paresseux, car ils ne pensent pas à ce qui est approprié.


Je ne le compterais pas dans les lignes de code, mais dans les expressions. "(x == condition)" est atomique, donc je le mettrais dans une méthode / fonction uniquement, s'il est utilisé plusieurs fois ET peut être modifié, comme function isAdult () = { age >= 18; }mais sûrement pas isAtLeast18.
utilisateur inconnu

2

Je dirais qu'ils sont trop courts, mais c'est mon opinion subjective.

Parce que:

  • Il n'y a aucune raison de créer une fonction si elle n'est utilisée qu'une ou deux fois. Sauter aux defs sucer. Surtout avec des codes VS et C ++ incroyablement rapides.
  • Vue d'ensemble de la classe. Lorsque vous avez des milliers de petites fonctions, cela me met en colère. J'aime bien voir les définitions de classe et voir rapidement ce qu’il fait, et non pas comment il a été défini: SetXToOne, SetYToVector3, MultiplyNumbers, + 100 setters / getters.
  • Dans la plupart des projets, ces assistants deviennent poids mort après une ou deux phases de refactoring, puis vous effectuez une "recherche de tous" -> supprimez pour vous débarrasser du code obsolète, généralement environ 25% +.

Les fonctions qui sont longues sont mauvaises, mais les fonctions qui sont plus courtes que 3 lignes et qui exécutent seulement 1 chose sont également mauvaises.

Donc, je dirais seulement écrire petite fonction si c'est:

  • 3+ lignes de code
  • Fait des choses que les développeurs juniors pourraient manquer (ne sais pas)
  • Est-ce que la validation supplémentaire
  • Est utilisé, ou sera utilisé au moins 3x
  • Simplifie l'interface fréquemment utilisée
  • Ne deviendra pas un poids mort lors de la prochaine refactorisation
  • A une signification particulière, par exemple, une spécialisation de modèle ou quelque chose
  • Est-ce que certains travaux d'isolation - références const, affecte les paramètres mutables, récupère les membres privés

Je parie que le prochain développeur (senior) aura mieux à faire que de se souvenir de toutes vos fonctions SetXToOne. Ainsi, ils se transformeront bientôt en poids mort.


1

Je n'aime pas l'exemple non. 1, à cause du nom générique.

conditionMetne semble pas être générique, donc il représente une condition spécifique? Comme

isAdult () = { 
  age >= 18 
}

Ce serait bien. C'est une différence sémantique, alors que

isAtLeast18 () { age >= 18; } 

ne serait pas bien pour moi.

Peut-être qu'il est souvent utilisé et peut faire l'objet de modifications ultérieures:

getPreferredIcecream () { return List ("banana", "choclate", "vanilla", "walnut") }

est bien aussi. En l'utilisant plusieurs fois, il vous suffit de changer d'un seul lieu, le cas échéant. Peut-être que la crème fouettée sera possible demain.

isXYZ (Foo foo) { foo.x > 15 && foo.y < foo.x * 2 }

n'est pas atomique, et devrait vous donner une belle occasion de test.

Bien sûr, si vous avez besoin de passer une fonction, transmettez ce que vous voulez et écrivez des fonctions qui paraissent ridicules.

Mais en général, je vois beaucoup plus de fonctions, qui sont trop longues, que de fonctions qui sont trop courtes.

Un dernier mot: Certaines fonctions semblent seulement appropriées, car elles sont écrites trop verbeuses:

function lessThan (a, b) {
  if (a < b) return true else return false; 
}

Si vous voyez que c'est la même chose que

return (a < b); 

vous n'aurez pas de problème avec

localLessThan = (a < b); 

au lieu de

localLessThan = lessThan (a, b); 

0

Il n'y a pas de code comme pas de code!

Restez simple et ne compliquez pas trop les choses.

Ce n'est pas être paresseux, c'est faire votre travail!


0

Oui, son ok pour avoir une fonction de code court. Dans le cas de méthodes telles que "getters", "setters", "accessors" est très courant, comme indiqué dans les réponses précédentes.

Parfois, ces fonctions "accesors" courtes sont virtuelles, car lorsqu'elles sont remplacées dans des sous-classes, les fonctions auront plus de code.

Si vous voulez que votre fonction ne soit pas si courte, eh bien, dans de nombreuses fonctions, que ce soit globales ou méthodes, j'utilise généralement une variable "result" (style pascal) au lieu d'un retour direct, c'est très utile lorsque vous utilisez un débogueur.

function int CalculateSomething() {
  int Result = -1;

   // more code, maybe, maybe not

  return Result;
}

0

Trop court n'est jamais un problème. Quelques raisons pour les fonctions courtes sont:

Réutilisabilité

Par exemple, si vous avez une fonction, comme une méthode set, vous pouvez l'affirmer pour vous assurer que les paramètres sont valides. Cette vérification doit être effectuée partout où la variable est définie.

Maintenabilité

Vous pouvez utiliser une déclaration qui, à votre avis, pourrait changer. Par exemple, vous affichez maintenant un symbole dans une colonne, mais cela pourrait changer ultérieurement (ou même un bip).

Uniformité

Vous utilisez, par exemple, le motif de façade et la seule chose que fait une fonction est de la transmettre à une autre sans changer d'argument.


0

Lorsque vous nommez une section de code, c'est essentiellement pour lui donner un nom . Cela peut être dû à plusieurs raisons, mais le point crucial est que vous puissiez lui donner un nom explicite qui ajoute à votre programme. Des noms comme "addOneToCounter" n’ajouteraient rien, mais le conditionMet()feraient.

Si vous avez besoin d'une règle pour déterminer si l'extrait est trop court ou trop long, déterminez le temps qu'il vous faut pour trouver un nom significatif à l'extrait. Si vous ne pouvez pas le faire dans un délai raisonnable, la taille de l'extrait de code ne convient pas.


0

Non, mais ça peut être trop concis.

Rappelez-vous: le code est écrit une fois, mais lu plusieurs fois.

N'écrivez pas de code pour le compilateur. Ecrivez-le pour les futurs développeurs qui devront maintenir votre code.


-1

Oui, ma fonction peut être de plus en plus petite et, qu’elle soit bonne ou mauvaise, cela dépend de la langue / du framework que vous utilisez.

À mon avis, je travaille principalement sur les technologies frontales. Les petites fonctions sont principalement utilisées en tant que fonctions d'assistance que vous serez obligé de les utiliser comme beaucoup lorsque vous travaillez avec de petits filtres et en utilisant la même logique dans votre application. Si votre application a trop de logique commune, il y aura alors une tonne de petites fonctions.

Mais dans une application où vous n'avez pas de logique commune, vous ne serez pas obligé de créer de petites fonctions, mais vous pouvez diviser votre code en segments où il devient facile pour vous de gérer et de comprendre.

En général, casser votre gros code en petite fonction est une très bonne approche. Dans les cadres et les langages modernes, vous serez obligé de le faire, par exemple

data => initScroll(data)

est une fonction anonyme dans ES 2017 JavaScript et Typescript

getMarketSegments() {
 this.marketService.getAllSegments(this.project.id)
  .subscribe(data => this.segments = data, error => console.log(error.toString()));
}

Dans le code ci-dessus, vous pouvez voir 3 déclarations de fonction et 2 appels de fonction. Il s'agit d'un simple appel de service dans Angular 4 avec Typescript. Vous pouvez le considérer comme vos exigences

([] 0)
([x] 1)
([x y] 2)

Les fonctions ci-dessus sont 3 fonctions anonymes en langage clojure

(def hello (fn [] "Hello world"))

Le précédent est une déclaration fonctionnelle en clojure

Donc oui, FUNCTIONS peut être aussi petit, mais que ce soit bon ou mauvais si vous avez des fonctions comme:

incrementNumber(numb) { return ++numb; }

Bien que ce ne soit pas une bonne pratique, mais si vous utilisiez cette fonction dans une balise HTML comme nous le faisons dans Angular Framework, si Incrément ou Décrément ne sont pas pris en charge dans les modèles HTML angulaires, alors cela aurait été la solution moi.

Prenons un autre exemple

insertInArray(array, newKey) {
 if (!array.includes(newKey)) {
   array.push(newKey);
 }
}

L'exemple ci-dessus est un must lors de la lecture de tableaux dans des modèles angulaires HTML. Donc, parfois, vous devrez créer de petites fonctions


-2

Je suis en désaccord avec presque réponse donnée à ce moment.

Récemment, j'ai trouvé un collègue qui écrit tous les membres de la classe comme suit:

 void setProperty(int value){ mValue=value; }
 int getProperty() const { return (mValue); }

Cela pourrait être un bon code dans des cas sporadiques, mais sûrement pas si vous définissez de nombreuses classes ayant de très nombreuses propriétés. Je ne veux pas dire, avec ceci, que des méthodes comme celles ci-dessus ne seront pas écrites. Mais si vous finissez par écrire la plus grande partie du code en tant que "wrapper" de la logique réelle, il y a quelque chose qui ne va pas.

Le programmeur manque probablement de logique générale, de peur des changements futurs et de refactoriser le code.

La définition de l'interface est un besoin réel; En effet, si vous devez définir et obtenir une propriété simple (sans beaucoup de logique, ce qui raccourcit le membre), cela sera possible. Mais si le besoin réel pouvait être analysé différemment, pourquoi ne pas définir une interface plus intuitive?

Pour vraiment répondre à la question, bien sûr que non, et la raison en est très évidente: la méthode / propriété / quoi que ce soit doit être défini pour ce dont il a besoin. Même une fonction virtuelle vide a sa raison d'être.


6
Il existe une bonne raison d’ajouter des méthodes d’accesseur / mutateur, auxquelles vous faites allusion sous "Peur à propos du futur ... refactoring". Mais vous avez également raison de dire que cela n'ajoute pas de valeur au code. Ni en réduisant la taille (localement ou globalement) ni en améliorant la lisibilité. Dans mon esprit, cela témoigne d'une conception de langage médiocre dans les conventions Java et JavaBeans. C’est l’un des domaines dans lesquels C # a réussi à améliorer le langage afin de répondre aux deux préoccupations de la syntaxe de propriété automatique . En tant que programmeur Java, je suis d’accord avec votre style brut pour les classes de base de type struct.
Anm le

1
Les fonctions Getter / Setter sont bonnes même si elles ne font que lire ou écrire une variable. En pratique, vous pouvez imaginer un scénario dans lequel vous décidez par la suite d’imprimer une valeur à l’écran chaque fois que le champ est modifié ou de vérifier si cette valeur est valide ou non. (Peut-être que c'est un dénominateur pour une fraction, et que vous voulez vérifier pour vous assurer qu'il n'est pas nul.)
Rei Miyasaka Le

2
les getters et les setters sont affreux, malgré leur utilisation valable. S'il est nécessaire de les utiliser, je considère cela comme un échec de la langue.
Carson Myers le

@Rei: pourquoi une classe externe aurait-elle besoin de vérifier la valeur des dénominateurs? Cela devrait être fait par la fonction divide () de la classe Fraction ou la classe Fraction devrait fournir un isDivisible () pour vérifier les dénominateurs nuls. Les getters / setters ont généralement besoin d'une odeur de code indiquant que votre classe a un couplage élevé et / ou une cohésion faible (c'est-à-dire mauvaise).
Lie Ryan

@Lie Quoi? Je n'ai jamais dit qu'une classe externe devrait être utilisée pour vérifier les dénominateurs. Je dis qu'une classe externe peut définir un dénominateur à 0 par accident. Le but des vérifications de validité chez les installateurs est d'encourager la découverte plus précoce de tout bogue dans le code du consommateur. Fournir une fonction isDivisible () qui peut être appelée ou non ne fonctionne pas non plus à cette fin. Et comment exactement le besoin de getters / setters indique-t-il un couplage élevé?
Rei Miyasaka
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.