Home > Statische Code-Analyse > “Law of Demeter” als Software Metrik

“Law of Demeter” als Software Metrik

3. Juni 2012

Das “Law of Demeter” (LoD) ist ein wichtiges Prinzip, um in seinem Code eine niedrige Kopplung zu erreichen. Und man könnte es relativ einfach in eine Software-Metrik überführen.

Um die Kopplung zu messen, könnte man die “Verletzungen des LODs” zählen. “0” bedeutet, dass keine Verletzungen vorhanden sind und das Ergebnis wird für jede Verletzung, die gefunden wird, um eins erhöht.

Ich frage mich, ob jemand so eine Metrik schon implementiert hat und ob sie in Eclipse oder NetBeans verwendet werden kann.

Hier noch ein kleines Beispiel.

Beispiel (for dem Refactoring)
Wir haben vier Klassen Alfa, Bravo, Charlie und Delta, die in einer Struktur wie in einer Kette angeordnet sind. Man könnte damit soetwas wie alfa.getBravo().getCharlie().getDelta(); machen.
Dieser Code verletzt das Gesetz von Demeter zweimal und würde zu einer “Demeter Distanz” von “2” führen.

Der detailierte Code ist hier:

package lawofdemeter;
 
public class Main
{
 
    public static void main(String[] args)
    {
        Alfa alfa = new Alfa();
        alfa.getBravo().        // This is allowed, according to Law of Demeter
                getCharlie().   // Violation of Law of Demeter
                getDelta();     // Violation of Law of Demeter
    }
 
    private static class Alfa
    {
 
        private final Bravo bravo;
 
        public Alfa()
        {
            bravo = new Bravo();
        }
 
        public Bravo getBravo()
        {
            return bravo;
        }
    }
 
    private static class Bravo
    {
 
        private final Charlie charlie;
 
        public Bravo()
        {
            charlie = new Charlie();
        }
 
        public Charlie getCharlie()
        {
            return charlie;
        }
    }
 
    private static class Charlie
    {
 
        private final Delta delta;
 
        public Charlie()
        {
            delta = new Delta();
        }
 
        Delta getDelta()
        {
            return delta;
        }
    }
 
    private static class Delta
    {
    }
}

Beispiel (nach dem Refactoring)

Um das Maß zu seinem Optimum zu verbessern, wäre eine Möglichkeit, die grün markierten Methoden einzufügen.
Jetzt ist es möglich, den gesamten Code mit einer “Demeter Distanz” von 0 zu schreiben.
Hier ist der entsprechende Code:

package lawofdemeter;
 
public class Main2
{
 
    public static void main(String[] args)
    {
        Alfa alfa = new Alfa();
        alfa.getDelta();
    }
 
    private static class Alfa
    {
 
        private final Bravo bravo;
 
        public Alfa()
        {
            bravo = new Bravo();
        }
 
        public Bravo getBravo()
        {
            return bravo;
        }
 
        public Delta getDelta() {
            return bravo.getDelta();
        }
    }
 
    private static class Bravo
    {
 
        private final Charlie charlie;
 
        public Bravo()
        {
            charlie = new Charlie();
        }
 
        public Charlie getCharlie()
        {
            return charlie;
        }
 
        public Delta getDelta() {
            return charlie.getDelta();
        }
    }
 
    private static class Charlie
    {
 
        private final Delta delta;
 
        public Charlie()
        {
            delta = new Delta();
        }
 
        Delta getDelta()
        {
            return delta;
        }
    }
 
    private static class Delta
    {
    }
}

Ich glaube, dass die zweite Variante (im Allgemeinen) besser als die erste ist. Aber warum?

Ein wichtiger Punkt ist die Lesbarkeit. Man hat ein alfa und man will ein delta bekommen. Es ist intuitiver für den Leser, wenn er nur alfa.getDelta() liest. Und wenn er wirklich daran interessiert ist, wie man das delta bekommt, kann er zu getDelta() springen und die Details dort finden.

Der zweite Punkt ist – wie schon erwähnt – die Kopplung. In der ersten Version ist man davon abhängig, dass ein Alpha ein Bravo hat, welches ein Charlie hat, welches ein Delta hat. Der Code wird nur unter diesen Bedingungen funktionieren und ist kaputt, wenn ein dieser Pfad sich ändert. Und der Code ist weniger anpassungsfähig für andere Szenarios.

In der umgeschriebenen Version ist man nur abhängig von der Tatsache, dass es einen direkten Weg von alfa gibt, um an das delta zu kommen. Und die Details werde an die anderen Klassen delegiert, welche die Details sowieso schon kennen.

Kommentare sind geschlossen