Metriken und wofür sie gut sein können

Es gibt einige Literatur, die ich als Standard für objekt-orientierte Softwareentwicklung betrachte. Für einen Kunden habe ich heute ein paar Erkenntnisse zu Metriken zusammengefasst mit Hinweisen auf weiterführende Literatur, die ich der breiten Öffentlichkeit nicht vorenthalten möchte. Wie bei allen Metriken gilt für mich auch hier, dass Metriken nicht als KPIs als extrinsische Motivation vorgegeben werden sollten, sondern jedes Team sich seine Metriken anhand von auftretenden Problemen selbst wählen sollte – intrinsisch motiviert.

Code Coverage (Branch)

Code Coverage beschreibt, wie viel Code durch Tests abgedeckt ist. Dabei ist für mich die meistens interessante Metrik die Zweigabdeckung (engl.: Branch-Coverage) – im Gegensatz zur Zeilen- und Methodenabdeckung.

Bei der Zweigabdeckung geht es darum, dass alle Bedingungen einmal durchlaufen werden müssen. Für eine 100%ige Zweigabdeckung von folgendem Pseudo-Code bedarf es insgesamt mindestens drei Tests:


if (a || b) {
    c();
}
d();

Im ersten Test sollte a true sein. Im zweiten Test sollte a false und b true sein, und im dritten Test sollten a und b false sein.

Die Zweigabdeckung zählt zu den sog. White-Box Testverfahren.

Einer der oftmals gemachten Fehler mit Codeabdeckung ist, einzig darauf zu achten, dass eine Kennzahl erreicht wird. Viel wichtiger bei der Entwicklung ist allerdings, die sinnvollsten Tests parallel zur Entwicklung zu schreiben, – im Idealfall mit Hilfe von testgetriebener Entwicklung – dabei die Codeabdeckung zunächst nicht zu beachten, und anschließend die Codeabdeckung heranzuziehen, um die Stellen im Code, die noch nicht abgedeckt sind, im Brain-On Modus kritisch zu hinterfragen, ob dafür nicht noch ein automatisierter Test geschrieben werden sollte. Die weiterführende Literatur gibt hierfür noch ein paar weitere Begründungen und Tipps.

Weiterführende Literatur

Lines of Executable Code

Bei Lines of Executable Code wird der Umfang an nicht-Kommentar-Code gemessen, der für das Programm notwendig ist. Wie bei dem berühmten Zitat von Goethe geht es bei gutem Code nicht darum, möglichst viel Code zu schreiben, sondern eher möglichst wenig.

Entschuldigen Sie, dass ich Ihnen einen langen Brief schreibe, für einen kurzen habe ich keine Zeit.

Guter Code lässt sich dadurch erkennen, dass er minimal in Bezug auf Anzahl an Klassen und Methoden ist.

Weiterführende Literatur

Statische Code-Analyse

Bei der statischen Code-Analyse werden häufig vorkommende Fehler in der jeweiligen Programmiersprache analysiert. Dadurch lassen sich beispielsweise Null-Referenzierungen in Java-Code früh aufdecken, aber auch Paradigmen wie nicht verwendete Variablen oder Quer-Zuweisungen.

Wie bei allen Regeln sollten auch die Regeln für die Code-Analyse nicht mit gedankenlosem Vertrauen verbessert werden. Im Zweifelsfall spreche ich mit meinen anderen Teammitgliedern darüber, was wir hier verbessern können, und welche Fehler wir vielleicht aus unserer Konfiguration entfernen sollten.

Weiterführende Literatur

Zyklomatische Codekomplexität

Die zyklomatische Codekomplexität nach McCabe bildet die Komplexität einer Klasse oder einer Methode in der Source-Code-Basis ab. Jede konditionelle Bedingung erhöht dabei den Wert der zyklomatischen Codekomplexität um 1. Eine Methode der Komplexität 20 besitzt somit 20 Bedingungen. Derart komplexer Code ist in der Regel nur schwer zu warten.

McCabe’s Theorie besagt außerdem, dass für eine Methode oder Klasse der Komplexität N mindestens N+1 Unittests benötigt werden, um eine ausreichende Abdeckung zu erzielen. Eine Klasse der (über alle Methoden aufsummierten) Komplexität 100 benötigt also 101 Unittests, um eine Basisabdeckung für Fehler durch Regressionen (ungewolltes Einbauen von Fehlern) zu verhindern.

Weiterführende Literatur

Komponenten-Abhängigkeiten

Zu viele Abhängigkeiten einer Komponente (Klasse oder Paket) deuten auf ein schlechtes Design der Software hin. Die Code-Struktur ist dabei sehr von Änderungen an den Abhängigkeiten betroffen. Sogenannte Ripple-Effekte treten dann bei Änderungen an einer Klasse auf, so dass Änderungen langfristig immer schwieriger werden, da immer mehr Klassen betroffen sind. Diese Abhängigkeiten werden durch das Konzept von Kopplung (engl.: Coupling) und Kohäsion (engl.: Cohesion) ausgedrückt.

Aus diesem Grund sollten Klassen und Pakete wie die Unix-Tools unabhängig von einander sein. Jedes Klasse sollte eine kleine Aufgabe sehr gut erledigen können. Das große Zusammenspiel der kleinen Helfer wird dann durch Dependency Inversion gezielt in die übergeordneten Abstraktionen gegeben, so dass auch diese abstrakteren Komponenten weiterhin testbar bleiben.

Weiterführende Literatur

Abhängigkeitszyklen

Zyklen in der Architektur sind im besten Fall schlecht zu warten, im schlimmsten Fall bedeuten sie Unwartbarkeit für die weitere Entwicklung eines Projekts. Im schlimmsten Fall ist ein sog. Big Ball of Mud entstanden, eine Masse von Spaghetti Code, die das Ende des Projektes andeuten kann.

Aus diesem Grund sind zyklische Abhängigkeiten ein Hinweis auf schlechtes Design und schlechte Architektur. Jedes Klasse und jedes Paket sollte eine klare Abhängigkeitsstruktur besitzen. Im einfachen Fall liegt eine Klasse einfach in dem falschen Paket und der Zyklus kann durch Verschieben der Klasse aufgebrochen werden. Im schlimmeren Fall ist die Abhängigkeitsstruktur innerhalb der Software falsch definiert, und Prinzipien wie Dependency Inversion und Single Responsibility sollten hier Abhilfe schaffen.

Weiterführende Literatur

  • Print
  • Digg
  • StumbleUpon
  • del.icio.us
  • Facebook
  • Yahoo! Buzz
  • Twitter
  • Google Bookmarks

5 Gedanken zu „Metriken und wofür sie gut sein können“

    1. Hallo Robert,

      danke für die Ergänzung. Ich persönlich fand Agile Software Development: Pattern, Principles and Practices von Uncle Bob bisher die beste Erläuterung für die SOLID-Prinzipien plus die Prinzipien für die Paketierung. Clean Code und The Clean Coder von ihm setzen zu einem guten Stück genau darauf auf.

  1. Hallo Markus,

    vielleicht noch eine kleine Ergänzung von mir: auch die Abstraktheit eines Paketes ist meines Erachtens eine wichtige Metrik. Sie beschreibt das Verhältnis zwischen abstrakten Elementen (= abstrakte Klassen, Interfaces) und allen(!) (also: abstrakte UND konkrete Elemente (= instanziierbare Klassen)) in einem Paket. Dieser Quotient ergibt einen Wert zwischen 0.0 und 1.0, wobei ein Paket mit einem Wert von 1 nur abstrakte Elemente enthält.

    Der Abhängigkeitsgraph sollte in einem guten Design immer von den konkreteren Paketen zu den abstrakteren Paketen gehen. Befindet sich ein sehr konkretes Paket an der Wurzel einer Abhängigkeitshierarchie, so stimmt etwas nicht, das Design wird dadurch sehr volatil weil dieses Paket häufigen Änderungen unterworfen sein dürfte, was wiederum zu einem Dominoeffekt führt.

    Auf der anderen Seite befindet sich ein relativ abstraktes Paket, welches aber von niemanden sonst verwendet wird, in der sog. „Zone der Nutzlosigkeit“ – es kann offensichtlich ohne Auswirkungen einfach herausgenommen werden.

    Was ich sonst noch hinzufügen möchte: Metriken geben nur einen Hinweis darauf, das etwas nicht stimmen könnte. Sie machen zumeist nur einen Abschnitt im Code sichtbar, auf den der Entwickler mal genauer schauen sollte. Nur weil eine Kennzahl außerhalb der Norm liegt, heißt es nicht gleich automatisch, dass das Design per se schlecht ist.

    1. Hallo,
      schöne Zusammenfassung und zu Stephan Roth:

      Nur weil eine Kennzahl außerhalb der Norm liegt, heißt es nicht gleich automatisch, dass das Design per se schlecht ist.“

      – stimmt und schlimmer noch: eine zwanghafte Verbesserung des Design führt leicht dazu, dass zwar die Vorgaben einer Metrik eingehalten werden, aber das Design schwerer verständlich und im schlimmsten Fall auch nicht mehr wartbar wird.
      Daher befürworte ich, dass Metriken für die Entwickler auch nur von diesen genutzt und bewertet werden und nicht etwa von Chefs. Sonst werden Metriken zu Zielen und dienen damit nicht mehr der Selbst-Bewertung der Qualität des Codes oder des Designs sondern der Leistungsbewertung von Mitarbeitern.

  2. Hi

    Sehr sinnvoller Artikel. Ich wünsche mir mehr aus dem Lager: „Warum XY gut ist“, unbedingt auch mit einem Kritischen Blick darauf und viel weniger aus der Serie „considered harmful“.
    Den hier kann man auch einem Anfänger geben und er kapiert es.

    Danke
    S.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.