web-dev-qa-db-fra.com

Y a-t-il une telle chose que d'avoir trop de fonctions / méthodes privées?

Je comprends l'importance d'un code bien documenté. Mais je comprends également l'importance du code auto-documenté . Plus il est facile de lire visuellement une fonction particulière, plus vite nous pouvons avancer pendant la maintenance du logiciel.

Cela dit, j'aime séparer les grandes fonctions en d'autres plus petites. Mais je le fais au point où une classe peut avoir plus de cinq d'entre eux juste pour servir une méthode publique. Multipliez maintenant cinq méthodes privées par cinq méthodes publiques, et vous obtenez environ vingt-cinq méthodes cachées qui ne seront probablement appelées qu'une seule fois par ces méthodes publiques.

Bien sûr, il est maintenant plus facile de lire ces méthodes publiques, mais je ne peux m'empêcher de penser qu'avoir trop de fonctions est une mauvaise pratique.

[Modifier]

Les gens me demandent pourquoi je pense qu'avoir trop de fonctions est une mauvaise pratique.

La réponse simple: c'est un sentiment d'intestin.

Ma conviction n'est pas, pour un peu, soutenue par des heures d'expérience en génie logiciel. C'est juste une incertitude qui m'a donné un "bloc d'écrivain", mais pour un programmeur.

Dans le passé, je ne programmais que des projets personnels. Ce n'est que récemment que je suis passé à des projets en équipe. Maintenant, je veux m'assurer que les autres peuvent lire et comprendre mon code.

Je ne savais pas ce qui améliorerait la lisibilité. D'une part, je pensais à séparer une grande fonction en d'autres plus petites avec des noms intelligibles. Mais il y avait un autre côté de moi qui disait que c'était juste superflu.

Je demande donc ceci pour m'éclairer afin de choisir le bon chemin.

[Modifier]

Ci-dessous, j'ai inclus deux versions de la façon dont je pouvais résoudre mon problème. Le premier le résout en pas en séparant de gros morceaux de code. Le second sépare les choses.

Première version:

public static int Main()
{
    // Displays the menu.
    Console.WriteLine("Pick your option");
    Console.Writeline("[1] Input and display a polynomial");
    Console.WriteLine("[2] Add two polynomials");
    Console.WriteLine("[3] Subtract two polynomials");
    Console.WriteLine("[4] Differentiate two polynomials");
    Console.WriteLine("[0] Quit");
}

Deuxième version:

public static int Main()
{
    DisplayMenu();
}

private static void DisplayMenu()
{
    Console.WriteLine("Pick your option");
    Console.Writeline("[1] Input and display a polynomial");
    Console.WriteLine("[2] Add two polynomials");
    Console.WriteLine("[3] Subtract two polynomials");
    Console.WriteLine("[4] Differentiate two polynomials");
    Console.WriteLine("[0] Quit");
}

Dans les exemples ci-dessus, ce dernier appelle une fonction qui ne sera utilisée qu'une seule fois pendant toute la durée d'exécution du programme.

Remarque: le code ci-dessus est généralisé, mais il est de la même nature que mon problème.

Maintenant, voici ma question: laquelle? Dois-je choisir le premier ou le second?

63
Sal

Multipliez maintenant cinq méthodes privées par cinq méthodes publiques, et vous obtenez environ vingt-cinq méthodes cachées qui ne seront probablement appelées qu'une seule fois par ces méthodes publiques.

C'est ce qu'on appelle encapsulation , ce qui crée un Control Abstraction au niveau supérieur. C'est une bonne chose.

Cela signifie que toute personne lisant votre code, lorsqu'elle arrive à la méthode startTheEngine() dans votre code, peut ignorer tous les détails de niveau inférieur tels que openIgnitionModule(), turnDistributorMotor() , sendSparksToSparkPlugs(), injectFuelIntoCylinders(), activateStarterSolenoid(), et toutes les autres fonctions complexes et petites qui doivent être exécutées afin de faciliter la fonction beaucoup plus grande et plus abstraite de startTheEngine().

À moins que le problème que vous rencontrez dans votre code ne concerne directement l'un de ces composants, les responsables du code peuvent passer à autre chose, ignorant la fonctionnalité encapsulée en sandbox.

Cela a également l'avantage supplémentaire de rendre votre code plus facile à tester. . Par exemple, je peux écrire un cas de test pour turnAlternatorMotor(int revolutionRate) et tester ses fonctionnalités complètement indépendantes des autres systèmes. S'il y a un problème avec cette fonction et que la sortie n'est pas celle que j'attends, alors je sais quel est le problème.

Le code qui n'est pas décomposé en composants est beaucoup plus difficile à tester. Du coup, vos mainteneurs ne voient que l'abstraction au lieu de pouvoir creuser en composants mesurables.

Mon conseil est de continuer à faire ce que vous faites car votre code évoluera, sera facile à maintenir et pourra être utilisé et mis à jour pour les années à venir.

36
jmort253

Oui et non. Le principe fondamental est: ne méthode doit faire une chose et une seule chose

Il est correct de "diviser" votre méthode en méthodes plus petites. Là encore, ces méthodes devraient de manière optimale être suffisamment générales pour ne pas seulement servir cette "grande" méthode mais être réutilisables dans d'autres endroits. Dans certains cas, une méthode suivra une structure arborescente simple, comme une méthode Initialize qui appelle InitializePlugins, InitializeInterface etc.

Si vous avez une très grande méthode/classe, c'est généralement un signe que cela fait trop et vous devez faire un remaniement pour briser le "blob". Peut-être cacher une certaine complexité dans une autre classe sous une abstraction, et utiliser l'injection de dépendance

22
Homde

Je pense qu'en général, il vaut mieux pécher par trop de fonctions plutôt que par trop peu. Les deux exceptions à cette règle que j'ai vues dans la pratique concernent les SEC et YAGNI = principes. Si vous avez beaucoup de fonctions presque identiques, vous devez les combiner et utiliser des paramètres pour éviter de vous répéter. Vous pouvez également avoir trop de fonctions si vous les avez créées "au cas où" et qu'elles ne sont pas utilisées. Je ne vois absolument rien de mal à avoir une fonction qui n'est utilisée qu'une seule fois si elle ajoute la lisibilité et la maintenabilité.

17
Karl Bielefeldt

la grande réponse de jmort253 m'a inspiré à suivre avec une réponse "oui, mais" ...

Avoir beaucoup de petites méthodes privées n'est pas une mauvaise chose, mais faites attention à ce sentiment insignifiant qui vous fait poser une question ici :). Si vous arrivez à un point où vous écrivez des tests qui se concentrent uniquement sur des méthodes privées (soit en les appelant directement, soit en configurant un scénario tel que l'un soit appelé d'une certaine manière pour pouvoir tester le résultat), alors vous devriez prendre du recul.

Ce que vous pourriez avoir, c'est une nouvelle classe avec sa propre interface publique plus ciblée essayant de s'échapper. À ce stade, vous voudrez peut-être penser à extraire une classe pour encapsuler la partie de vos fonctionnalités de classes existantes qui vit actuellement en méthode privée. Maintenant, votre classe d'origine peut utiliser votre nouvelle classe comme dépendance, et vous pouvez écrire directement des tests plus ciblés contre cette classe.

10
Pete Hodgson

Presque tous les projets OO auxquels j'ai participé ont beaucoup souffert des classes trop volumineuses et des méthodes trop longues.

Lorsque je ressens le besoin d'un commentaire expliquant la prochaine section de code, j'extraye cette section dans une méthode distincte. À long terme, cela raccourcit le code. Ces petites méthodes sont réutilisées plus que ce à quoi vous vous attendiez initialement. Vous commencez à voir des opportunités d'en collecter un tas dans une classe séparée. Bientôt, vous pensez à votre problème à un niveau supérieur, et tout l'effort va beaucoup plus vite. Les nouvelles fonctionnalités sont plus faciles à écrire, car vous pouvez vous appuyer sur ces petites classes que vous avez créées à partir de ces petites méthodes.

8
kevin cline

Une classe avec 5 méthodes publiques et 25 méthodes privées ne me semble pas si grande. Assurez-vous simplement que vos classes ont des responsabilités bien définies et ne vous inquiétez pas trop du nombre de méthodes.

Cela dit, ces méthodes privées doivent se concentrer sur un aspect spécifique de l'ensemble de la tâche, mais pas de manière "doSomethingPart1", "doSomethingPart2". Vous ne gagnez rien si ces méthodes privées ne sont que des morceaux d'une longue histoire arbitrairement divisée, chacune n'ayant aucun sens en dehors de tout le contexte.

7
user281377

Extrait de R. Martin's Clean Code (p. 176):

Même des concepts aussi fondamentaux que l'élimination de la duplication, l'expressivité du code et le SRP peuvent être poussés trop loin. Afin de réduire la taille de nos classes et méthodes, nous pourrions créer trop de petites classes et méthodes. Donc, cette règle [minimiser le nombre de classes et de méthodes] suggère que nous gardons également notre nombre de fonctions et de classes bas. Le nombre élevé de classes et de méthodes est parfois le résultat d'un dogmatisme inutile.

4
user2418306

Quelques options:

  1. C'est très bien. Nommez simplement les méthodes privées ainsi que vos méthodes publiques. Et nommez bien vos méthodes publiques.

  2. Résumé de certaines de ces méthodes d'assistance dans des classes d'assistance ou des modules d'assistance. Et assurez-vous que ces classes/modules d'assistance sont bien nommés et sont des abstractions solides en soi.

3
yfeldblum

Je ne pense pas qu'il y ait jamais un problème de "trop ​​de méthodes privées" si c'est le cas, c'est probablement un symptôme d'une mauvaise architecture de code.

Voici comment j'y pense ... Si l'architecture est bien conçue, il est généralement évident où le code qui fait X devrait être. C'est acceptable s'il y a quelques exceptions à cela - mais celles-ci doivent être vraiment exceptionnelles sinon refactorisez l'architecture pour les gérer en standard.

Si le problème est qu'à l'ouverture de votre classe, elle regorge de méthodes privées qui décomposent de plus gros morceaux en petits morceaux de code, alors c'est peut-être un symptôme d'une architecture manquante. Au lieu des classes et de l'architecture, cette zone de code a été implémentée de manière procédurale à l'intérieur d'une classe.

Trouver un équilibre ici dépend du projet et de ses exigences. Le contre-argument à cela est le dicton selon lequel un programmeur junior peut créer la solution en 50 lignes de code qui prend un architecte 50 classes.

1
Michael Shaw

Y a-t-il une telle chose que d'avoir trop de fonctions/méthodes privées?

Oui.

En Python le concept de "privé" (tel qu'utilisé par C++, Java et C #) n'existe pas vraiment).

Il existe une convention de dénomination "en quelque sorte privée", mais c'est tout.

Privé peut conduire à un code difficile à tester. Il peut également briser le "principe ouvert-fermé" en rendant le code simplement fermé.

Par conséquent, pour les personnes qui ont utilisé Python, les fonctions privées n'ont aucune valeur. Rendez tout public et finissez-en.

0
S.Lott