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
Post a comment or leave a trackback: Trackback URL.

Schreibe einen Kommentar

Trage deine Daten unten ein oder klicke ein Icon um dich einzuloggen:

WordPress.com-Logo

Du kommentierst mit Deinem WordPress.com-Konto. Abmelden / Ändern )

Twitter-Bild

Du kommentierst mit Deinem Twitter-Konto. Abmelden / Ändern )

Facebook-Foto

Du kommentierst mit Deinem Facebook-Konto. Abmelden / Ändern )

Google+ Foto

Du kommentierst mit Deinem Google+-Konto. Abmelden / Ändern )

Verbinde mit %s

%d Bloggern gefällt das: