Warum ist die zyklomatische Komplexität für eine einzelne Methode so wichtig?


10

Ich verwende SonarLint seit kurzem für Eclipse und es hat mir sehr geholfen. Es warf mir jedoch eine Frage zur zyklomatischen Komplexität auf.

SonarLint hält einen CC von 10 für akzeptabel, und es gibt einige Fälle, in denen ich darüber hinaus bin, etwa 5 oder 6 Einheiten. Diese Teile beziehen sich auf Mapper, bei denen die Werte auf verschiedenen Variablen beruhen, zum Beispiel:

  • Feld A basiert auf String sA;
  • Feld B basiert auf String sB;
  • Feld C basiert auf String sC;
  • usw ...

Ich habe keine andere Wahl, als iffür jedes Feld eine zu setzen. Dies ist (zum Glück) nicht meine Wahl, sondern ein bereits existierendes und komplexes System, das ich selbst nicht ändern kann.


Der Kern meiner Frage ist: Warum ist es so wichtig, in einer einzigen Methode keinen zu hohen CC zu haben ? Wenn Sie einige Ihrer Bedingungen in eine oder mehrere Untermethoden verschieben, um die Komplexität zu verringern, werden die Kosten Ihrer Gesamtfunktion nicht gesenkt, sondern das Problem wird nur an eine andere Stelle verschoben, denke ich?

(Entschuldigung für kleine Fehler, falls vorhanden).


BEARBEITEN

Meine Frage bezieht sich nicht auf die globale zyklomatische Komplexität, sondern nur auf die Komplexität einzelner Methoden und die Aufteilung von Methoden (es fällt mir schwer zu erklären, was genau ich meine, sorry). Ich frage mich, warum es zulässig ist, Ihre Bedingungen in kleinere Methoden aufzuteilen, wenn sie noch zu einer "Supermethode" gehören, die nur jede Untermethode ausführt und so den Algorithmus komplexer macht.

Der zweite Link ( über das Anti-Muster ) ist jedoch eine große Hilfe.




^^^ "Pfeilspitze" -Frage ist wahrscheinlich ein besseres Duplikat in dem Sinne, dass sie erklärt, wie Sie Ihren Code verbessern können, aber ich habe die erste ausgewählt, weil ich den Teil Ihrer Frage zur zyklomatischen Komplexität ausführlich erklärt habe
Mücke

Das Aufteilen einer Methode in kleinere Teile reduziert nicht die Gesamtmenge des ausgeführten Codes, sondern verdeutlicht die einzelnen Aufgaben, die gerade ausgeführt werden. Sie können jeweils viel einfacher einzeln verstanden werden, als wenn sie alle in einem größeren Ganzen verwickelt sind. Zumindest werden viele einmalige Zwischenvariablen aus dem größeren Bereich entfernt.
Doval

1
Für Ihren speziell beschriebenen Fall würde ich in Ihrer primären Methode etwas tun, wie "A = extractAFrom (sA);" für jedes Feld. Sie können sich wahrscheinlich bessere Namen einfallen lassen, da Sie die tatsächlichen Felder und ihre Verwendung kennen.
Tin Man

Antworten:


32

Das Kernstück hier: "Gehirnkapazität".

Sie sehen, eine der wichtigsten Funktionen des Codes ist ... zu lesen . Und Code kann leicht zu lesen und zu verstehen sein. oder schwer.

Und ein hoher CC impliziert einfach viele "Ebenen" innerhalb einer Methode. Und das bedeutet: Sie als menschlicher Leser werden es schwer haben, diese Methode zu verstehen.

Wenn Sie den Quellcode lesen, versucht Ihr Gehirn automatisch, die Dinge ins rechte Licht zu rücken: Mit anderen Worten, es versucht, eine Art "Kontext" zu schaffen.

Und wenn Sie eine kleine Methode (mit einem guten Namen) haben, die nur aus wenigen Zeilen und einem sehr niedrigen CC besteht; dann kann Ihr Gehirn diesen "Block" leicht akzeptieren. Du liest es, du verstehst es; ERLEDIGT.

Auf der anderen Seite, wenn Ihr Code einen hohen CC hat, wird Ihr Gehirn viele, viele "Zyklen" mehr verbringen, um abzuleiten, was los ist.

Eine andere Art zu sagen: Sie sollten sich immer dazu neigen, ein komplexes Netzwerk einfacher Dinge einem einfachen Netzwerk komplexer Dinge vorzuziehen . Weil Ihr Gehirn kleine Dinge besser versteht.


9
Im Grunde geht es also nicht um technische Fragen, sondern um Menschen ? Das klingt in der Tat irgendwie klug, ich weiß nicht, wie ich vorher nicht daran gedacht habe. Vielen Dank !
Yassine Badache

4
In diesem Fall empfehle ich Ihnen von ganzem Herzen, "Clean Code" von Robert Martin zu erwerben (das PDF finden Sie möglicherweise kostenlos in den Netzen). Sie sehen, das Erstellen von lesbarem Code ist eine der wichtigsten, aber sehr oft ignorierten Tugenden eines guten Programmierers.
GhostCat begrüßt Monica C.

@YassineBadache CC macht es auch schwierig, jeden Winkel und jede Ecke zu testen (vollständige Abdeckung).
Tulains Córdova

Dies war auch der Kern von Dijkstras Goto-Papier .
Seth Battin

Nach meiner Erfahrung treten Fehler fast immer in Methoden mit hohem CC auf, und wenn Fehler in einer Methode mit niedrigem CC auftreten, sind sie normalerweise völlig offensichtlich und können sich nach dem ersten Durchlauf des Codes nicht mehr verstecken. Außerdem muss ich fast nie eine Low-CC-Methode modifizieren - mehr Belastung für das Gehirn.
Loren Pechtel

6

CC ist wie alle anderen Faustregeln für Codegerüche eine Heuristik . Es ist kein ausfallsicheres Kriterium, das Ihnen eine absolute Wahrheit sagt. Wenn dies der Fall wäre, wäre es vernünftig, solche Methoden einfach in der Sprache illegal zu machen und die Menschen zu zwingen, ihre Ziele auf andere Weise zu erreichen.

Aber so funktionieren Indikatoren nicht. Meistens besteht ihre Aufgabe darin, Menschen auf Dinge aufmerksam zu machen, die ihnen nicht bewusst waren. In Ihrem Fall sind Sie sich bewusst, dass die Logik kompliziert ist und die alternativen Lösungen sie noch komplizierter machen würden. Daher macht es keinen Sinn, zu versuchen, die primitive Faustregel zu erfüllen, wenn ihr Hauptzweck darin besteht, Warnungen an Personen zu senden, die sich eines Problems nicht bewusst sind .


2
Wenn "FieldA auf String sA angewiesen ist", wie OP angibt, bin ich nicht davon überzeugt, dass das Verschieben in einen CalculateFieldA (String sA) zu einem komplizierteren Code führt.
Taemyr

2

Kurz gesagt: Es geht um Lesbarkeit und damit um Wartbarkeit Ihres Codes.

Wenn Sie eine lange, komplexe Methode mit vielen (verschachtelten) Methoden haben if, ist es schwierig zu sagen, was sie tatsächlich tut. Wenn Sie einige private Methoden extrahieren und sie sinnvoll benennen, ist dies viel einfacher.


Dies ist zwar eine gute Antwort, aber ein bisschen kurz. Es wäre schön, wenn Sie ein Beispiel für das geben könnten, was Sie sagen, und genauer auf die von OP gestellte Frage eingehen könnten: "Warum ist es so wichtig, in einer einzigen Methode keinen zu hohen CC zu haben?".
Machado

2

Die zyklomatische Komplexität einer Methode hängt von der Anzahl der für eine Methode erforderlichen Testfälle ab. Insbesondere bedeutet eine zyklomatische Komplexität von 10, dass 10 die Obergrenze für Testfälle ist, um eine vollständige Verzweigungsabdeckung für Ihre Methode zu erhalten. Dies hängt auch mit der Anzahl der zu testenden Pfade ab, abzüglich aller unmöglichen Pfade.

Darüber hinaus stimme ich den anderen Antworten für andere Überlegungen zu - die geistige Leistungsfähigkeit eines Entwicklers oder ein Indikator für potenzielle Probleme oder Refactoring oder ein Maß für die Lesbarkeit und Wartbarkeit des Codes .


0

CC ist nur eine Heuristik, und wie schlecht eine bestimmte Punktzahl ist, hängt von vielen Dingen ab.

Das heißt, Sie sollten einen hohen CC immer als etwas betrachten, das Code hervorhebt, der überarbeitet werden könnte / sollte. Sie sagen, dass das Verschieben der ifAnweisung auf eine andere Methode das Problem verbirgt - aber gibt es dort ein Muster, das Sie abstrahieren können, anstatt n-mal zu kopieren? Wenn es eine lange if-elseKette ist, können Sie daraus eine switch-Anweisung machen oder vielleicht Polymorphismus oder etwas anderes verwenden? Wenn es eine tiefe Verschachtelung gibt, können einige Ihrer Bedingungsklauseln verbunden werden, oder gibt es separate Verantwortlichkeiten an, die in verschiedene Klassen aufgeteilt werden sollten?


0

Ich sehe die zyklomatische Komplexität als Warnung. Wenn Sie den Code lesen können und er nicht zu komplex ist, um ihn zu verstehen, würde ich mir keine Sorgen machen. Es gibt wahrscheinlich wichtigere Dinge, über die Sie sich Sorgen machen müssen. Es gibt immer solche.

Eine Möglichkeit, die von Ihnen erwähnte Art von CC zu reduzieren, ist die Verwendung von Polymorphismus, da Sie Ihre Frage mit dem Java-Tag versehen haben. Anstatt Codepfade strikt einzugeben , können Sie auch gut benannte Klassen verwenden. Dies kann helfen, ist aber manchmal übertrieben und kann das Verständnis Ihres Codes noch erschweren.

Dies kann jedoch ein Zeichen für Code sein, der schwer zu warten ist. Ist beim Lesen der Methode leicht zu erkennen, welchen Codepfad Sie für jeden Fall verwenden werden? Könnten Sie diese Methode überspringen, wenn Sie die Codebasis nicht gut kennen und nach etwas Ähnlichem suchen, aber weiter unten im Code? Ich weiß, dass einige Leute befürworten, Methoden in viele 1/2-Zeilen-Methoden mit beschreibenden Namen aufzuteilen, aber manchmal denke ich, dass dies noch schwieriger zu lesen ist als der Code, den er ersetzen sollte.

Letztendlich ist die Wartbarkeit ein schwieriges Problem und es liegt an Ihnen, zu entscheiden, welche Ihrer Meinung nach leichter zu lesen ist. Die Tatsache, dass Sie überhaupt darüber nachdenken, bedeutet, dass Sie auf dem richtigen Weg sind. Denken Sie daran, der Betreuer, der in einem Jahr versuchen muss, diesen Code zu entschlüsseln, könnten Sie sein. Machen Sie es ihnen so einfach wie möglich.


0

Es kommt darauf an, wie viel Zeit damit verbracht wird, Code zu betrachten (Gehirnzyklen) und zu verstehen, was der Code tut.

  • Betrachten Sie eine 10-Zeilen-Methode - Nehmen Sie sich wahrscheinlich ein paar Minuten Zeit, um zu verstehen, was sie tut.
  • Betrachten Sie eine 100-Zeilen-Methode - Nehmen Sie sich wahrscheinlich eine Stunde oder länger Zeit, um zu verstehen, was gerade passiert.
  • Betrachten Sie eine 1000-Zeilen-Methode - Nehmen Sie sich wahrscheinlich einen Tag oder länger Zeit, um zu verstehen, was gerade passiert.

Auch größere Methoden sind schwerer zu testen und schwerer vorherzusagen, welche Art von Verhalten auftreten könnte.

Die zyklomatische Komplexität ist ein Maß. In diesem Fall sind höhere Werte Indikatoren für potenzielle Probleme. Komplexer Code braucht länger, um zu verstehen, und wird wahrscheinlich nicht so gründlich getestet wie weniger komplexe Methoden. Daher ist es wichtig zu beachten, welche Bereiche des Codes mit dieser Maßnahme für Refactoring- und Wartungszwecke komplex sind.

Eine andere zu berücksichtigende Sache ist das Aktualisieren von komplexem Code. Bei der Analyse könnte ein Entwickler melden, dass das Ändern des Codes mehr oder weniger riskant ist, wenn man seine Komplexität betrachtet.

Die Messung der Komplexität ist daher von großem Wert, da sie genutzt und für Entscheidungszwecke verwendet werden kann.


1
Sorry Ghost Cat Antwort sehr ähnlich, sollte Seite aktualisiert haben.
Jon Raynor
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.