Pourquoi les gens sont-ils si fortement opposés aux balises #region dans les méthodes?

27

J'entends beaucoup parler de garder les méthodes courtes et j'ai entendu beaucoup de programmeurs dire que l'utilisation de balises #region dans une méthode est un signe certain qu'elle est trop longue et devrait être refactorisée en plusieurs méthodes. Cependant, il me semble qu'il existe de nombreux cas où la séparation du code avec des balises #region au sein d'une méthode est la meilleure solution pour la refactorisation en plusieurs méthodes.

Supposons que nous ayons une méthode dont le calcul peut être séparé en trois phases plutôt distinctes. De plus, chacune de ces étapes n'est pertinente que pour le calcul de cette méthode, et donc les extraire dans de nouvelles méthodes ne nous permet pas de réutiliser le code. Quels sont donc les avantages d'extraire chaque phase dans sa propre méthode? Pour autant que je sache, tout ce que nous gagnons est une certaine lisibilité et une portée variable distincte pour chaque phase (ce qui aidera à empêcher les modifications d'une phase particulière de casser accidentellement une autre phase).

Cependant, les deux peuvent être atteints sans extraire chaque phase dans sa propre méthode. Les balises de région nous permettent de réduire le code dans un formulaire tout aussi lisible (avec l'avantage supplémentaire que nous n'avons plus à laisser notre place dans ce fichier si nous décidons de développer et d'examiner le code), et d'envelopper simplement chaque phase dans {}crée sa propre portée pour travailler avec.

L'avantage de le faire de cette façon est que nous ne polluons pas la portée au niveau de la classe avec trois méthodes qui ne sont en fait pertinentes que pour le fonctionnement interne d'une quatrième méthode. Refactoriser immédiatement une méthode longue en une série de méthodes courtes me semble être la réutilisation de code équivalente à une optimisation prématurée; vous introduisez une complexité supplémentaire afin de résoudre un problème qui, dans de nombreux cas, ne se pose jamais. Vous pouvez toujours extraire l'une des phases dans sa propre méthode ultérieurement si l'occasion de réutilisation du code se présente.

Pensées?

jjoelson
la source
4
Je travaille actuellement avec une classe assez grande. Il suit le principe de responsabilité unique; tout dans la classe est une fonctionnalité requise. Il a beaucoup de méthodes privées, principalement en raison de la refactorisation. J'utilise #region pour diviser ces méthodes en catégories fonctionnelles, ce qui a très bien fonctionné pour nous. Il existe de nombreuses autres classes dans ce projet qui n'ont pas nécessité un tel traitement. Le bon outil pour le bon travail, je dis.
Robert Harvey
4
@RobertHarvey, les utiliser dans une classe est différent de les utiliser dans une méthode.
CaffGeek
18
@Chad: Ah, je n'ai pas remarqué ça. Les utiliser dans une méthode semble un peu extrême. Si une méthode est si longue qu'elle nécessite #regions, je la refactorise en méthodes distinctes.
Robert Harvey
8
Pas vraiment une réponse, mais non seulement je déteste toutes les #regionbalises, mais je désactive complètement le pliage de code dans Visual Studio. Je n'aime pas le code qui essaie de me cacher.
Daniel Pryden
2
"De plus, chacune de ces étapes n'est pertinente que pour le calcul de cette méthode, et donc les extraire dans de nouvelles méthodes ne nous permet pas de réutiliser le code". OTOH, je trouve que si je divise une fonction en 3, je trouve souvent plus tard que les parties individuelles <i> sont </i> utiles plus tard, par exemple. si certaines données d'entrée ne changent qu'une seule phase, vous pouvez le tester isolément, etc.
Jack V.

Réponses:

65

Tout ce dont vous devriez vous soucier, c'est que votre code soit utilisable et non réutilisable. Un singe peut transformer du code utilisable en code réutilisable, s'il y a des transformations à faire.

L'argument "j'ai besoin de cela seulement ici" est pauvre, pour le dire poliment. La technique que vous décrivez est souvent appelée la technique des gros titres et est généralement mal vue.

  1. Vous ne pouvez pas tester des régions, mais vous pouvez tester de vraies méthodes isolément.
  2. Les régions sont des commentaires, pas des éléments syntaxiques. Dans le pire des cas, l'imbrication de vos régions et de vos blocs se contredit. Vous devez toujours vous efforcer de représenter la sémantique de votre structure avec les éléments syntaxiques du langage que vous utilisez.
  3. Après refactoring aux méthodes, il n'est plus nécessaire de plier pour lire le texte. On pourrait regarder le code source dans n'importe quel outil qui n'a pas de pliage, comme un terminal, un client de messagerie, une vue Web pour votre VCS ou un visualiseur diff.
  4. Après refactorisation aux méthodes, la méthode résultante est au moins aussi bonne qu'avec les régions, et il est plus simple de déplacer les pièces individuelles.
  5. Le principe de responsabilité unique suggère que toute unité devrait avoir une seule tâche et une seule tâche. La tâche de la méthode "principale" est de composer les méthodes "d'aide" pour obtenir le résultat souhaité. Les méthodes «d'aide» résolvent un problème discret et simple de manière isolée. La classe contenant toutes ces méthodes ne doit également remplir qu'une seule tâche et ne contenir que les méthodes liées à cette tâche. Ainsi, les méthodes d'assistance appartiennent soit à la portée de la classe, soit le code ne doit pas être dans la classe en premier lieu, mais au moins dans une méthode globale ou, mieux encore, doit être injecté .

Également pertinent: les réflexions de Jeff Atwoods sur le pliage de code

back2dos
la source
9
1. La plupart des programmeurs ne testent pas toutes les méthodes privées. 2. Un nom de méthode ne peut pas transmettre tout ce qu'il y a à savoir sur cette méthode; quelles exceptions pourraient être levées? Null est-il une entrée valide? Parfois, il est acceptable d'utiliser des constructions non syntaxiques pour rendre votre code plus compréhensible. Dans de nombreuses langues, les fichiers sont un exemple d'élément non syntaxique qui est assez largement accepté comme moyen d'organiser le code. 3. Il est préférable de plonger dans le fonctionnement interne d'une méthode dans un IDE pour diverses raisons; les situations où les régions pourraient vous mordre dans votre VCS ou votre client de messagerie sont plutôt rares.
jjoelson
3
4. Mais vous venez d'exporter une sérieuse complexité dans le reste de votre classe. Est-ce que ça vaut le coup? De plus, les régions peuvent être déplacées aussi facilement qu'un appel de méthode. 5. Maintenant, vous parlez de polluer votre espace de noms avec plus de classes qui ne seront utilisées que dans un seul endroit. Pourquoi les classes et les méthodes sont-elles les seules unités d'encapsulation que vous accepterez? Vous pouvez toujours créer cette nouvelle classe ultérieurement (ou si) il devient nécessaire de séparer cette classe.
jjoelson
7
@jjoelson: 1. Et alors? 2. Exactement mon point: il est correct d'utiliser des constructions non syntaxiques si (et seulement si) la syntaxe seule ne suffit pas. 3. "Rare?" - Je suppose que vous avez des chiffres pour le montrer. Je peux vous dire avec certitude que l'outil diff (ou blâme ou autre d'ailleurs) fourni avec TortoiseSVN n'a pas de pliage. 4. Comment cela est-il lié au point que j'ai soulevé? 5. C'est pourquoi la plupart des langues modernes ont des espaces de noms emboîtables. Vous recourez à l'art ASCII plutôt que d'utiliser une large palette d'éléments de langage disponibles pour structurer votre code.
back2dos
4
@jjoelson: 1. C'est votre avis et hors de portée de cette question. 2. Par extension de mon argument, les fonctions imbriquées sont meilleures que les régions, oui. 3. Parce que j'ai parfois besoin de parcourir un certain nombre de révisions pour suivre un problème. Quoi qu'il en soit, le code source est écrit pour les humains, pas pour les IDE. 4. D'une part, l'argument n'a aucun rapport avec mon point de vue, deuxièmement, c'est encore une fois votre opinion, troisièmement, il sort du cadre de cette question. 5. C # a d'autres moyens de structurer le code que la fonction d'imbrication. Vous devez soit les utiliser, soit un langage qui autorise les fonctions d'imbrication.
back2dos
13
Vous devriez prendre ceci pour discuter si vous souhaitez toujours débattre ... Je n'ai plus rien à dire à l'OP, c'est un développeur junior typique et convaincu dans ses convictions. Rien ne changera d'avis mais plus d'expérience OMI.
maple_shaft
15

Ce ne sont pas les régions dans les méthodes qui posent problème, mais le cas quand il y a un besoin (ou même une utilisation) de mettre des régions dans les méthodes.

Ayant dû déboguer de nombreuses méthodes de ligne 200-300, je peux vous dire que je ne le souhaiterais à personne. Si vous écrivez et prenez soin de votre propre code, c'est bien - faites ce que vous voulez. Mais une fois que quelqu'un d'autre l'examine, il doit être immédiatement clair ce que fait une méthode.

"D'abord, il prend les choses, puis il les fait bouger, puis s'ils ont besoin de bourdonner, il le fait, sinon il vérifie s'ils sont bleus et inverse leur valeur Copernicus. Ensuite, si la deuxième chose est supérieure à la première, nous besoin d'obtenir la boîte de jus et de l'insérer ... "

Non, ce n'est pas suffisant. Décomposez-le en régions autant que vous voulez, mais je secoue toujours la tête en y pensant.

Si vous entrez dans les méthodes, vous obtenez de nombreux avantages:

  • Une meilleure compréhension de ce qui se passe où, même si ce n'est que par le nom de la méthode. Et vous êtes mal qu'une méthode ne peut pas être entièrement documenté - ajoutez le bloc de documentation (TIH ///) et entrez la description, les paramètres, le type de retour, et aussi exception, example, remarksnœuds détail ces scénarios. C'est là que ça va, c'est pour ça!
  • Il n'y a pas d'effets secondaires ou de problèmes de cadrage. Vous pouvez dire que vous déclarez toutes vos variables dans une sous-portée avec {}, mais dois-je vérifier chaque méthode pour vous assurer que vous n'avez pas «triché»? Est-ce que dodgyObjectj'utilise ici uniquement parce qu'il est utilisé dans cette région, ou est-ce que cela vient d'ailleurs? Si j'étais dans ma propre méthode, je serais facilement en mesure de voir si elle m'a été transmise ou si je l'ai créée moi-même (ou plutôt, si vous l'avez créée).
  • Mon journal des événements me dit dans quelle méthode une exception s'est produite. Oui, je peux peut-être trouver le code incriminé avec un numéro de ligne, mais connaître le nom de la méthode (surtout si je les ai nommés correctement) me donne une très bonne indication de ce qui s'est passé et ce qui s'est mal passé. "Oh, la TurnThingsUpsideDownméthode a échoué - elle échoue probablement en tournant une mauvaise chose" est beaucoup mieux que "Oh, la DoEverythingméthode a échoué - cela aurait pu être 50 choses différentes et je vais devoir fouiller pendant une heure pour la trouver" .

Tout cela avant tout problème de réutilisabilité ou d'improvisibilité. Des méthodes correctement séparées facilitent évidemment la réutilisation, et vous permettent également de remplacer facilement une méthode qui ne fonctionne pas (trop lente, trop boguée, dépendance changée, etc.). Avez-vous déjà essayé de refactoriser l'une de ces énormes méthodes? Il n'y a aucun moyen de savoir que ce que vous changez n'affectera rien d'autre.

Veuillez encapsuler correctement votre logique dans des méthodes de taille raisonnable. Je sais qu'il est facile pour eux de devenir incontrôlable, et affirmer que cela ne vaut pas la peine d'être repensé une fois à ce stade est un autre problème. Mais vous devez accepter le fait qu'il n'y a aucun mal et au moins un avantage potentiel à avoir des méthodes correctement encapsulées, rédigées de façon claire et simplement conçues.

Kirk Broadhurst
la source
L'analyse des commentaires XML de Visual Studio, avec les balises #region, relève de la catégorie des fonctionnalités de Visual Studio. Tout mon argument est qu'il n'est pas faux de s'appuyer sur ces fonctionnalités si tout le monde dans votre projet utilise Visual Studio. En ce qui concerne les effets secondaires et les problèmes de portée, vous pouvez toujours bousiller les choses avec les champs mondiaux. Dans les deux cas, vous devez vous fier aux programmeurs pour ne pas faire de bêtises avec des effets secondaires.
jjoelson
5
@jjoelson Vous pouvez toujours lire les commentaires XML sans Visual Studio, mais les balises de région sont presque complètement inutiles en dehors de VS. L'extension logique de votre argument est une méthode géante qui exécute l'intégralité de votre application, tant que vous l'avez séparée en régions!
Kirk Broadhurst
2
@jjoelson, s'il vous plaît, ne nous expliquez pas à quel point les champs mondiaux sont mauvais. Dire quelque chose n'est pas utile parce que vous avez une "solution de contournement" pour le bousiller de toute façon est tout simplement stupide. Gardez simplement les méthodes courtes et les variables de portée.
OliverS
@OliverS, Kirk est celui qui a évoqué l'état partagé en tant que problème avec mon schéma de régions dans une méthode. Fondamentalement, je disais exactement ce que vous dites: le fait qu'un programmeur puisse abuser de l'état en partageant trop de variables entre les régions n'est pas une mise en accusation de l'ensemble du schéma, tout comme la possibilité de bousiller l'état partagé entre les méthodes via les globaux n'est pas '' t une mise en accusation du schéma à méthodes multiples.
jjoelson
7

Si votre méthode est suffisamment complexe pour pouvoir être séparée en trois phases distinctes, non seulement ces méthodes devraient-elles être trois méthodes distinctes ... mais votre méthode devrait en fait être une classe distincte, dédiée à ce calcul.

"Mais alors ma classe n'aura qu'une seule méthode publique!"

Vous avez raison, et il n'y a rien de mal à cela. L'idée du principe de responsabilité unique est que votre classe fait une chose .

Votre classe peut appeler chacune des trois méthodes à tour de rôle et renvoyer le résultat. Une chose.

En bonus, votre méthode est désormais testable car ce n'est plus une méthode privée.

Mais peu importe une classe; en réalité, vous devriez en avoir quatre : un pour chacun des éléments de votre méthode, plus un qui prend chacun des trois comme dépendance et les appelle dans le bon ordre, renvoyant le résultat.

Cela rend vos classes encore plus testables. Cela vous permet également de changer facilement l'une de ces trois pièces. Écrivez simplement une nouvelle classe héritant de l'ancienne et remplacez le comportement modifié. Ou créez une interface pour le comportement de chacune de vos trois pièces; puis pour en remplacer un, écrivez simplement une nouvelle classe implémentant cette interface et remplacez-la par l'ancienne dans votre configuration de conteneur d'injection de dépendances.

Quelle? Vous n'utilisez pas l'injection de dépendance? Eh bien, vous n'en avez probablement pas encore vu le besoin, car vous ne suivez pas le principe de la responsabilité unique. Une fois que vous aurez commencé, vous constaterez que la façon la plus simple de donner à chaque classe ses dépendances est d'utiliser un conteneur DI.

MODIFIER :

OK, mettons de côté la question du refactoring. Le but de #regionest de masquer le code , ce qui signifie principalement du code qui n'a pas besoin d'être modifié dans des circonstances normales. Le code généré est le meilleur exemple. Il doit être masqué dans les régions, car vous n'avez généralement pas besoin de le modifier. Si vous en avez besoin, le fait d'agrandir une région vous donne un petit avertissement de style "Here be dragons" pour vous assurer que vous savez ce que vous faites.

Par conséquent, je dirais #regionqu'il ne faut pas l'utiliser au milieu d'une méthode. Si j'ouvre une méthode, je veux voir le code. L'utilisation de #region me donne un autre niveau de masquage dont je n'ai pas besoin, et cela devient une gêne: je déplie la méthode ... et je ne vois toujours pas de code.

Si vous craignez que les gens voient la structure de la méthode (et que vous refusez de la refactoriser), ajoutez des commentaires de bannière comme celui-ci:

//
// ---------- COMPUTE SOMETHING OR OTHER ----------
//

Ceux-ci aideront une personne parcourant le code à voir les différentes parties de votre méthode sans avoir à gérer les #regionbalises d' extension et de réduction .

Kyralessa
la source
2
Tout cela pour une méthode qui est appelée au même endroit? Même la plupart des lispers inconditionnels ne résumeront pas une fonction d'ordre supérieur tant qu'ils n'auront pas identifié au moins deux endroits où elle peut être utilisée pour définir plus facilement une fonction.
jjoelson
1
@jjoelson Est-il si difficile de créer une nouvelle classe? Qu'est-ce que c'est, une ligne, une orthèse d'ouverture et une orthèse de fermeture. Oh, et vous devez appuyerctrl+n
Kirk Broadhurst
2
Ce n'est pas qu'il est difficile de faire une nouvelle classe, mais il y a des frais généraux pour avoir une classe supplémentaire. C'est une couche d'indirection supplémentaire qui rend plus difficile pour un mainteneur de code de trouver ce qu'il cherche. Ce n'est pas si grave, mais cela ne vous achète rien dans le cas où ce morceau de code est peu susceptible d'être appelé de n'importe où ailleurs. Et, comme vous l' avez mentionné, il est assez facile de faire cette nouvelle classe et de mettre le code là s'il se avère que vous avez besoin d'appeler ce morceau de code à plusieurs endroits.
jjoelson
2
@jjoelson, c'est une réaction assez courante. C'était la mienne, lorsque j'ai appris pour la première fois des choses comme SRP et DI, et c'était la réaction de mes collègues lorsque nous avons commencé à briser les dépendances. Si vous examinez un cas individuel , cela ne semble pas en valoir la peine. L'avantage est global. Une fois que vous commencez à faire de la SRP avec toutes vos classes, vous constatez qu'il est beaucoup plus facile de modifier une partie de votre code sans que les modifications ne se répercutent sur la moitié de votre application.
Kyralessa
@ Kyralessa, ce sont des méthodes qui ne sont utilisées qu'en un seul endroit. La modification d'une telle méthode ne se répercutera pas sur la moitié de votre application. Si un tel code est implémenté en tant que région dans la méthode qui l'utilise, alors vous avez une encapsulation parfaite; seule la méthode contenant utilise le code et vous êtes donc libre de changer tout ce que vous voulez sans vous soucier de son effet, sauf dans cette méthode.
jjoelson
4

Je pense que l'exemple que vous donnez dans votre argument est moins sur YAGNI (vous n'en aurez pas besoin) et plus sur l'écriture d'un code de qualité approprié qui est facilement maintenable.

Dans les premiers cours de programmation, nous apprenons que si une méthode est longue de 700 LOC, elle est probablement trop grande et serait certainement une énorme douleur à essayer et à déboguer.

Deuxièmement, si j'écris les méthodes A, B et C qui ne sont utilisées que dans la méthode D, je peux plus facilement tester unitairement AB et C indépendamment de D, ce qui permet des tests unitaires plus robustes dans les 4 méthodes.

maple_shaft
la source
Les tests unitaires sont certainement un bon point, mais je ne suis pas sûr que cela justifie la pollution de la portée de la classe dans tous les cas. De façon réaliste, quelqu'un teste-t-il réellement chaque petite méthode privée qu'il écrit? Je dirais que les gens ont tendance à tester unitairement les méthodes privées qui sont souvent utilisées, c'est-à-dire les méthodes privées qui seraient de toute façon candidates à la réutilisation du code.
jjoelson
@jjoelson Si la méthode a une logique significative et n'encapsule pas d'autres fonctionnalités, j'écris toujours un test unitaire contre elle. Les méthodes de test unitaire n'ont rien à voir avec la réutilisation du code. Vous devez tester les méthodes de test unitaire pour vérifier que pour des entrées données, vous obtenez les sorties attendues de manière cohérente et répétable. Si vous remarquez que la portée de la classe est polluée comme vous l'appelez, alors votre classe viole peut-être le principe de responsabilité unique.
maple_shaft
2
La plupart des programmeurs que j'ai rencontrés ne sont pas d'accord avec l'idée de tester unitairement chaque méthode privée. Cela ne vaut tout simplement pas le temps qu'il faut pour implémenter et maintenir des tests sur toutes les méthodes privées.
jjoelson
3

Supposons que nous ayons une méthode dont le calcul peut être séparé en trois phases plutôt distinctes. De plus, chacune de ces étapes n'est pertinente que pour le calcul de cette méthode, et donc les extraire dans de nouvelles méthodes ne nous permet pas de réutiliser le code. Quels sont donc les avantages d'extraire chaque phase dans sa propre méthode? Pour autant que je sache, tout ce que nous gagnons est une certaine lisibilité et une portée variable distincte pour chaque phase (ce qui aidera à empêcher les modifications d'une phase particulière de casser accidentellement une autre phase).

Ce sont deux avantages. Mais l'important, pour moi en tout cas, c'est le débogage . Si vous devez suivre ce code, il est beaucoup plus simple de pouvoir passer au-dessus de deux des trois sections et de ne suivre que celle qui vous intéresse. La refactorisation en méthodes plus petites le permet; les balises de région ne le font pas.

Mason Wheeler
la source
1
ctrl-f10- courir vers le curseur
Steven Jeuris
2

Ma règle personnelle est que si une méthode est plus longue qu'un écran, disons 40 lignes, elle est trop longue. Si une classe dépasse 500 lignes, elle est trop grande. Je brise parfois ces règles, parfois même par un grand multiple, mais je le regrette généralement dans l'année.

Même une méthode de 20 à 30 lignes devient un peu longue dans la plupart des cas. Je dirais donc que l'utilisation de régions dans une méthode est généralement une mauvaise idée, tout simplement parce qu'il ne serait presque jamais logique de réduire une région de 20 à 30 lignes en plusieurs sous-régions.

La décomposition de fonctions longues selon cette définition présente au moins deux avantages:

  1. Vous pouvez mettre un nom sur ce que font ces sous-fonctions, ce qui clarifie votre pensée actuelle et simplifie la tâche des responsables ultérieurs.

  2. La décomposition en fonctions plus petites vous oblige à ne transmettre que les paramètres dont ces fonctions plus petites ont besoin, de sorte que l'étendue des données qu'elles nécessitent et modifient est très claire. Cela suppose que vous n'accédez pas et ne modifiez pas l'état d'objet dans une centaine de fonctions feuilles différentes, ce que je découragerais également.

D'après mon expérience, ces règles produisent du code qui est plus facile à écrire sans commettre d'erreurs courantes et peut être compris et modifié plus tard sans casser les comportements subtils. Peu importe si la personne qui doit comprendre / modifier le code est quelqu'un d'autre, ou moi-même après avoir dormi et tout oublié.

Je considérerais donc les régions dans les méthodes comme une "odeur de code" indiquant que des pratiques non durables sont appliquées. Comme toujours, il pourrait y avoir des exceptions, mais elles se produisent si rarement qu'elles ne valent presque pas la peine d'être discutées.

PeterAllenWebb
la source
2

C'est reparti ... Il y a plein d'autres sujets sur les programmeurs qui ont abouti à la même discussion.

Vous signalez des arguments très intéressants concernant les fonctions courtes. Ce n'est pas une déclaration populaire, mais je suis avec vous à ce sujet . Après en avoir souvent discuté auparavant, j'ai l'impression que la discussion se résume généralement à savoir si vous vous concentrez principalement sur une encapsulation appropriée ou si vous prenez le développement piloté par les tests au maximum. Ce sont les deux principaux prétendants à ce qui semble se révéler une autre guerre sainte, et je crains que nous ne soyons sous-alimentés.

Toutefois ...

À mon avis, la solution n'est certainement pas d'envelopper les «phases» dans les régions. Le pliage de code est utilisé pour balayer le code sous le tapis. Laissez le code tel quel, cela pourrait vous rappeler que vous voudrez peut-être refactoriser cela plus tard! Pour le relier à un argument dans votre question: comment pourrez-vous voir une opportunité de réutilisation de code si vous ne voyez aucun code? Les longs segments de code devraient être exactement cela, une épine dans l'œil qui donne envie de le refactoriser.

Comme remplacement approprié pour les régions, je suggère d'utiliser des paragraphes de code car Alex Papadimoulis les nomme dans un commentaire . Vous utilisez peut-être déjà une approche similaire. Ce sont simplement des blocs de code avec un en-tête de commentaire, expliquant ce que fait le bloc entier. Vous avez la lisibilité des fonctions, mais vous pouvez utiliser des phrases anglaises espacées normalement, et vous ne perdez aucune encapsulation.

Steven Jeuris
la source
Eh bien, j'utilise essentiellement des régions afin de délimiter les paragraphes de code (les régions peuvent avoir des commentaires qui sont visibles même lorsque le code est plié). J'aime utiliser des régions pour cela, car cela donne au mainteneur le choix de voir le code s'il veut examiner l'implémentation ou de le plier s'il ne veut voir que la "vue d'ensemble".
jjoelson
1

Bien que je convienne qu'il est généralement préférable de refactoriser le code que d'utiliser #region, ce n'est pas toujours possible.

Pour appuyer cette affirmation, permettez-moi de donner un exemple.

class Foo : IComparable
{
  private String name;
  private int foo;
  private Bar bar;

  public int CompareTo(Foo other)
  {
#region Ascending on name
     if (this.name < other.name) return -1;
     if (this.name > other.name) return 1;
#endregion
#region Usual order on bar
     int compBar = bar.compareTo(other.bar);
     if (compBar != 0) return compBar;
#endregion
#region Descending on foo
     if (this.foo > other.foo) return -1;
     if (this.foo < other.foo) return 1;
#endregion
     return 0; // equal
  }

Il est facile de réajuster les régions pour modifier l'ordre ou de les étendre lorsque des champs supplémentaires sont ajoutés à la classe. De toute façon, des commentaires sont nécessaires pour voir rapidement comment la commande est censée fonctionner. Et surtout: je ne vois pas comment le refactoring aidera la lisibilité dans ce cas.

Cependant, ces exceptions sont rares. Habituellement, il est possible de refactoriser, comme le disent de nombreuses autres réponses.

Sjoerd
la source
0

Je ne pense pas qu'il y ait une seule réponse pour expliquer pourquoi certaines personnes ou équipes décident de ne pas utiliser, #regionmais si je devais en énumérer quelques-unes, ce seraient les principales raisons que j'ai vues.

  • Les noms et l'ordre des régions rendent plus explicite l'ordre et l'organisation du code qui impose un style particulier qui peut devenir une source de conflits et de bikeshedding.
  • La plupart des concepts ne rentrent pas proprement dans un petit nombre de régions. En règle générale, vous commencez par les régions par les modificateurs d'accès public , privé, puis peut-être par type de membre (ex. Méthode, propriété, champ), mais qu'en est-il des constructeurs qui couvrent ces modificateurs, des variétés statiques de tous ces éléments, des membres protégés, des membres internes, des internes protégés membres, membres d'interface implicites, événements, etc. En fin de compte, vous auriez les classes les mieux conçues où vous avez un seul ou une méthode dans chaque région en raison de la catégorisation granulaire.
  • Si vous êtes capable de garder des choses pragmatiques et de ne regrouper les choses qu'en trois ou quatre types de régions constantes, cela peut fonctionner, mais quelle valeur cela ajoute-t-il vraiment? Si vous concevez bien des classes, vous ne devriez vraiment pas avoir besoin de parcourir les pages de code.
  • Comme indiqué ci-dessus, les régions peuvent masquer du code laid, ce qui peut le rendre moins problématique qu'il ne l'est. Le garder comme une douleur oculaire peut aider à le résoudre.
jpierson
la source