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 if
fü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.
quelle
Antworten:
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.
quelle
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 .
quelle
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.quelle
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 .
quelle
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
if
Anweisung 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 langeif-else
Kette 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?quelle
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.
quelle
Es kommt darauf an, wie viel Zeit damit verbracht wird, Code zu betrachten (Gehirnzyklen) und zu verstehen, was der Code tut.
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.
quelle