In meiner vorherigen Frage zur Einfachheit in Bezug auf die Lesbarkeit gab es viele Antworten , die mir geholfen haben, zu erkennen, dass meine Definition und mein Verständnis der Einfachheit im Code möglicherweise falsch waren.
Wie kann ich Einfachheit im Code definieren? Welche Softwaremessungen und -metriken stehen zur Verfügung, um die Code-Einfachheit zu messen?
code-quality
Richard
quelle
quelle
Antworten:
Die gebräuchlichsten Metriken zum Messen der Komplexität (oder Einfachheit, wenn Sie davon ausgehen, dass Einfachheit das Gegenteil von Komplexität ist) sind McCabes Cyclomatic Complexity und die Halstead Complexity Metrics .
Die zyklomatische Komplexität misst die Anzahl unterschiedlicher Pfade durch eine bestimmte Einheit, normalerweise eine Methode oder Funktion, obwohl sie auch für eine Klasse berechnet werden kann. Mit zunehmender Anzahl von Pfaden wird es schwieriger, sich an den Datenfluss durch ein bestimmtes Modul zu erinnern, der mit dem Konzept des Arbeitsspeichers zusammenhängt . Eine hohe zyklomatische Komplexität deutet auf Schwierigkeiten beim Testen eines Moduls hin. Es sind mehr Testfälle erforderlich, um die verschiedenen Pfade durch das System abzudecken. Es gab auch Studien, die eine hohe zyklomatische Komplexität mit hohen Fehlerraten in Verbindung brachten. In der Regel bedeutet eine zyklomatische Komplexität von 10, dass eine Einheit überprüft und möglicherweise überarbeitet werden sollte.
Bei den Halstead-Komplexitätsmessungen werden die Eingaben von gesamten und verschiedenen Operatoren und Operanden verwendet, um das Volumen, den Schwierigkeitsgrad und den Aufwand eines Codeteils zu berechnen. Die Schwierigkeit (Anzahl der eindeutigen Operatoren / 2) * (Gesamtanzahl der Operanden / Anzahl der eindeutigen Operanden) hängt mit der Fähigkeit zusammen, den Code für Aufgaben wie das Erlernen des Systems oder das Durchführen einer Codeüberprüfung zu lesen und zu verstehen. Sie können dies wiederum auf Systemebene, Klassenebene oder Methoden- / Funktionsebene zählen. Es gibt hier und hier einige Veröffentlichungen zur Berechnung dieser Messungen .
Durch einfaches Zählen von Codezeilen erhalten Sie auch eine Vorstellung von der Komplexität. Mehr Codezeilen bedeuten, dass in einem Modul mehr zu lesen und zu verstehen ist. Ich würde zögern, dies als eigenständige Messung zu verwenden. Stattdessen würde ich es mit anderen Messungen verwenden, z. B. der Anzahl der Fehler in einem bestimmten Modul, um die Fehlerdichte zu erhalten. Eine hohe Fehlerdichte kann auf Probleme beim Schreiben von Tests und beim Durchführen von Codeüberprüfungen hinweisen, die möglicherweise durch komplexen Code verursacht werden.
Fan-In und Fan-Out sind zwei weitere Metriken, die sich auf den Datenfluss beziehen. Wie hier definiert , ist Fan-In die Summe der aufgerufenen Prozeduren, der gelesenen Parameter und der ausgelesenen globalen Variablen. Fan-Out ist die Summe der Prozeduren, die eine bestimmte Prozedur aufrufen. und globale Variablen geschrieben. Auch hier kann ein hohes Ein- und Ausblenden der Lüfter ein Hinweis darauf sein, dass das Modul möglicherweise schwer zu verstehen ist.
In bestimmten Paradigmen gibt es möglicherweise andere Kennzahlen oder Metriken, die ebenfalls nützlich sind. In der objektorientierten Welt können beispielsweise die Überwachung der Kopplung (Wunsch niedrig), der Kohäsion (Wunsch hoch) und der Vererbungstiefe (Wunsch niedrig) verwendet werden, um zu beurteilen, wie einfach oder kompliziert ein System ist.
Natürlich ist es wichtig zu wissen, dass viele Messgrößen und Metriken lediglich Indikatoren sind. Sie müssen Ihr Urteilsvermögen einsetzen, um festzustellen, ob eine Umgestaltung erforderlich ist, um die Einfachheit zu erhöhen, oder ob sich die Mühe nicht lohnt, dies zu tun. Sie können die Messungen vornehmen, die Metriken berechnen und mehr über Ihren Code erfahren, möchten Ihr System jedoch nicht anhand der Zahlen entwerfen. Letztendlich mach was Sinn macht.
quelle
Anstatt einen formalen Modus zur Definition von Einfachheit zu betrachten, möchte ich Einfachheit eher als ein Attribut der Qualität des Code-Schreibens definieren.
Ich lege kein Maß an Einfachheit an, aber wann nennst du etwas Einfaches oder nicht?
1. Code Traversal:
Wie einfach ist es, durch den Code zu navigieren? Ist es leicht zu erkennen, wo die API-Funktionen geschrieben sind? Ist es einfach, Anrufabläufe zu verstehen, z. B. welche Methoden andere aufrufen (und warum) - sind gute Zustandsautomaten implementiert oder Algorithmen sauber identifiziert?
Wenn die Codeüberquerung einfach ist, ist der Code einfach zu befolgen.
2. Benennung
Während andere Codierungsstandards dazu beitragen, dass der Code übersichtlicher aussieht, ist die Benennung von Klassen / Objektinstanzen / Variablen / Methoden das Wichtigste. Die Verwendung klarer und eindeutiger Namen hat eindeutig einen großen Einfluss auf die Einfachheit des Codes. Wenn es schwierig ist, einen einfachen Namen zu identifizieren, ist dies ein Zeichen dafür, dass Sie die Idee dieser Variablen / Methode überdenken möchten.
3. Interpretation und Referenzen
Hat jede Ihrer Methoden eine klare Rolle zu spielen. Sind die einzelnen Variablen / Attribute leicht zu bestimmen, welche Rolle sie spielen? Wenn ein Teil des Codes etwas tut, das Annahmen impliziert oder sich auf nicht verwandte Variablen auswirkt, kann dies zu einem Alptraum für die Wartung werden.
4. Abhängigkeit oder Kopplung
Dies ist nur anhand des Codes schwer zu beurteilen, wird jedoch sehr deutlich, wenn jemand versucht, Ihre Fehler zu beheben. Wenn sich einige andere Dinge in einem anderen Objekt ändern, ändert sich die Operation hier? Sind diese Änderungen offensichtlich? Müssen Sie die API so oft ändern, um Inhalte aufzunehmen? Dies legt nahe, dass Intermodulbeziehungen nicht einfach sind
5. Benutzereingaben oder Anwendungen
Wie einfach sind die Benutzereingaben oder Anwendungen, die auf der API / UI akzeptiert werden? Wenn Sie mehrere mögliche Benutzer / Anwendungen (für verschiedene Zwecke) angeben müssen - liegen sie auf der Hand? Gibt es Zustände / Details, die sich nicht auf die höhere Abstraktion beziehen, aber dennoch die Schnittstelle hin und her bewegen?
Eine einfache Frage, die ich im Allgemeinen stellen würde, lautet wie folgt: Wenn ich anstelle eines Programms die gleiche von einem Menschen auszuführende Funktion gewünscht hätte, hätte ich diese Informationen auf einem Papierformular ausgefüllt ? Wenn nicht, bin ich hier nicht einfach genug.
Ich werde nicht sagen, dass diese Liste vollständig ist, aber ich denke, Kriterien sind, wie einfach oder schwierig es ist, die Software zu verwenden und zu modifizieren. Das ist einfach
quelle
Mir sind keine guten vorhandenen Metriken zur Vereinfachung des Codes bekannt (das bedeutet nicht, dass sie nicht existieren - nur, dass ich nichts über sie weiß). Ich könnte einige vorschlagen, vielleicht werden einige helfen:
Einfachheit der verwendeten Sprachfunktionen: Wenn die Sprache Funktionen enthält, die als "erweitert" und "einfach" eingestuft werden können, können Sie die Häufigkeit der erweiterten Funktionen zählen. Wie Sie "fortgeschritten" definieren, ist möglicherweise etwas subjektiver. Ich nehme an, einige könnten sagen, dass dies auch der Messung der "Klugheit" eines Programms gleicht. Ein häufiges Beispiel: Einige könnten sagen, dass der
?:
Operator eine "erweiterte" Funktion sein sollte, andere könnten anderer Meinung sein. Ich weiß nicht, wie einfach es wäre, ein Tool zu schreiben, das dies testen kann.Einfachheit der Konstrukte innerhalb des Programms: Sie können die Anzahl der Parameter messen, die eine Funktion akzeptieren wird. Wenn Sie> n % aller Funktionen mit> m Parametern haben , können Sie festlegen, dass dies nicht einfach ist, je nachdem, wie Sie n und m definieren (möglicherweise n = 3 und m = 6?). Ich denke, es gibt einige statische Analysewerkzeuge, die dies messen können - ich denke, JTest hat einfach Funktionen mit> m Parametern gemessen .
Sie könnten versuchen, die Anzahl der verschachtelten Schleifen oder Kontrollstrukturen zu zählen. Ich denke, das ist eigentlich keine schlechte Metrik und ich denke, es gibt einen Namen dafür (ich kann mich nicht von oben erinnern). Wieder denke ich, dass es Werkzeuge gibt (wie JTest), die dies bis zu einem gewissen Grad messen können.
Sie könnten versuchen, "Refactorability" zu messen. Wenn Ihr Code viele Codeteile enthält, die überarbeitet werden könnten , aber nicht , könnte dies möglicherweise nicht einfach sein. Ich erinnere mich auch an die Zeit, als ich mit JTest zusammengearbeitet habe, dass es auch versucht hat, dies zu messen, aber ich erinnere mich, dass ich in diesem Fall nicht oft damit einverstanden war, also YMMV.
Sie könnten versuchen, die Anzahl der Schichten zwischen verschiedenen Teilen Ihres Systems zu messen. Beispiel: Wie viele verschiedene Codeteile berühren Daten, die aus einem Webformular stammen, bevor sie in der Datenbank gespeichert werden? Dies könnte schwierig zu messen sein ...
quelle
?:
ein Problem sind, wenn sie 5 tief verschachtelt sind. Sauber getrennte Schichten sind besser als eine gewundene Schicht. Aber 7 meist redundante Schichten, bei denen nur 2 oder 3 notwendig waren, ist eine schlechte Sache.