Sind #Regionen ein Antimuster oder ein Codegeruch?


265

C # ermöglicht die Verwendung von #region/ #endregionkeywords, um Codebereiche im Editor komprimierbar zu machen. Wann immer ich dies tue, tue ich es, um große Codestücke auszublenden, die wahrscheinlich in andere Klassen oder Methoden umgestaltet werden könnten. Zum Beispiel habe ich Methoden gesehen, die 500 Codezeilen mit 3 oder 4 Regionen enthalten, nur um es handhabbar zu machen.

Ist der umsichtige Umgang mit Regionen also ein Zeichen von Ärger? Mir scheint es so zu sein.


9
Zu Ihrer Information: CodeMap eliminiert praktisch den Bedarf an Regionen. visualstudiogallery.msdn.microsoft.com/… - Klicken Sie auf und Sie gelangen zur Methode / attribute / whatever. Ich benutze es jeden Tag und es ist erstaunlich, wie viel Sie an Produktivität und kognitiven Aspekten gewinnen. Sie erhalten eine viel klarere "Vogelperspektive" der Klasse.

7
Kann jemand dies zu einem Wiki machen? Es gibt keine richtige oder falsche Antwort auf diese Frage (na ja, im Rahmen der Vernunft), sie ist fast vollständig subjektiv.
Ed S.

6
Jeff Atwood hasst sie für das, was es wert ist . Er argumentiert, dass sie schlechten Code verstecken.
Brian

3
Code Geruch ist ein Entwickler, der nicht duscht und kein Deodorant verwendet!
Marko

5
Sorgfältig gestaltete Regionen in stinkendem Code sind das, was ein paar Spritzer Febreeze auf einer verkrusteten Couch bewirken. Es macht es erträglich, bis Sie das (Zeit-) Geld finden, um es zu ersetzen.
Newtopian

Antworten:


285

Ein Codegeruch ist ein Symptom, das darauf hinweist, dass das Design ein Problem aufweist, das möglicherweise die Anzahl der Fehler erhöht. Dies gilt nicht für Regionen, aber Regionen können wie lange Methoden zur Entstehung von Codegerüchen beitragen.

Schon seit:

Ein Antimuster (oder Antimuster) ist ein Muster, das in sozialen oder geschäftlichen Abläufen oder in der Softwareentwicklung verwendet wird und häufig verwendet wird, in der Praxis jedoch ineffektiv und / oder kontraproduktiv ist

Regionen sind Anti-Muster. Sie erfordern mehr Arbeit, was weder die Qualität noch die Lesbarkeit des Codes erhöht, die Anzahl der Fehler nicht verringert und die Umgestaltung des Codes möglicherweise komplizierter macht.

Verwenden Sie keine Regionen innerhalb von Methoden. Refactor statt

Methoden müssen kurz sein . Wenn eine Methode nur zehn Zeilen enthält, würden Sie wahrscheinlich keine Regionen verwenden, um fünf davon auszublenden, wenn Sie an den anderen fünf arbeiten.

Außerdem muss jede Methode eine und eine einzige Sache tun . Regionen hingegen sollen verschiedene Dinge trennen . Wenn Ihre Methode A und dann B ausführt, ist es logisch, zwei Regionen zu erstellen. Dies ist jedoch ein falscher Ansatz. Stattdessen sollten Sie die Methode in zwei separate Methoden umgestalten.

Die Verwendung von Regionen kann in diesem Fall auch das Refactoring erschweren. Stellen Sie sich vor, Sie haben:

private void DoSomething()
{
    var data = LoadData();
    #region Work with database
    var verification = VerifySomething();
    if (!verification)
    {
        throw new DataCorruptedException();
    }

    Do(data);
    DoSomethingElse(data);
    #endregion

    #region Audit
    var auditEngine = InitializeAuditEngine();
    auditEngine.Submit(data);
    #endregion
}

Das Einklappen der ersten Region, um sich auf die zweite zu konzentrieren, ist nicht nur riskant: Wir können leicht die Ausnahme vergessen, die den Fluss stoppt (es könnte eine Schutzklausel mit einem returnstattdessen geben, die noch schwieriger zu erkennen ist), sondern es würde auch ein Problem geben Wenn der Code auf diese Weise überarbeitet werden soll:

private void DoSomething()
{
    var data = LoadData();
    #region Work with database
    var verification = VerifySomething();
    var info = DoSomethingElse(data);

    if (verification)
    {
        Do(data);
    }

    #endregion

    #region Audit
    var auditEngine = InitializeAuditEngine(info);
    auditEngine.Submit(
        verification ? new AcceptedDataAudit(data) : new CorruptedDataAudit(data));
    #endregion
}

Jetzt machen Regionen keinen Sinn, und Sie können den Code in der zweiten Region möglicherweise nicht lesen und verstehen, ohne den Code in der ersten zu betrachten.

Ein anderer Fall, den ich manchmal sehe, ist dieser:

public void DoSomething(string a, int b)
{
    #region Validation of arguments
    if (a == null)
    {
        throw new ArgumentNullException("a");
    }

    if (b <= 0)
    {
        throw new ArgumentOutOfScopeException("b", ...);
    }
    #endregion

    #region Do real work
    ...
    #endregion
}

Es ist verlockend, Regionen zu verwenden, wenn die Validierung von Argumenten sich über mehrere zehn LOC erstreckt. Es gibt jedoch einen besseren Weg, um dieses Problem zu lösen: den, der vom .NET Framework-Quellcode verwendet wird:

public void DoSomething(string a, int b)
{
    if (a == null)
    {
        throw new ArgumentNullException("a");
    }

    if (b <= 0)
    {
        throw new ArgumentOutOfScopeException("b", ...);
    }

    InternalDoSomething(a, b);
}

private void InternalDoSomething(string a, int b)
{
    ...
}

Verwenden Sie zum Gruppieren keine Regionen außerhalb der Methoden

  • Einige Leute verwenden sie, um Felder, Eigenschaften usw. zu gruppieren. Dieser Ansatz ist falsch: Wenn Ihr Code StyleCop-kompatibel ist, sind Felder, Eigenschaften, private Methoden, Konstruktoren usw. bereits gruppiert und leicht zu finden. Wenn dies nicht der Fall ist, sollten Sie darüber nachdenken, Regeln anzuwenden, die die Einheitlichkeit Ihrer Codebasis gewährleisten.

  • Andere Leute benutzen Regionen, um viele ähnliche Wesen zu verbergen . Wenn Sie beispielsweise eine Klasse mit hundert Feldern haben (die mindestens 500 Codezeilen enthält, wenn Sie die Kommentare und das Leerzeichen zählen), könnten Sie versucht sein, diese Felder in eine Region einzufügen, sie zu reduzieren und sie zu vergessen. Wiederum machen Sie es falsch: Bei so vielen Feldern in einer Klasse sollten Sie besser über die Verwendung der Vererbung nachdenken oder das Objekt in mehrere Objekte aufteilen.

  • Schließlich sind einige Leute versucht, Regionen zu verwenden , um verwandte Dinge zu gruppieren : ein Ereignis mit seinem Delegierten oder eine Methode in Bezug auf E / A mit anderen Methoden in Bezug auf E / A usw. Im ersten Fall wird es zu einem Chaos, das schwer zu pflegen ist , lesen und verstehen. Im zweiten Fall wäre es wahrscheinlich besser, mehrere Klassen zu erstellen.

Gibt es eine gute Verwendung für Regionen?

Nein, es gab eine Legacy-Verwendung: generierten Code. Bei Tools zur Codegenerierung müssen jedoch nur Teilklassen verwendet werden. Wenn C # Regionen unterstützt, liegt dies hauptsächlich daran, dass diese Legacy-Verwendung verwendet wird, und dass es unmöglich ist, Regionen zu entfernen, ohne vorhandene Codebasen zu beschädigen, da zu viele Benutzer Regionen in ihrem Code verwendet haben.

Denken Sie darüber nach goto. Die Tatsache, dass die Sprache oder die IDE eine Funktion unterstützt, bedeutet nicht, dass sie täglich verwendet werden sollte. Die StyleCop SA1124-Regel ist klar: Sie sollten keine Regionen verwenden. Noch nie.

Beispiele

Ich führe gerade eine Codeüberprüfung des Codes meines Kollegen durch. Die Codebasis enthält viele Regionen und ist ein perfektes Beispiel dafür, wie Regionen nicht verwendet werden und warum Regionen zu schlechtem Code führen. Hier sind einige Beispiele:

4 000 LOC Monster:

Ich habe kürzlich irgendwo auf Programmers.SE gelesen, dass, wenn eine Datei zu viele usings enthält (nachdem der Befehl "Remove Unused Usings" ausgeführt wurde), dies ein gutes Zeichen dafür ist, dass die Klasse in dieser Datei zu viel tut. Gleiches gilt für die Größe der Datei.

Bei der Überprüfung des Codes bin ich auf eine 4 000 LOC-Datei gestoßen. Es stellte sich heraus, dass der Autor dieses Codes dieselbe 15-Zeilen-Methode einfach hunderte Male kopiert und dabei die Namen der Variablen und die aufgerufene Methode leicht geändert hat. Ein einfacher regulärer Ausdruck erlaubt das Trimmen der Datei von 4 000 LOC auf 500 LOC, indem nur ein paar Generika hinzugefügt werden. Ich bin mir ziemlich sicher, dass diese Klasse mit einem cleveren Refactoring auf ein paar Dutzend Zeilen reduziert werden kann.

Durch die Verwendung von Regionen ermutigte sich der Autor, die Tatsache zu ignorieren, dass der Code nicht gewartet und schlecht geschrieben werden kann, und den Code stark zu duplizieren, anstatt ihn umzugestalten.

Region "Do A", Region "Do B":

Ein weiteres hervorragendes Beispiel war eine Monster-Initialisierungsmethode, die einfach Aufgabe 1, dann Aufgabe 2, dann Aufgabe 3 usw. ausführte. Es gab fünf oder sechs Aufgaben, die völlig unabhängig voneinander waren und jeweils etwas in einer Containerklasse initialisierten. Alle diese Aufgaben wurden in einer Methode und in Regionen zusammengefasst.

Dies hatte einen Vorteil:

  • Die Methode war anhand der Regionsnamen ziemlich klar zu verstehen. Abgesehen davon wäre dieselbe Methode, die einmal überarbeitet wurde, genauso klar wie die ursprüngliche.

Die Probleme waren andererseits vielfältig:

  • Es war nicht offensichtlich, ob es Abhängigkeiten zwischen den Regionen gab. Hoffentlich gab es keine Wiederverwendung von Variablen; Andernfalls könnte die Wartung noch mehr zum Albtraum werden.

  • Die Methode war kaum zu testen. Wie können Sie leicht feststellen, ob die Methode, die zwanzig Dinge gleichzeitig ausführt, diese korrekt ausführt?

Felder Region, Eigenschaften Region, Konstruktor Region:

Der überprüfte Code enthielt auch viele Regionen, in denen alle Felder, alle Eigenschaften usw. zusammengefasst waren. Dies hatte ein offensichtliches Problem: das Wachstum des Quellcodes.

Wenn Sie eine Datei öffnen und eine große Liste von Feldern sehen, neigen Sie eher dazu, die Klasse zuerst umzugestalten und dann mit Code zu arbeiten. Bei Regionen hat man die Angewohnheit, Dinge zusammenzubrechen und zu vergessen.

Ein weiteres Problem ist, dass Sie, wenn Sie es überall tun, Ein-Block-Regionen erstellen, was keinen Sinn ergibt. Dies war tatsächlich der Fall in dem Code, den ich überprüft habe, in dem viele #region Constructoreinen Konstruktor enthielten.

Schließlich sollten Felder, Eigenschaften, Konstruktoren usw. bereits in Ordnung sein . Wenn dies der Fall ist und sie mit den Konventionen übereinstimmen (Konstanten, die mit einem Großbuchstaben beginnen usw.), ist bereits klar, an welcher Stelle der Elementtyp anhält und an welcher Stelle der andere beginnt, sodass Sie hierfür keine expliziten Regionen erstellen müssen.


13
Ich denke, es gibt mindestens ein paar vertretbare Verwendungen von #regions - z. B. das Ausblenden von Guard-Klauseln (Überprüfen von Eingabeparametern), die, wenn sie nicht zusammengefasst werden, den Kern oder das "Fleisch" der Methode beeinträchtigen. Ein weiteres Beispiel ist die Ausnahmebehandlung an API-Grenzen. Sie möchten die Stapelablaufverfolgung häufig nicht beeinflussen, indem Sie andere Methoden zum Umbrechen der Ausnahme aufrufen. Sie müssen also mehrere Codezeilen umbrechen und erneut werfen. Dies ist häufig auch nicht relevanter Code und kann sicher reduziert werden.
Daniel B

9
Reality-Check. Ich habe viele intermethodenbezogene Regionen gesehen, die hilfreich waren. Wenn Sie eine Methode mit mehreren Hundert Zeilen und verschachtelter Steuerlogik mit Dutzenden bis Hunderten von Zeilen in einigen von diesen haben - Gott sei Dank, der Idiot hat es zumindest in Regionen gebracht.
Radarbob

37
@radarbob: Kurz gesagt, Regionen sind hilfreich für beschissenen Code, der eigentlich gar nicht existieren sollte.
Arseni Mourzenko

41
-1 (wenn ich den Ruf hätte). Auch wenn Ihre Mitglieder gut organisiert und getrennt sind, kann es viele geben. Regionen ersparen es Ihnen, durch 10 oder 12 Eigenschaften und die zugehörigen Getter und Setter zu scrollen, um zu einer Methode zu gelangen, an der Sie arbeiten möchten. Die einzige Alternative besteht darin, alle Ihre Objekte einzeln zusammenzubrechen, wovon ich kein Fan bin. Das Anzeigen / Verbergen von Funktionsbereichen in großem Maßstab ist äußerst nützlich. In Bezug auf Regionen innerhalb der Methode stimme ich jedoch zu.
Asad Saeeduddin

14
Ich bin mit dieser Antwort absolut nicht einverstanden: Code-Gestank und Region haben nichts miteinander zu tun. Wenn Ihr Code stinkt, stinkt er mit oder ohne Regionen. Ich benutze Regionen, um meine Klassen in Regionen zu unterteilen. Im Allgemeinen halte ich mich jedoch an das gleiche Muster: Öffentliche Eigenschaften, Öffentliche Methoden, Private Felder, Private Methoden. Das ist die einzige Verwendung, für die ich Regionen hätte. Alles andere, Sie brechen wahrscheinlich SRP-Prinzipal in Ihrem Code.
Alexus

113

Es ist unglaublich für mich, wie viele Menschen Regionen so leidenschaftlich hassen !

Ich stimme so vielen ihrer Einwände voll und ganz #regionzu: Es ist eine schlechte Sache, Code in a zu schieben , um ihn vor dem Blick zu verbergen. #regionsEs ist eindeutig ein Fehler, eine Klasse in Klassen zu unterteilen, in denen sie umgestaltet werden soll. Das #regionEinbetten redundanter semantischer Informationen ist also redundant.

Aber keines dieser Dinge bedeutet , dass es etwas von Natur aus falsch mit Regionen in Ihrem Code verwenden! Ich kann nur annehmen, dass die meisten Leute Einwände haben, weil sie in Teams gearbeitet haben, in denen andere dazu neigen, IDE-Funktionen wie diese falsch zu verwenden. Ich habe den Luxus, allein in der Grundschule zu arbeiten, und ich schätze die Art und Weise, wie Regionen dazu beigetragen haben, meinen Workflow zu organisieren. Vielleicht ist es meine obsessive Zwangsstörung, aber ich mag es nicht, einen Haufen Code gleichzeitig auf meinem Bildschirm zu sehen, egal wie sauber und elegant es geschrieben sein mag. Die Trennung Dinge in logische Bereiche ermöglicht es mir , den Code zu kollabieren , die ich nicht kümmern auf dem Code zu arbeiten , die ich tunWert darauf legen. Ich ignoriere schlecht geschriebenen Code nicht, es macht keinen Sinn, ihn so zu überarbeiten, wie er ist, und die zusätzliche "Meta" -Organisation ist eher beschreibend als sinnlos.

Jetzt, da ich mehr Zeit in C ++ verbracht habe und direkter mit der Windows-API programmiert habe, wünsche ich mir, dass die Unterstützung für Regionen genauso gut ist wie für C #. Sie könnten argumentieren, dass die Verwendung einer alternativen GUI-Bibliothek meinen Code einfacher oder klarer machen würde, wodurch die Notwendigkeit beseitigt würde, irrelevantes Code-Rauschen vom Bildschirm zu entfernen, aber ich habe andere Gründe, dies nicht zu tun. Ich beherrsche meine Tastatur und meine IDE so gut, dass das Erweitern / Reduzieren des in Regionen unterteilten Codes weniger als einen Bruchteil einer Sekunde dauert. Die Zeit, die ich mir durch den Versuch, meinen bewussten Fokus auf den Code zu beschränken, an dem ich gerade arbeite, einspare, ist es mehr als wert. Es gehört alles in eine einzelne Klasse / Datei, aber es gehört nicht alles gleichzeitig auf meinen Bildschirm.

Der Punkt ist, dass #regionsdas Trennen und logische Teilen Ihres Codes nicht um jeden Preis zu vermeiden ist. Wie Ed betont, ist es kein "Codegeruch". Wenn Ihr Code riecht, können Sie sicher sein, dass er nicht aus den Regionen stammt, sondern aus dem Code, den Sie in diesen Regionen zu vergraben versucht haben. Wenn eine Funktion Ihnen hilft, besser organisiert zu sein oder besseren Code zu schreiben, dann sage ich, verwenden Sie sie . Wenn es zu einem Hindernis wird oder Sie feststellen, dass Sie es falsch verwenden, hören Sie auf , es zu verwenden. Wenn das Schlimmste zum Schlimmsten wird und Sie gezwungen sind, mit Leuten zusammenzuarbeiten, die es verwenden, merken Sie sich die Tastenkombination, um die Code-Gliederung zu deaktivieren: Ctrl+ M, Ctrl+P. Und hör auf dich zu beschweren. Manchmal habe ich das Gefühl, dass dies eine andere Art und Weise ist, wie sich diejenigen, die als "echte", "Hardcore" -Programmierer gesehen werden wollen, beweisen wollen. Sie sind nicht besser dran, Regionen zu meiden, als Syntaxfarben zu meiden. Es macht Sie nicht zu einem Macho-Entwickler.

Abgesehen davon sind Regionen innerhalb einer Methode einfach Unsinn. Jedes Mal, wenn Sie dies möchten, sollten Sie ein Refactoring in einer separaten Methode durchführen. Keine Ausreden.


9
Gut gesagt. Die Verwendung von Regionen für die Organisation ist nicht schädlicher als das Umschalten der Option "View Whitespace" der IDE. Es ist eine persönliche Präferenz.
Josh

24
Wenn ich in WPF mit ViewModels arbeite, die 10 oder 20 Eigenschaften haben, die einfach Eigenschaften in mein Modell einschließen, liebe ich Regionen - ich kann diese Eigenschaften einfach in einer Region verstecken (sie müssen nie berührt werden) und den relevanten Code im Auge behalten .
Kirk Broadhurst

4
Stimme voll und ganz zu. In .NET 2.0 sind Eigenschaften ungefähr 8-10 Zeilen lang. Wenn Sie mehr als 20 Eigenschaften in einer Klasse haben, nehmen diese viel Platz ein. Regionen sind perfekt, um sie zu reduzieren.
Kristof Claes

6
@Kristof: Ebenso wie Eigenschaften in .NET 4.0, die eine einfache Eingabevalidierung durchführen. Automatische Eigenschaften waren für meine Zwecke einfach nicht so magisch.
Cody Grey

8
Ich bin bereit, mit meinem linken Ball zu wetten, dass Leute, die Regionen hassen, entweder nie eine WPF-Anwendung entwickelt haben oder nie die WPF-Funktionen wie Datenbindung und Befehlsbindung wirklich genutzt haben. Das Einrichten Ihres Codes für diese Arbeit nimmt viel Platz in Anspruch, und Sie müssen sie im Allgemeinen nicht noch einmal ansehen.
l46kok

70

Zunächst einmal kann ich den Begriff "Codegeruch" nicht mehr aushalten. Es wird zu oft verwendet und wird oft von Leuten geworfen, die guten Code nicht erkennen konnten, wenn er sie biss. Sowieso...

Ich persönlich benutze nicht gerne viele Regionen. Es macht es schwieriger, an den Code zu kommen, und der Code interessiert mich. Ich mag Regionen, wenn ich einen großen Codestück habe, der nicht sehr oft berührt werden muss. Abgesehen davon scheinen sie mir nur im Weg zu stehen, und Regionen wie "Private Methods", "Public Methods" usw. machen mich einfach verrückt. Sie sind vergleichbar mit Kommentaren der Sorte i++ //increment i.

Ich möchte auch hinzufügen, dass die Verwendung von Regionen nicht wirklich ein "Anti-Pattern" sein kann, da dieser Begriff häufig zur Beschreibung von Programmlogik- / Designmustern und nicht zum Layout eines Texteditors verwendet wird. Das ist subjektiv; Verwenden Sie, was für Sie funktioniert. Sie werden nie mit einem nicht zu wartenden Programm enden, weil Sie Regionen überbeanspruchen. Genau darum geht es bei Anti-Patterns. :)


2
Normalerweise würde ich Sie für den Code-Geruch-Kommentar abstimmen, aber in diesem Fall ist er genau richtig. Nicht-Code kann kein Code-Geruch sein. +2!

7
Haha, ich will damit nicht sagen, dass der Begriff "Codegeruch" nicht richtig verwendet werden kann. Es kann, aber ich sehe, dass es heutzutage so viel herumwirbelt, dass meine unmittelbare Reaktion nur Ärger ist, besonders wenn es von Leuten kommt, die wirklich nur wiederholen, was sie hören, ohne es zu verstehen oder kritisch zu denken. Aussagen wie "mehr als 5 lokale Variablen in einer Funktion sind ein Codegeruch" zeigen nur, wie wenig Erfahrung diese Person tatsächlich hat.
Ed S.

13
Ich bin mir nicht sicher, ob ich Ihren Kommentar zu Codegerüchen verstehe. Code-Gerüche zeigen nicht an, dass ein Problem vorliegt. Möglicherweise liegt ein Problem vor.
Craig

7
+1 für die Aufrechterhaltung des Begriffs Code-Geruch. Ich hatte die Nase voll, als ich einen Post sah, in dem behauptet wurde, private Methoden seien ein Code-Geruch. Aber insgesamt bin ich mit Ihrer Abneigung gegen Regionen nicht einverstanden. Ich bin leicht abgelenkt. Tatsächlich würde ich es lieben, wenn VS einen VB4-Modus hätte, in dem Sie jeweils nur eine Methode anzeigen könnten.
Josh

7
Ich wollte nur mitreden und sagen, dass der Missbrauch einer vollkommen guten Metapher die Metapher nicht entwerten sollte. "Codegeruch" ist eine großartige Metapher, die sofort verstanden, leicht zu merken und leicht zu verwenden ist. Es gibt immer noch viele Stellen, an denen das Anwenden der Metapher "Codegeruch" immer noch der beste Weg ist, einen Punkt zu vermitteln.
Eric King

23

Ja, Regionen sind ein Codegeruch!

Ich würde mich freuen, wenn Regionen vollständig aus dem Compiler entfernt würden. Jeder Entwickler hat ein eigenes sinnloses Pflegesystem, das für einen anderen Programmierer niemals von Wert sein wird. Ich habe alles mit Programmierern zu tun, die ihr Baby schmücken und verschönern wollen, nichts mit echtem Wert.

Können Sie sich ein Beispiel vorstellen, in dem Sie allerdings "Meine Güte, ich wünschte, mein Kollege hätte einige Regionen hier verwendet!"

Obwohl ich meine IDE so konfigurieren kann, dass alle Regionen automatisch erweitert werden, sind sie immer noch schmerzhaft und beeinträchtigen das Lesen des tatsächlichen Codes.

Es ist mir wirklich egal, ob alle meine öffentlichen Methoden zusammengefasst sind oder nicht. Herzlichen Glückwunsch, Sie kennen den Unterschied zwischen einer Variablendeklaration und einer Initialisierung und müssen sie nicht im Code anzeigen!

Wertlose Pflege!

Wenn Ihre Datei außerdem eine Informationsarchitektur benötigt und Regionen verwendet werden, möchten Sie möglicherweise das Kernproblem bekämpfen: Ihre Klasse ist viel zu groß! Das Aufteilen in kleinere Teile ist viel vorteilhafter und fügt bei richtiger Ausführung eine echte Semantik / Lesbarkeit hinzu.


Sind #regions Teil des Compilers? Ich dachte, sie wären nur eine Anweisung an die IDE, die ignoriert werden könnte.
Steve Rukuts

2
Der Compiler muss sie ignorieren, wenn er Ihren C # -Code analysiert. Wenn es sie nicht ignoriert, würde es sich über sie übergeben. Ich meine es so.
Joppe

1
"Können Sie sich ein Beispiel vorstellen, in dem Sie allerdings" Meine Güte, ich wünschte, mein Kollege hätte einige Regionen hier verwendet! " Ja, sehr gerne. Wenn ich eine Klasse mit privaten Methoden und öffentlichen Methoden habe, teile ich sie in Regionen auf, da Sie beim Umgestalten der öffentlichen Methoden nicht unbedingt den privaten Code berühren müssen und umgekehrt.
Anshul

Offensichtlich haben Sie noch nie ausgelagerten Code gesehen. Sooo oft wären Regionen großartig in ausgelagertem Code zu sehen gewesen. Auch wenn der Code scheiße ist, wäre es viel einfacher gewesen, ihn zu verstehen, wenn er in einem logischen Sinn gruppiert gewesen wäre. Obwohl, wenn ihr Code nicht logisch ist, sind die Regionen es auch nicht, also hätte es wahrscheinlich noch schlimmer gemacht. Regionen sind jedoch großartig, wenn sie richtig verwendet werden.
Nickmccomb

15

Ich persönlich benutze Regionen, um verschiedene Arten von Methoden oder Codeteilen zusammenzufassen.

So könnte eine Codedatei beim Öffnen so aussehen:

  • Öffentliche Eigenschaften
  • Konstruktoren
  • Methoden speichern
  • Methoden bearbeiten
  • Private Hilfsmethoden

Ich setze Regionen nicht in Methoden ein. IMHO, das ist ein Zeichen für Code-Geruch. Ich bin einmal auf eine Methode gestoßen, die über 1200 Zeilen lang war und 5 verschiedene Regionen enthielt. Es war ein beängstigender Anblick!

Wenn Sie damit Ihren Code so organisieren, dass andere Entwickler schneller darauf zugreifen können, ist dies kein Anzeichen für Probleme. Wenn Sie es verwenden, um Codezeilen in einer Methode auszublenden, ist es an der Zeit, diese Methode zu überdenken.


14
Pfui. Ich weiß, dass dies ein subjektives Thema ist, aber Mann, ich kann dieses Schema wirklich nicht ausstehen. Meiner Erfahrung nach hilft die hinzugefügte "Organisation" überhaupt nicht und macht das Durchsuchen des Codes nur zu einer Nackenschmerzen. Ich bevorzuge auch Gruppierungsmethoden nicht nur nach Zugriffsmodifikator, sondern auch nach logischer Verantwortung. Für die öffentliche Schnittstelle gruppiere ich normalerweise jede Methode / Eigenschaft zusammen, aber oft ruft eine geschützte Methode eine private Hilfsfunktion auf, und in diesem Fall bevorzuge ich die Hilfsfunktion (die nur dort verwendet werden darf) oberhalb oder unterhalb der Methode, die es aufruft.
Ed S.

3
@ Ed S. - deshalb sagte ich "könnte so aussehen". Das ist sehr subjektiv. Ich sage nicht, dass jede Datei so aussehen sollte. Ich wäre überrascht, wenn sie es taten. Nur ein Beispiel zu einem komplexen Thema. :)
Tyanna

Oh ich weiß, wie ich sagte; es ist subjektiv. Was auch immer für Sie / Ihr Team funktioniert. Ich habe es gerade für dieses Schema herausgebracht, weil es (für mich) nicht funktioniert, aber ich musste ein Projekt aufrechterhalten, das genau dies tat. Es hat mich verrückt gemacht.
Ed S.

3
@EdS. Gehen Sie also in Ihre Optionen in vs und schalten Sie Regionen aus. Problem gelöst.
Andy

Warum haben Ihre Objekte Sicherungsmethoden? :(
TheCatWhisperer

10

Das Verwenden von #regionBlöcken, um eine sehr große Klasse lesbar zu machen, ist in der Regel ein Zeichen für einen Verstoß gegen das Prinzip der Einzelverantwortung. Wenn sie es gewohnt sind, Verhalten zu gruppieren, ist es auch wahrscheinlich, dass die Klasse zu viel tut (erneut gegen SRP verstößt).

Wenn man sich an die Gedankenlinie des "Code-Geruchs" hält, sind #regionBlöcke keine Code-Gerüche an sich, sondern eher "Febreze for Code", indem sie versuchen, Gerüche zu verbergen. Während ich sie in der Vergangenheit tonnenweise benutzt habe, werden Sie beim Refactoring weniger sehen, weil sie sich am Ende nicht viel verstecken.


5

Das Schlüsselwort hier ist "vernünftig". Es ist schwer vorstellbar, dass das Einfügen einer Region in eine Methode sinnvoll ist. das ist alles zu wahrscheinlich, um Code-Verstecken und Faulheit zu sein. Es kann jedoch gute Gründe dafür geben, hier und da einige Regionen im eigenen Code zu haben.

Wenn es sehr viele Regionen gibt, halte ich das für einen Codegeruch. Regionen sind oft ein Hinweis auf einen möglichen Ort für zukünftige Umgestaltungen. Viele Regionen bedeuten, dass jemand den Hinweis nicht wirklich versteht.

Mit Bedacht eingesetzt bilden sie einen guten Mittelweg zwischen der Struktur einer einzelnen Klasse mit vielen Methoden und der Struktur vieler Klassen mit nur wenigen Methoden. Sie sind am nützlichsten, wenn eine Klasse sich dem Punkt nähert, an dem sie in mehrere Klassen umgestaltet werden soll, aber noch nicht ganz da ist. Durch das Gruppieren verwandter Methoden wird es mir später einfacher, eine Reihe verwandter Methoden in ihre eigene Klasse zu extrahieren, wenn ihre Anzahl weiter zunimmt. Wenn ich zum Beispiel eine Klasse habe, die sich 500 Codezeilen nähert, ist diese Gruppe von Methoden mit insgesamt 200 Codezeilen, die in einer Region gesammelt wurden, wahrscheinlich ein gutes Stück, um sie irgendwie umzugestalten - und diese andere Region mit 100 Codezeilen Methoden könnten auch ein gutes Ziel sein.

Eine andere Möglichkeit, Regionen zu verwenden, besteht darin, einen der negativen Effekte der Umgestaltung einer großen Methode zu reduzieren: Viele kleine, prägnante und leicht wiederverwendbare Methoden, durch die ein Leser scrollen muss, um zu einer anderen, meist nicht verwandten Methode zu gelangen. Eine Region kann eine gute Möglichkeit sein, eine Methode und ihre Helfer für die Leser meta-einzukapseln, sodass jemand, der mit einem anderen Aspekt der Klasse arbeitet, sie einfach ausblenden und diesen Teil des Codes schnell verwerfen kann. Dies funktioniert natürlich nur, wenn Ihre Regionen wirklich gut organisiert sind und im Wesentlichen als eine andere Möglichkeit zur Dokumentation Ihres Codes verwendet werden.

Im Allgemeinen finde ich Regionen, die mir dabei helfen, mich zu organisieren, meinen Code zu "dokumentieren" und mir dabei helfen, Orte zu finden, an denen ich umgestalten kann, viel früher als wenn ich keine Regionen verwende.


4

Ich verwende hauptsächlich Regionen für CRUD-Serverklassen, um die verschiedenen Arten von Operationen zu organisieren. Selbst dann könnte ich gerne ohne sie gehen.

Wenn es ausgiebig verwendet wird, wird eine rote Fahne gehisst. Ich würde nach Klassen Ausschau halten, die zu viel Verantwortung tragen.

Nach meiner Erfahrung ist eine Methode mit hunderten Zeilen Code definitiv ein Geruch.


4

Meine Faustregel lautet: Wenn eine Datei mehr als 5 Regionen enthält, riecht es nach Code

Das heißt, es mag in Ordnung sein, Felder, Methoden, Eigenschaften und Konstruktoren abzugrenzen, aber wenn Sie damit beginnen, jede andere Methode in eine eigene Region zu packen, stimmt etwas nicht

..und ja, ich war an vielen Projekten beteiligt, bei denen das der Fall ist, oft aufgrund von schlechten Codierungsstandards, Codegenerierung oder beidem. Es wird schnell alt, alle Gliederungen in Visual Studio umschalten zu müssen, um einen guten Überblick über den Code zu erhalten.


4

REGIONEN HABEN IHRE VERWENDUNG

Ich habe sie zuvor für Windows Forms-Apps verwendet, um Ereignisse auf der Benutzeroberfläche von Hand zu codieren.

Bei meiner Arbeit verwenden wir jedoch einen Codegenerator für die Verarbeitung von SQL und er verwendet automatisch Regionen, um die ausgewählten, aktualisierten, gelöschten usw. Methodentypen zu sortieren.

Obwohl ich sie nicht oft benutze, eignen sie sich perfekt zum Entfernen großer Codestücke.


1
Ich habe ähnliche Codegeneratoren verwendet und bevorzuge die Verwendung von Teilklassen, um generierten Code zu entfernen.
Craig

Wir tun dies, die Regionen befinden sich im generierten Code, um das Lesen oder Debuggen zu vereinfachen (falls erforderlich).
Ken

4

Wenn Sie Regions- IN- Code haben, haben Sie sicherlich ein Problem (mit Ausnahme des generierten Codes). Wenn Sie Regions in Code einfügen, heißt das im Grunde "refactor this".

Es gibt jedoch auch andere Fälle. Eines, das mir einfällt, dass ich vor einiger Zeit gemacht habe: Ein Tisch mit ein paar tausend vorberechneten Gegenständen. Es ist eine Beschreibung der Geometrie, ohne einen Fehler in der Tabelle. Es wird nie eine Gelegenheit geben, sie anzusehen. Sicher, ich hätte die Daten von einer Ressource oder Ähnlichem erhalten können, aber das würde die Verwendung des Compilers zur Erleichterung des Lesens ausschließen.


1
Das ist ein besserer Anwendungsfall für eine Teilklasse, die in einer separaten Datei gespeichert ist, oder für eine injizierte IMyDataSource mit einer HardcodedDataSource-Implementierung.
Bryan Boettcher

3

Bei einem kürzlich durchgeführten Projekt gab es eine 1700-Linien-Methode, in die mehrere Regionen eingebettet waren. Das Interessante ist, dass die Regionen bestimmte Aktionen, die innerhalb der Methode durchgeführt wurden, ausgegrenzt haben. Ich konnte für jede Region eine Refactor-> Extrahierungsmethode durchführen, ohne die Funktionalität des Codes zu beeinträchtigen.

Im Allgemeinen sind Regionen nützlich, die zum Ausblenden des Kesselschildcodes verwendet werden. Ich würde davon abraten, Regionen zum Ausblenden von Eigenschaften, Feldern und dergleichen zu verwenden, da dies wahrscheinlich ein Zeichen dafür ist, dass die Klasse weiter unterteilt werden sollte, wenn sie für die Arbeit in der Klasse zu unhandlich sind. Wenn Sie jedoch eine Region in eine Methode einfügen, ist es wahrscheinlich besser, eine andere Methode zu extrahieren, die erklärt, was passiert, als diesen Block in eine Region zu brechen.


3

Können Regionen in Code mit guter Qualität verwendet werden? Wahrscheinlich. Ich wette, das sind sie in vielen Fällen. Meine persönlichen Erfahrungen lassen mich jedoch sehr misstrauisch werden - ich habe Regionen gesehen, die fast ausschließlich missbraucht wurden. Ich würde sagen, ich bin erschöpft, aber immer noch optimistisch.

Ich kann den Code, den ich bisher mithilfe von Regionscodes gesehen habe, grob in drei Kategorien unterteilen:

  • Code mit schlechtem Faktor: Der größte Teil des Codes, den ich gesehen habe, verwendet Regionen als Factoring-Tool für Arme. Beispielsweise kann eine Klasse, die zu einem Punkt herangewachsen ist, an dem es sinnvoll ist, sie für verschiedene Zwecke zu spezialisieren, stattdessen in separate Regionen aufgeteilt werden, eine für jeden Zweck.

  • Code, der mit den falschen Bibliotheken und manchmal in der falschen Sprache für die Problemdomäne geschrieben wurde Wenn ein Programmierer nicht die richtigen Bibliotheken für die Problemdomäne verwendet, wird der Code häufig unglaublich ausführlich - mit vielen kleinen Hilfsfunktionen die wirklich nicht gehören (sie gehören wahrscheinlich in ihre eigene Bibliothek).

  • Code von Studenten oder Absolventen geschrieben. Einige Programme und Kurse scheinen zu versuchen, die Schüler mit der Verwendung von Regionen für alle möglichen seltsamen Zwecke zu beleben. Sie werden Regionen sehen, die den Quellcode so weit verunreinigen, dass das Verhältnis von Regions-Tags zu Codezeilen im Bereich von 1: 5 oder schlechter liegt.


3

Ich würde sagen, es ist ein "Code-Geruch".

Anti-Patterns sind im Allgemeinen grundlegende strukturelle Probleme in einer Software, während Regionen für sich genommen nur ein unangenehmes Verhalten in einem Editor hervorrufen. Die Verwendung von Regionen ist an sich nicht schlecht, aber eine häufige Verwendung, insbesondere zum Verbergen von Codestücken, kann darauf hinweisen, dass an anderer Stelle andere, unabhängige und größere Probleme auftreten.


@ Andrew Grimm: Ja
Whatsisname

3

Ich verwende Regionen nur für eine Sache (zumindest kann ich mir keine anderen Orte vorstellen, an denen ich sie verwende): um Komponententests für eine Methode zu gruppieren.

Normalerweise habe ich eine Testklasse pro Klasse und gruppiere dann die Komponententests für jede Methode unter Verwendung von Regionen, die den Namen der Methode haben. Ich bin mir nicht sicher, ob dies ein Codegeruch oder etwas anderes ist, aber da die Grundidee darin besteht, dass Komponententests nicht geändert werden müssen, es sei denn, sie brechen, weil sich etwas im Code geändert hat, ist es für mich einfacher, alle Tests für eine bestimmte Methode zu finden ziemlich schnell.

Möglicherweise habe ich in der Vergangenheit Regionen zum Organisieren von Code verwendet, aber ich kann mich nicht erinnern, wann ich das letzte Mal damit gearbeitet habe. Ich halte mich jedoch an meine Regionen in Unit-Test-Klassen.


1
Haben Sie jemals Tests durchgeführt, bei denen mehrere Methoden getestet wurden?
Marcie

Ich verstehe die Frage oder was Sie damit anstreben nicht wirklich. Die Antwort lautet: Nein, ein Komponententest zielt immer nur auf eine Methode bzw. einen bestimmten Aspekt einer Methode ab.
Anne Schuessler

2

Ich glaube, das ist ein Anti-Muster und denke ehrlich, dass sie beseitigt werden sollten. Aber wenn Sie in der unglücklichen Situation sind, an einem Ort zu arbeiten, an dem es sich um einen Standard handelt, bietet Visual Studio ein hervorragendes Tool, um die Menge zu minimieren, die Sie jedes Mal erbrechen möchten, wenn Sie eine Region sehen, die ich hasse #Regionen

Dieses Plugin wird die Schriftgröße der Regionen wirklich klein machen. Sie werden auch erweitert, sodass Sie nicht die Tastenkombination Strg + M + L drücken müssen, um alle Regionen zu öffnen. Es behebt diese Form von Code-Krebs nicht, macht sie aber erträglich.


0

Ich verwende Regionen, um jede Kombination aus Sichtbarkeit und Elementtyp zu enthalten. So gehen alle privaten Funktionen in eine Region usw.

Der Grund, warum ich das tue, ist nicht, dass ich Code zusammenfalten kann. Das liegt daran, dass ich meinen Editor so geschrieben habe, dass ich beispielsweise einen Verweis auf einen Proxy einfügen kann:

#region "private_static_members"
 /// <summary>
 /// cache for LauncherProxy
 /// </summary>
private static LauncherProxy _launcherProxy;
#endregion

#region "protected_const_properties"
protected LauncherProxy LauncherProxy{
  get{
    if(_launcherProxy==null) {
      if (!God.Iam.HasProxy(LauncherProxy.NAME)) {
        God.Iam.RegisterProxy(new LauncherProxy());
      }
      _launcherProxy=God.Iam.Proxy(LauncherProxy.NAME) as LauncherProxy;
    }
    return _launcherProxy;
  }
}
#endregion

in den Code und lassen Sie jedes Teil ordentlich in die richtige Region stecken.

In diesem Fall würde das Makro mein Projekt analysieren, mir eine Listbox mit Proxies geben und den Code für den gewünschten Code einfügen. Mein Cursor bewegt sich nicht einmal.

Zu Beginn des Lernens von C # hatte ich die Verwendung von Regionen zum Zusammenhalten von Gemeinsamkeiten in Betracht gezogen. Dies ist jedoch ein Erfolgs- und Misserfolgsversuch, da es sich nicht immer um eine Eins-zu-Eins-Beziehung handelt. Wer möchte sich über ein Mitglied ärgern, das von zwei Regionen benutzt wird, oder sogar anfangen, die Dinge nach diesen Begriffen zu trennen?

Die einzige andere Art der Trennung sind Methoden. Ich werde Methoden in Befehle, Funktionen und Handler aufteilen, sodass ich einen Bereich für öffentliche, private usw. Befehle usw. habe.

Das gibt mir Granularität, aber es ist konsistente, eindeutige Granularität, auf die ich mich verlassen kann.


-1, sobald ich 125 Punkte zum Abstimmen bekomme. Sie fügen nicht benötigte Codezeilen hinzu. WARUM WARUM WARUM Würden Sie eine Region um ein Grundstück legen ... if (God.Iam.AbusingRegions () == true) myName = "Mark"
DeadlyChambers

1
@DeadlyChambers Der Grund wird im zweiten Absatz angegeben. Ich verwende Editor-Makros, um allgemeine Codemuster in die Datei einzufügen. Die Regionen helfen dabei, die Datei strukturiert zu halten, sodass ähnliche Elemente gruppiert werden. Ich lege keine Region um eine einzelne Eigenschaft, aber alle Eigenschaften fallen in eine bestimmte Region, abhängig von ihren Attributen "protected_const_properties". Hast du den Beitrag gelesen?
Mark

1
Sie können das wahrscheinlich umgestalten in: protected LauncherProxy LauncherProxy => God.Iam.GetOrAddProxy <LauncherProxy> (ref _launcherProxy); und somit brauchst du jetzt keine region. _LauncherProxy kann auch in _launcherProxyCache umbenannt werden, sodass Sie dort weder Region noch Kommentar benötigen.
Aeroson

0

Regionen sind Präprozessorausdrücke - dh sie werden wie Kommentare behandelt und vom Compiler im Grunde genommen ignoriert. Sie sind lediglich ein visuelles Werkzeug, das in Visual Studio verwendet wird. Daher ist #region eigentlich kein Codegeruch, weil es einfach kein Code ist. Der Code-Geruch ist eher die 800-Zeilen-Methode, in die viele verschiedene Verantwortlichkeiten eingebettet sind. Wenn Sie also 10 Regionen in einer Methode sehen, wird sie wahrscheinlich verwendet, um einen Code-Geruch zu verbergen. Trotzdem habe ich gesehen, dass sie extrem effektiv eingesetzt wurden, um eine Klasse attraktiver und navigierbarer zu machen - auch in einer sehr gut geschriebenen und strukturierten Klasse!


0

Regionen waren eine raffinierte organisatorische Idee, berücksichtigten jedoch nicht alle Entwicklertendenzen, die nach den meisten modernen OOP-Praktiken eine Überkategorisierung erfordern und im Allgemeinen unnötig sind dass Ihre Klasse / Methode viel zu groß ist und überarbeitet werden sollte, da Sie wahrscheinlich das "S" der SOLID-Prinzipien verletzen ... aber wie jeder Geruch bedeutet das nicht unbedingt, dass etwas schief geht.

Regionen dienen eher dem funktionalen Code als dem objektorientierten Code, IMO, wo Sie lange Funktionen für sequentielle Daten haben, deren Aufteilung sinnvoll ist, aber ich habe sie manchmal persönlich in c # verwendet, und fast immer Konzentrieren Sie sich auf Code, den Sie nicht ansehen müssen / wollen. Für mich waren dies normalerweise rohe SQL-Zeichenfolgenkonstanten in der Codebasis, die für NPoco oder seine Varianten verwendet wurde. Wenn Sie sich nicht wirklich darum kümmern, wie die Daten das POCO-Objekt über Ihr ORM ausfüllen, war es völlig sinnlos, diese zu betrachten ... und wenn Sie sich darum kümmern, hey, erweitern Sie einfach die Region und die BAM! Mehr als 150 Zeilen komplizierter SQL-Abfragen für Ihr Sehvergnügen.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.