Je comprends l'importance d'un code bien documenté. Mais je comprends aussi l’importance du code auto-documenté . Plus il est facile de lire visuellement une fonction particulière, plus nous pouvons avancer rapidement pendant la maintenance du logiciel.
Cela dit, j'aime séparer les grandes fonctions en d'autres plus petites. Mais je le fais à un point où une classe peut en avoir plus de cinq simplement pour servir une méthode publique. Maintenant, multipliez cinq méthodes privées par cinq publiques et vous obtiendrez environ 25 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 pas m'empêcher de penser qu'avoir trop de fonctions est une mauvaise pratique.
[Modifier]
Les gens me demandent pourquoi, à mon avis, avoir trop de fonctions est une mauvaise pratique.
La réponse simple: c'est un instinct.
Ma conviction n’est pas, pour une part, étayée par des heures d’expérience en génie logiciel. C'est juste une incertitude qui m'a donné un "blocage de l'é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é aux projets en équipe. Maintenant, je veux m'assurer que les autres peuvent lire et comprendre mon code.
Je n'étais pas sûr de ce qui améliorera la lisibilité. D'un côté, je pensais séparer une grande fonction en une autre plus petite avec des noms intelligibles. Mais il y avait un autre côté de moi qui disait que c'était simplement redondant.
Donc, je demande à ceci de m'éclairer afin de choisir le bon chemin.
[Modifier]
Ci-dessous, j'ai inclus deux versions permettant de résoudre mon problème. Le premier résout le problème en ne séparant pas de gros morceaux de code. Le second fait des choses séparées.
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 même nature que mon problème.
Maintenant, voici ma question: laquelle? Est-ce que je choisis le premier ou le second?
Réponses:
C'est ce qu'on appelle l' encapsulation , qui crée une abstraction de contrôle au niveau supérieur. C'est une bonne chose.
Cela signifie que toute personne lisant votre code, quand ils arrivent à la
startTheEngine()
méthode dans votre code, peut ignorer tous les détails de niveau inférieur tels queopenIgnitionModule()
,turnDistributorMotor()
,sendSparksToSparkPlugs()
,injectFuelIntoCylinders()
,activateStarterSolenoid()
, et toutes les autres fonctions complexes, petits, qui doivent être exécutées afin de faciliter la fonction beaucoup plus grande et plus abstraite destartTheEngine()
.Sauf si le problème que vous rencontrez dans votre code concerne directement l'un de ces composants, les responsables du code peuvent passer à autre chose, en ignorant la fonctionnalité encapsulée en bac à sable.
Cela présente également l’avantage supplémentaire de rendre votre code plus facile à tester. . Par exemple, je peux rédiger un scénario de
turnAlternatorMotor(int revolutionRate)
test et tester ses fonctionnalités de manière totalement indépendante des autres systèmes. S'il y a un problème avec cette fonction et que le résultat n'est pas ce que j'attendais, je sais alors quel est le problème.Le code qui n'est pas décomposé en composants est beaucoup plus difficile à tester. Soudain, vos responsables ne font que regarder l’abstraction au lieu de pouvoir creuser des composants mesurables.
Mon conseil est de continuer à faire ce que vous faites car votre code évoluera, sera facile à gérer et pourra être utilisé et mis à jour pour les années à venir.
la source
myString.replaceAll(pattern, originalData);
ou moi coller toute la méthode replaceAll dans mon code, y compris le tableau de caractères de sauvegarde qui représente l'objet chaîne sous-jacent à chaque fois que j'ai besoin d'utiliser les fonctionnalités d'une chaîne?Oui et non. Le principe fondamental est: une 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 être suffisamment générales pour ne pas servir uniquement cette méthode "volumineuse" mais être réutilisables à 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 en fait trop et que vous devez procéder à une refactorisation pour dissocier le "blob". Peut-être cachent-ils une certaine complexité dans une autre classe sous abstraction et utilisent l'injection de dépendance
la source
Je pense qu'en général, il vaut mieux pécher par excès de fonctions que par trop peu. Les deux exceptions à cette règle que j'ai constatées dans la pratique concernent les principes DRY et YAGNI . 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 si elles ne sont pas utilisées. Je ne vois absolument rien de mal à avoir une fonction qui n'est utilisée qu'une fois si elle ajoute de la lisibilité et de la maintenabilité.
la source
La bonne réponse de jmort253 m'a inspiré à donner la 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 écrivez des tests axés uniquement sur des méthodes privées (soit en les appelant directement, soit en configurant un scénario tel que celui-ci est appelé de manière à pouvoir tester le résultat), vous devriez prendre du recul.
Vous avez peut-être une nouvelle classe avec sa propre interface publique plus ciblée qui tente de s’échapper. À ce stade, vous voudrez peut-être envisager d'extraire une classe pour encapsuler cette partie de la fonctionnalité de votre classe existante qui vit actuellement dans une méthode privée. Désormais, votre classe d'origine peut utiliser votre nouvelle classe comme dépendance et vous pouvez écrire directement des tests plus ciblés sur cette classe.
la source
Presque tous les projets OO auxquels j'ai adhéré ont souffert de classes trop grandes et de méthodes trop longues.
Lorsque je ressens le besoin d'un commentaire expliquant la section de code suivante, je l'extrais dans une méthode distincte. À long terme, cela raccourcit le code. Ces petites méthodes sont réutilisées plus que prévu initialement. Vous commencez à voir des occasions de rassembler un groupe d'entre eux dans une classe séparée. Bientôt, vous réfléchissez à votre problème à un niveau plus élevé et tout l’effort est beaucoup plus rapide. Les nouvelles fonctionnalités sont plus faciles à écrire, car vous pouvez utiliser ces petites classes que vous avez créées à partir de ces petites méthodes.
la source
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 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 pas de sens en dehors de tout le contexte.
la source
Extrait du Clean Code de R. Martin (p. 176):
la source
Quelques options:
C'est très bien. Il suffit de nommer les méthodes privées ainsi que vos méthodes publiques. Et nommez bien vos méthodes publiques.
Abstrait certaines de ces méthodes d'assistance dans des classes ou des modules d'assistance. Et assurez-vous que ces classes / modules d’appel sont bien nommés et constituent de solides abstractions en soi.
la source
Je ne pense pas qu'il y ait jamais un problème de "trop de méthodes privées" si cela semble être le symptôme d'une architecture de code médiocre.
Voici comment j'y pense ... Si l'architecture est bien conçue, il est généralement évident que le code utilisé par X devrait être. Il est acceptable s'il existe quelques exceptions à cela - mais elles doivent être vraiment exceptionnelles, sinon, refactoriser l'architecture pour les gérer en standard.
Si le problème est que lors de l’ouverture de votre classe, elle est pleine de méthodes privées qui divisent de plus gros morceaux en de plus petits morceaux de code, alors c’est peut-être un symptôme de l’architecture manquante. Au lieu de classes et d'architecture, ce domaine de code a été implémenté de manière procédurale dans une classe.
Trouver un équilibre ici dépend du projet et de ses exigences. L'argument opposé à cela est le dicton selon lequel un programmeur junior peut créer la solution en 50 lignes de code qui prennent 50 classes pour un architecte.
la source
Oui.
En Python, le concept de "privé" (tel qu'utilisé par C ++, Java et C #) n'existe pas vraiment.
Il existe une convention d'appellation "en quelque sorte de privé", mais c'est tout.
Privé peut conduire à un code difficile à tester. Il peut également enfreindre le "principe d'ouverture-fermeture" en rendant le code simplement fermé.
Par conséquent, pour les utilisateurs de Python, les fonctions privées n’ont aucune valeur. Il suffit de tout rendre public et d’en finir.
la source