Tag Archives: Java

CC – Singleton korrekt implementieren


Flattr this

Motivation

Seit ich Clean Code [martin2009cleancode] lese, wollte ich das Gelesene auch gleich in meinem Blog posten um mir jenes erworbene Wissen für die Zukunft zu sichern. Leider geht das nicht so einfach, da diverse Punkte durchaus kontrovers diskutiert werden und sich stets auch Alternativen finden, welche nicht unbedingt schlechter sind. Zur Bewertung der Lösungen müssen erst eigene Erfahrungen gesammelt werden. Es genügt nicht zu sagen, es hies immer das wäre eine schlechte Lösung darum habe ich diese nie verwendet. Man muss auch verstehen warum die Lösung schlecht ist. Dazu muss man entweder ein paar Argumente kennen oder Erfahrungen mit der Lösung gesammelt haben oder aber vollständig die Vor- und Nachteile sowie die eigentlichen Ziele im konkreten Fall erfasst haben.

Es gibt Leute die lesen solche Bücher in ein paar Tagen und berufen dann Meetings ein um den Rest der Welt mit dem zu missionieren was sie selbst von dem Buch erfasst haben. In der Regel haben sie einige Dinge falsch verstanden und argumentieren dann vehement gegen die Anderen.

Diesen Fehler wollte ich nicht machen. Deshalb möchte ich auch ausdrücklich darauf hinweisen, dass die Artikel nur gesammeltes Wissen und Erfahrung sind. Keine Garantie, dass die Aussagen stimmen. Letztlich muss jeder selbst darüber nachdenken. In meinen Artikeln kann ich nur Hilfen und Argumente zur Verfügung stellen. Ich kann auch Empfehlungen aussprechen aber entscheiden muss letzlich jeder für sich allein.

Aus diesem Grund halte ich es für das Beste, einzelne Teilprobleme heraus zu greifen und diese von allen Seiten zu beleuchten. Vor- und Nachteile zu diskutieren und dem Leser damit eine Entscheidungshilfe an die Hand zu geben. Entscheiden muss er letztlich immer selbst am realen Kode.

Damit startet die Serie zur Clean Code Programmierung. Für den Leser stets erkennbar am dem CC – vor dem eigentlichen Titel.

Ziel des Singleton Pattern

Manchmal ist es wünschenswert, dass nur exakt eine Instanz von einer Klasse global existiert. Damit kann sich der Programmierer dann darauf verlassen, dass immer wenn Logik dieser Klasse ausgeführt wird, geschieht dies in dieser Einen Instanz. Soweit der Wunsch. In Wirklichkeit greifen im Java Umfeld noch einige Nebenbedingungen auf die wie nebenbei zu sprechen kommen. Diese Aufgabenstellung besitzt eine Lösung, das Singleton Pattern. Beschrieben ist dieses unter anderem in [Gam1994].

Wann ist das Pattern anzuwenden?

In [Gam1994] werden dazu 2 Gründe aufgeführt. Wende das Pattern an wenn:

  1. Du eine Klasse hast von der nur exakt eine Instanz existieren darf und diese soll von Clients zugreifbar sein über einen gut bekannten Zugriffspunkt.
  2. Wenn die Einzige Instanz durch Subklassen erweitert werden soll und ein Client soll in der Lage sein Instanzen von Subklassen zu nutzen ohne ihren Kode zu modifizieren.

Damit beginnt die erste Diskussion! In Java EE Umgebungen wird die Erzeugung von Objekten (Instanzen) dem Container übertragen. Er allein darf darüber entscheiden ob eine, zwei, oder mehr Instanzen einer Klasse zeitgleich existieren sollen. Die Verwendung von Singleton greift damit in die Freiheit des Containers ein. In konkreten Fällen kann damit eine Änderung der Implementierung der Containerlogik behindert werden. Der Architektur wird damit Flexibilität genommen. Der Architekt hatte möglicherweise bereits geplant zunächst einen Pico Container einzusetzen und in der zweiten Phase einen Spring Container. Er rechnet in der Regel nicht mit Entwicklern die ihm hier Steine in den Weg legen indem sie unkontrolliert in die Containerlogik eingreifen.

Sei es drum – wir haben mit unserem Architekten gesprochen und er sieht ein, dass es sein muss. Natürlich mit der Auflage das Pattern so wenig wie möglich zu nutzen. Wann nutzen wir es dann? Wenn die 1. Bedingung erfüllt ist? Wenn die 2. Bedingung erfüllt ist oder nur wenn beide Bedingungen erfüllt sind?

Aus meiner Sicht gibt es keinen Grund in einer Java EE Umgebungen ein Singleton zu verwenden, es sei denn man schreibt ein Framework und keine Anwendung. Aber diese Aussage möchte ich nicht als Lösung stehen lassen, da mir nicht klar ist ob meine Auffasung hier richtig ist. Letztlich läuft es wohl auf Einzelfallentscheidungen heraus.

Singleton – erster Versuch

package de.theserverside.designpatterns.singleton;

/**
* Klassische Implementierung des Singleton-Patterns
*/
public class ClassicSingleton {
private static ClassicSingleton instance = null;

/**
* Default-Konstruktor, der nicht außerhalb dieser Klasse
* aufgerufen werden kann
*/
private ClassicSingleton() {}

/**
* Statische Methode, liefert die einzige Instanz dieser
* Klasse zurück
*/
public static ClassicSingleton getInstance() {
if (instance == null) {
instance = new ClassicSingleton();
}
return instance;
}
}

Quelle: [Singleton]

Prinzipiell wird hier auf lange Sicht immer eine Instanz zurückgegben. Jedoch in der Anfangsphase kann es in Multithread Umgebungen zu Problemen kommen. Wenn der erste Thread in die getInstance() Methode eintritt und die if Anweisung mit dem Vergleich auf null noch passiert, dann jedoch vom System (Container, JVM, OS, …) schlafen gelegt wird. Während Thread 1 träumt, tritt ein zweiter Thread in die getInstance() Methode ein und passiert die if Abfrage welche immernoch true ergibt, erzeugt ein neues Objekt und bevor er dieses der Klassenvariablen zuweisen kann wird auch er ins Koma versetzt. Das Gleiche können jetzt noch hunderte von Threads genauso machen. Irgendwann wacht einer (evtl. der erste Thread) wieder auf und nimmt die Zuweisung auf die Klassenvariable vor. Ab da liefert die if Bedingung false. Jetzt wachen noch die anderen schlafenden Threads auf und nehmen ihrerseits die Zuweisung auf die Klassenvariablen vor. Je nachdem zu welchem Zeitpunkt dann die getInstance() Methode aufgerufen wird liefert sie ein anderes Objekt zurück. Erst ab dem Zeitpunkt ab dem sich kein Thread mehr innerhalb des Bodies der If Anweisung befindet, erst ab da wird stets die selbe Instanz zurückgegeben. Diese Implementierung führt also nicht zum Ziel.

 

Quellennachweis

[martin2009cleancode]
Martin, Robert C.: Clean code: a handbook of agile software craftsmanship. 1. Upper Saddle River, N.J. : Prentice Hall International, 2009. – ISBN 0-13-235088-2
[Gam1994]
Gamma, et al: Design Patterns: Elements of Reusable Object-Oriented Software : Addison Wesley Professional, 1994
[Singleton]
The Server Side Web Site Discussion

Architektur prüfen mit CodeCity


Flattr this
Wie an den meisten Wochenenden schmökere ich gerade wieder in den Fachzeitschriften. Am liebsten im JavaMagazin und dort habe ich in der Ausgabe 10/2010 einen interessanten Artikel gefunden.

Worum geht es?

Es geht darum die Kodequalität in Form einer Stadt zu visualisieren. Die Idee ist genial einfach. Packages werden zu Stadtbezirken, Klassen zu Häusern und Methoden zu Etagen. Die Grundfläche eines Hauses wird aus der Anzahl der Attribute einer Klasse abgeleitet. Damit ist klar was passiert. Klassen mit vielen Attributen besitzen große Grundflächen, Klassen mit vielen Methoden sind sehr hoch. Die Stadt wird zunächst einfarbig in blau gehalten. Um so mehr Lines of Codes ein Artefakt (Klasse, Methode) besitzt um so heller wird das blau. Historiendaten sollen auch ausgewertet werden können. Eine entfernte Methode wird als Loch im Gebäude dargestellt. Zusätzlich lassen sich spezielle Problemfelder (God Class, Data Class, Brain Class, Brain Method, Feature Envy und Shotgun Surgery)  benutzerdefinierten Farben zuordnen.

Was bringt es?

Was bringt das Ganze? Bestehende Großprojekte mit schlechter Wartbarkeit einem Codereview zu unterziehen, um jene Stellen zu finden welche wirkliche Probleme darstellen, dauert lange. In der Regel werden mehrere Personen herangesetzt, es sind tausende von Kodezeilen zu sichten. Jede Person hat eine leicht andere Meinung zur gerade betrachteten Kodestelle und in der verfügbaren Zeit kann unmöglich jeder Kodeabschnitt vollständig durchdacht werden. Letztlich geht es darum die wichtigsten Punkte für die Refaktorierung zu finden. Das geht mit CodeCity deutlich schneller. Alle Kodezeilen werden analysiert und in eine grafische Struktur gebracht. Abweichungen von einer regelmäßigen Struktur lassen sich so schnell erkennen und können dann gezielt analysiert werden. Dieses Vorgehen sollte eine deutlich effizientere Analyse bestehender Großprojekte ermöglichen.

Wie geht es?

Jetzt zum praktischen Teil. Natürlich wollte ich es sofort ausprobieren. Dazu benötigen wir inFusion und CodeCity. Diese laden wir uns zunächst aus dem Internet herunter. Beide habe ich unter Windows jeweils in ein eigenes Verzeichnis entpackt und die Startdateien mit einem Shortcut auf den Desktop gelegt. Das Startprogramm von inFusion nennt sich infusion.bat und das von CodeCity einfach codecity.exe.

Zunächst müssen wir inFusion starten um den Kode unseres Projektes analysieren zu lassen. Infusion startet und zeigt folgenden Dialog an.

Startscreen von Infusion

Infusion Start

Oben rechts in der Ecke das 2. Piktogramm von rechts öffnet einen Dialog über den wir unsere Projekt Sourcen auswählen können.

Dialog zum Auswählen der Java Quellen

Ich habe mir die Quellen des Gui4j Projektes ausgecheckt. Kann sein, dass ich aus Versehen lokal ein paar Änderungen vorgenommen habe. Das weiß aber ich nicht. Ist für unseren Test auch nicht weiter wichtig. Im Dialog den Ordner suchen in dem die Java Dateien abgelegt wurden. Im Beispiel ist es src, bei Projekten die per Maven gebaut werden ist er standardmäßig unter src/main/java zu finden. Den Dialog wie erwartet dann über die Load Schaltfläche schließen.

Die Analyse wird sofort durchgeführt

Wir sehen im unteren Teilfenster den src Ordner durch einen blauen Balken ausgewählt. Genau dort rufen wir per Rechtsklick auf die Maus ein Kontext Menü auf und exportieren die Daten über die Option Run Tools …/FAMIX 2.1 MSE Exporter. Ich habe mich für diese Option entschieden, da die 3.0 von der CodeCity Version 1.4 nicht fehlerfrei eingelesen werden konnte.

Das File bitte auf .mse enden lassen.

Export mit FAMIX 2.1 MSE Exporter

Die Analyse wäre damit erledigt. Generell kann man auch jetzt schon diverse Probleme feststellen. Schöner geht das aber evtl. mit der angestrebten Stadt. Diese bauen wir nun indem wir CodeCity starten.

Startscreen von CodeCity

Nach dem Start von CodeCity erscheinen drei Fenster. Wir benötigen das oben dargestellte um unseren MSE Export zu laden. Dazu Betätigen wir die Schaltfläche „an MSE file…“. Gleich darauf erfolgt das Einlesen der MSE Datei und dessen Verarbeitung. Als Ergebnis erscheint ein neuer Listeneintrag. Im Beispiel gui4j benannt (vermutlich einfach der Name der Exportdatei).

Quellen wählen und auf City drücken

Diesen Listeneintrag wählen wir aus und Betätigen dann die Schaltfläche „City„. Nun erscheint das Fenster mit unserer Stadt.

Eine farbenfrohe Stadt nach Auswahl aller Disharmonien

Wenn wir in diesem Fenster das Radioaktivitäts-Symbol betätigen und im sich öffnenden Dialog alle Auswahlboxen selektieren, dann wird unsere Stadt so farbenfroh wie hier dargestellt. Durch das Hinwegbewegen des Mauszeigers über interessante Bereiche, wird in der rechten oberen Ecke der Detailbereich aktualisiert. Hier lässt sich leicht ablesen wieviel Kodezeilen oder wieviel Methoden die Klasse besitzt und ähnliches.

Durch die Stadt bewegen ist auch möglich. Auf folgende Tasten wird im Artikel hingewiesen:

Zeichen Aktion
W, S Zoom
A, D Verschiebung waagerecht
Strg + Pfeil hoch/runter Rotation um die Horizontale
Strg + Pfeil links/rechts Rotation um die Vertikale
Taste + Shift Aktionen in kleineren Schritten ausführen

Zum Abschluss noch die im Artikel erwähnten Quellen:

  1. http://www.bibsonomy.org/bibtex/204bd07ba7388ba1edfc97617ca75d139/funthomas424242
  2. http://www.bibsonomy.org/bibtex/2377e6c82a1417ed9bfe494ce578bffdd/funthomas424242
  3. http://www.bibsonomy.org/bibtex/24d513cc73eb3a2f3e55295e595935c49/funthomas424242
  4. http://www.bibsonomy.org/bibtex/2587bde0b7ffa5d7fd9e9940eba7a4d58/funthomas424242
  5. http://www.bibsonomy.org/bibtex/29952e80cf589274cc96e02e67210a9c5/funthomas424242
  6. http://www.intooitus.com/infusion/download/inFusion.zip
  7. http://www.inf.usi.ch/phd/wettel/codecity-download.html
  8. http://www.inf.usi.ch/phd/wettel/codecity-tutorials.html
  9. http://www.inf.usi.ch/phd/wettel/activities.html

An dieser Stelle vielen Dank an Richard Wettel, der CodeCity erschaffen hat und natürlich auch an alle anderen Contributoren der beiden Programme inFusion und CodeCity.

Dann viel Spass beim Städtebau.