Über Metriken

Immer mal wieder bin ich in eine Diskussion über Metriken für Code-Qualität geraten in deren Verlauf ich mich gefragt habe, ob meine Vorstellung vom Begriff „Metrik“ eigentlich richtig ist. Um nicht jedesmal wieder zweifeln zu müssen, habe ich versucht das zu formulieren.

Als Metrik bezeichnet man in der Mathematik eine Funktion, die den Abstand zweier Punkt eines Raum (oder einer Menge von Objekten) berechnet. Unter „Abstand“ versteht man hier einen nicht negativen (reelen) Wert oder lax ausgedrückt: eine positve Zahl die auch null sein kann. Nicht jede solche Funktion ist tatsächlich eine Metrik, sie muß noch einige Bedingungen erfüllen, die hier nachzulesen sind. Für die Metriken in der Qualitätsbestimmung sind diese aber erstmal nicht von Interesse.

Die Definition nach IEEE 1061 wird üblicherweise so wiedergegeben:

Eine Software-Qualitätsmetrik ist eine Funktion, die eine Software-Einheit in einen Zahlenwert abbildet, welcher als Erfüllungsgrad einer Qualitätseigenschaft der Software-Einheit interpretierbar ist.

Sie ist also — wie ihre mathematische Schwester — eine Funktion, die Objekten — hier sind es Software-Einheiten, oder „software data“ wie es im englischen Äquivalent heißt — Zahlenwerte zuweist.

Die Software-Metrik weist also beliebigen Software-Bestandteilen Zahlen zu. Ist die „Software-Einheit“ ein Stück Code — betrachten wir im weiteren an diser Stelle Java-Klassen — dann können wir mithilfe der Metrik jeder Java-Klasse eine Zahl zuordnen. Und weil Zahlen im Gegensatz zu Java-Klassen eine natürliche Ordnung besitzen, kann man sie sinnvoll mit einander vergleichen. Überträgt man die Zahlen-Werte auf die Java-Klassen kann man nun die Java-Klassen miteinander vergleichen.

Wenn die Metrik zum Beispiel „Anzahl der Methoden“ heißt, kann man nun sagen: ist die Zahl der Methoden in Klasse A größer als die der Methoden in Klasse B, dann kann man — analog dazu — sagen: Klasse A ist größer als Klasse B. Statt „größer“ kann man auch ein anderes quantifizierbares Attibut verwenden: besser, schlechter, schöner, häßlicher,…

Aber genau mit diesem letzten Schritt haben wir den Definitions-Bereich der Metrik verlassen. Die Metrik ist eben nichts weiter als die Funktion und wenn man so will die Ordnung die sie definiert; sie hat nichts mit ihrer Interpretation zu tun. Wenn man daher sagt: Klasse A ist besser als Klasse B weil für Metrik x gilt: x(A) > x(B) dann „interpretieren wir sie als Erfüllungsgrad einer Qualitätseigenschaft“ um mit der IEEE-Definition zu sprechen. Das gleiche gilt, wenn verlangt wird daß ein bestimmter Schwellwert über- oder unterboten werden soll.
Die Aussage

Die Klasse darf maximal 10 Methoden besitzen

verwendet die Methoden-Zahl-Metrik und fügt einen Schwellwert hinzu. Dadurch wird sie zum Güte- oder Qualitäts-Kriterium. Sie verwendet die Metrik, ist aber nicht identisch mit ihr. Das ist eine Fehlinterpretiation, die ich erstaunlich oft gehört habe.

Eine Metrik ist also zunächstmal ein Meßinstrument. Bevor man es anwenden kann, muß man sich überlegen was man mit den Ergebnissen anfängt wenn man sie hat. Und mehr noch: man muß sich erstmal darüber klar werden, ob man die Ergebnisse tatsächlich haben will. Klassen sollen in der Regel möglichst wenig Methoden haben, Methoden sollen möglichst kurz sein. Kurze Methoden heißt aber auch mehr Methoden. Sollte dann statt der Methoden-Zahl nicht lieber die durchschnittliche Methodenlänge gemessen werden?

Metriken sind — richtig verstanden — ein hilfreiches Werkzeug, aber:

A fool with a tool is still a fool

Diese Metrik ist tatsächlich zugleich ein selbsterfüllendes Qualitäts-Merkmal.

Merkmale für Code-Qualität

Nachdem wir die zu erfüllenden Anforderungen kennen, müssen wir nun Merkmale finden in denen sich die Anforderungen widerspiegeln. Merkmale, die es erlauben den Grad zu messen in dem die Anforderungen erfüllt sind. Es giebt eine unglaubliche Menge von Vorschlägen für Eigenschaften, Merkmalen oder Qualitäten die Code haben sollte oder nicht haben dürfen soll um als „guter Code“ zu gelten. Man kann diese Merkmale auch — zumindest teilweise — den genannten Anforderungen zuordnen.

Und an dieser Stelle fangen die Probleme an. Die Menge der Regeln ist riesig und die der diskutierten Auslegungen unüberschaubar. Tatsächlich ist die Vorstellung von Code-Qualität nicht absolut. Sie ist abhängig von Zeit, Kultur, verwendeter Technologie, Fachlichkeit und vielen anderen Faktoren. Die wenigen allgemeingültigen Regeln sind dermaßen abstrakt formuliert, daß sie kaum unmittelbar anwendbar sind. Und sobald man versucht ihre Anwendung zu konkretisieren, starten die Diskussionen.

Jedes Team und jede Organisation, die versucht die Code-Qualität zu verbessern muß damit beginnen ein gemeinsames Verständnis für die Qualität zu entwickeln. Ohne ein solches Verständnis findet man keine Einigung und Regeln werden entweder gar nicht erfüllt oder sie werden nur um der Erfüllung willen erfüllt. Gesetzte Regeln müssen verstanden und immer wieder auf ihre Sinnhaftigkeit hinterfragt werden. Das ist aufwändig und erfordert Engagement — wer ist bereit dafür Energei aufzubringen?

In den alten Tagen war es üblich, Code-Qualität am Verhältnis von Kommentar- zu Code-Zeilen zu messen. Je größer das Verhältnis desto besser. In der Folge sind viele Entwickler dazu übergegangen, den Code mit leeren Kommentar-Zeilen aufzufüllen. Die Metrik wird erfüllt, aber was hat das mit Qualität zu tun?

Metriken führen nicht zu Code von besserer Qualität,
sondern zu Code der die Metriken erfüllt.

Moderne Metriken scheinen besser geeignet zu sein. Man zählt die Methoden der Klasse, die Zeilen von Methoden und Funktionen, man mißt die Abdeckung des Codes mit Unit-Tests und die Kohärenz in Modulen. Aber was ändert das an der Einstellung des Entwicklers? Wer schnell viel Code generieren will (oder muß), der findet Wege die Metriken zu erfüllen ohne dabei die Code-Qualität ändern zu müssen.

Qualität ist die Einstellung des Entwicklers,
die vom Code reflektiert wird.

Macht das Regeln — und die Metriken die sie messen — überflüssig oder unsinnig? Nein. Der qualitätsorientierte Entwickler sollte alle Mittel nutzen — und zumindest ernsthaft erproben — um die Qualität zu verbessern. Die vielleicht beste Formulierung diese Gedankens stammt von Michael Feathers:

Clean Code always looks
like it was written by someone who cares.

Michael Feathers

Die Kommentar-Metrik zeigt aber noch ein anderes Problem. Keine Metrik kann messen wie hoch der Bezug ist den der Code zu seiner Semantik hat. Man könnte diese Eigenschaft als „Angemessenheit“ bezeichnen. Betrachten wir diese Zeile:

int x = a + b;

Sie ist zu umfangarm um irgendeine Aussage über ihre Qualität zu machen. Sobald wir aber die Variablen umbenennen und schreiben:

int differenz = soll + ist;

macht die Zeile überhaupt keinen Sinn mehr. Sie widerspricht sich plötzlich selbst. Die zusätzliche semantische Information die durch die Bezeichner transportiert wird ist für den Compiler schlichtweg unsichtbar. Ebenso wie die Information die gar nicht im Code enthalten ist, weil sie nur im Fachkonzept existiert.

Was können wir also über die meßbaren Merkmale von Code-Qualität sagen? Sobald wir festgelegt haben, welchen Regeln wir folgen möchten, können wir dazu Merkmale festlegen an denen wir die Code-Qualität messen können. Sobald sich unser Verständnis der Qualität ändert müssen wir die Merkmale anpassen. Ausreichend sind solche Merkmale aber nicht, die Übereinstimmung des Codes mit seiner Bedeutung können sie nicht erfassen.