Buch-Rezension zu „Dependency Injection“

Dependency Injection“Dependency Injection – Design patterns using Spring and Guice” von Dhanji R. Prasanna erschien im August 2009 bei Manning. Prasanna arbeitet bei Google und beteiligt sich an der Entwicklung von Guice. Der Autor ist somit mitten drin und kann aus erster Hand berichten.

Das Buch startet mit einer Erklärung was Dependency Injection (DI) ist und wieso derzeit so viel davon gesprochen wird. Ein kleines Beispiel mit der Klasse Emailer, der vor dem absenden die Rechtschreibung prüfen soll, dient dabei der Erklärung der Vorteile von DI.

public class Emailer {
	private SpellChecker spellChecker;

 	public Emailer() {
		this.spellChecker = new SpellChecker();
	}

	public void send(String text) {
		spellChecker.check(text);		
		// send if ok...
	}
}

Die Fragen rund um diesen Code sind vielfältig: Wie kann man testen, ob der SpellChecker aufgerufen wurde? Oder wie ändert man die Sprache?
Als Antwort darauf werden Service Locator, Factories und Setter für den SpellChecker aufgezeigt. Es funktioniert, ist aber nicht wirklich elegant.
DI wird darauf hin mit dem Hollywood Prinzip („Don’t call us; we’ll call you!“) eingeführt. Wieso soll man alles selber immer wieder konfigurieren, wenn man all dies zentral an einer einzigen Stelle machen kann?
Eine kurze Auflistung der DI-Frameworks rundet das 1. Kapitel ab.

Ab Kapitel 2 geht es um die Benutzung von DI. Der Emailer wird aufgenommen und mittels Guice, PicoContainer und Spring injiziert. Es geht weiter mit dem Identifizieren der Abhängigkeiten, die man aufteilen will. Die Benennung der Abhängigkeiten (Keys) und deren Typ (String, Enum, Klasse) werden mit allen Vor- und Nachteilen bis ins kleinste Detail auseinander genommen.

Das Einfügen der Abhängigkeiten kann auf verschiedenen Ebenen erfolgen: im Konstruktor, per Set-Methode oder auf Feldern. Kapitel 3 liefert zu allen Möglichkeiten eine Erklärung.

Die Modularisierung der Architektur der Applikation füllt Kapitel 4, bevor es in Kapitel 5 und 6 um den Sichtbarkeitsbereich (Scope) der einzelnen Objekte geht. Kapitel 7 widmet sich dem Lebenszyklus der Objekte und Kapitel 8 deren Verhalten.
In Kapitel 9 werden Best Practices für das Design des Codes und auf was bei nebenläufigen Programmen geachtet werden muss gezeigt.

Kapitel 10 zeigt die Integration von DI in bekannte Frameworks. In Kapitel 11 wird zum Abschluss eine ganze Applikation von Grund auf mit Hilfe von DI erzeugt.

 
Fazit
Der Anfang des Buches zeigt sehr gut die Einsatzmöglichkeiten und die damit verbundenen Vorteile von DI auf. Es war klar, verständlich und auf den Punkt gebracht.
Ab Kapitel 2 geht es dann sehr schnell (zu?) tief in die Materie hinein. Die ganzen Überlegungen zu den Keys waren zwar lehrreich, doch ist der Umfang viel zu gross.
Ab Buchmitte war das lesen äusserst mühsam. Bei einem Problem würde ich die Detaillierung sicher schätzen. Da ich mich aber über die Möglichkeiten von DI und der konkreten Anwendung informieren wollte, ging es viel zu sehr ins Detail.
Die Beispiele und auch der Text dazu hatte in dem Teil auch nicht die Qualität, die man sonst von Manning gewohnt ist.
Kapitel 11 war dann wiederum sehr gut – da gab es wieder einen klaren Bezug zur Praxis.

Damit ich mir das Buch noch einmal kaufen würde, müsste etliches an der Strukturierung geändert werden. Pro Kapitel ein Thema, die detaillierten Ausführungen in eigene Kapitel oder in den Anhang und in der Zusammenfassung keine neuen Ansätze einbringen. (OK, vielleicht waren diese „Neuigkeiten“ bereits im Kapitel drin aber von den vielen anderen Themen rund herum verdeckt – das macht es aber auch nicht besser)
Einige Dinge sind noch nicht ganz „rund“ und mit ein wenig Nachbessern könnte man da noch viel verbessern. Es hat sehr viele Informationen drin, doch kommen die derzeit nicht wirklich zur Geltung.

„Dependency Injection“ kann ich nur dann empfehlen, wenn man sich ganz detailliert über das Thema informieren will. Ansonsten wartet man wohl besser auf die 2. Ausgabe.

 
Zum Buch
Dependency Injection – Design patterns using Spring and Guice” von Dhanji R. Prasanna, 2009 Manning, ISBN 978-1-933988-55-9, 352 Seiten

Advertisements

Testen von Exceptions mit JMockit

Für einen Unit-Test benötigt man meistens nur gewisse Teile eines „fremden“ Objekts. Oft genügt einem eine fixe Anzahl definierter Rückgabewerte. Statt das man nun das „fremde“ Objekt erzeugt und die Werte aus einer Datenbank holt, setzt man eine Testattrappe ein. Diese Attrappe liefert einem die definierten Rückgabewerte oder Exceptions, ohne dabei wirklich mit der Datenbank, dem Dateisystem oder dem Netzwerk zu sprechen. So eine Attrappe kann ein Mock oder Stub sein.

JMockit ist ein Framework für Java, das einem bei der Erstellung von Mocks und Stubs hilft. Für Java gibt es zahlreiche solcher Frameworks. JMockit hat aber einige besondere Fähigkeiten, was das Testen deutlich erleichtern kann.

Für AtaraxiS war ich in den letzten Tagen am erweitern der Unit-Tests. Die Testabdeckung war noch nicht überall so gut, wie ich diese haben will. Es fehlten vor allem noch die zahlreichen Catch-Blocke für die Exceptions.
(Wieso überhaupt Exceptions testen? AtaraxiS will die Verschlüsselung abstrahieren und reduziert die dabei möglichen Exceptions auf eine handlichere Anzahl. Diese Tests dienen der Kontrolle, ob auch nach dem anstehenden Umbau noch alles wie gewohnt läuft.)

	public ACDecryptInputStream (File inFile, SecretKey aesKey) throws IOException
	{
		try 
		{
			// Parse the Header of the File
			AtaraxisHeaderParser ahParser = new AtaraxisHeaderParser(inFile);

			// When it contains a Header, then prepare all for CBC-Mode
			IvParameterSpec ivSpec = new IvParameterSpec(ahParser.getIV());

			fis = new FileInputStream(inFile);
			fis.skip(ahParser.bytesToSkip());

			cipher = Cipher.getInstance("AES/CBC/PKCS7Padding", "BC");
			cipher.init(Cipher.DECRYPT_MODE, aesKey, ivSpec);
			
			// Create the CipherInputStream
			decryptedInputStream = new CipherInputStream(fis, cipher);
		} 
		catch (NoSuchAlgorithmException e)
		{
			LOGGER.error("NoSuchAlgorithmException", e);
			throw new IOException("NoSuchAlgorithmException");
		} 
		.....
	}

Um dies zu testen, müsste die Klasse Cipher bei getInstance() eine NoSuchAlgorithmException werfen. Dies könnte ich durch eine Abstraktionsschicht zwischen unserem Code und dem von BouncyCastle machen. Das bedingt aber eine Änderung am Code. Hier wäre das zwar möglich, doch geht das nicht immer.

JMockit hat dafür eine passende Methode. Mittels Mockit.redefineMethods() kann eine Methode umgeleitet werden. Das angegebene Ziel kann genau das machen, was man von ihm erwartet. Um die Exception zu werfen, dient dieser Aufruf:

	@Test(expected=IOException.class)
	public void ACDecryptInputStream_NoSuchAlgorithmException() throws Exception
	{
		Mockit.redefineMethods(javax.crypto.Cipher.class, new Object() {
			@SuppressWarnings("unused")
			public final Cipher getInstance(String transformation,
                    Provider provider)
             throws NoSuchAlgorithmException,
                    NoSuchPaddingException
			{
				throw new NoSuchAlgorithmException();
			}
		});

		ACDecryptInputStream acI = new ACDecryptInputStream(testFile, key);
		fail("IOException missing for " + acI);
	}

Dies ist nur eine der unzähligen Möglichkeiten, die JMockit bietet. Nach dem gleichen Prinzip kann man beliebige Rückgabewerte zurückliefern. Wer mehr dazu wissen will, findet auf der Projektseite von JMockit eine sehr detaillierte Anleitung.

Buch-Rezension zu „Test Driven“

Test Driven
Test Driven

„Test Driven – Practical TDD and Acceptance TDD for Java Developers“ von Lasse Koskela ist Ende 2007 bei Manning erschienen. Bei Test Driven geht es um die testgetriebene Software-Entwicklung in Java.

 
Teil 1: Grundlagen von TDD
Im ersten Kapitel werden die Ideen hinter Test Driven Development (TDD) vorgestellt und erklärt, wieso man als Entwickler davon profitiert. Der Initialaufwand für TDD ist höher als bei der Entwicklung ohne Tests. Doch soll der Code irgendwann in Produktion, muss dieser getestet werden. Und wenn man Tests eh braucht, kann man die auch zu einer Zeit schreiben, von der man selber noch etwas davon hat.
Koskela zeigt dabei auch die Wichtigkeit von Refactoring auf. Ohne Tests wird darauf zu oft verzichtet. Der Code läuft, wieso durch eine Änderung neue Probleme riskieren? Hat man die TDD Tests, passen diese auf das beibehalten der Funktionalität auf. Und Refactoring ist bei TDD zentral: Hält man sich an die Vorschläge im Buch und versucht immer die einfachste Lösung zum bestehen der Tests zu schreiben, hat man meistens eine fragwürdige Qualität. Erst das Refactoring macht aus dem funktionierenden auch guten Code – dies gilt auch für die Tests. Kapitel 3 widmet sich daher vollständig dem Refactoring.

Die konkrete Umsetzung von TDD wird in den restlichen Kapiteln des 1. Teils mit der Entwicklung einer Template Engine vorgestellt.

 
Teil 2: TDD für spezifische Technologien
Im zweiten Teil geht es um die Anwendung von TDD bei spezifischen Technologien. Dies reicht von Webkomponenten über Datenzugriff bis zu Swing. Ansätze zum Testen von Multi-Thread Programmen und Zeitfunktionen werden ebenfalls anschaulich erklärt. Eine kurze Vorstellung der dafür benutzten Technologien (wie JSP, JDBC, Hibernate, DbUnit, usw.) sowie deren Verwendung zum Testen runden diesen Teil ab.

 
Teil 3: Acceptance TDD
Im letzten Teil werden die Akzeptanz-Tests behandelt. Es wird mit einer Erklärung der Grundbegriffe und Möglichkeiten fürs Vorgehen begonnen und geht dann zur Umsetzung mittels Fit. Der Kunde kann mit der Hilfe von Fit seine Anwendungsfälle in Tabellenform erfassen. Diese dienen dann als Input für Tests und ermöglichen so die Verifizierung der Funktionalität. Damit dies funktioniert muss der Entwickler die Verbindung zwischen Fit und den Unit-Tests erstellen.

 
Fazit:
Test Driven erklärt auf verständliche Art was die testgetriebene Entwicklung ausmacht und wieso man diese anwenden soll. Kapitel 1 und 3 behandeln Grundlagen die auch ausserhalb von Java gelten.
Ich finde das Buch ist sehr gut geschrieben und ich konnte beim lesen nicht genug bekommen. Der dritte Teil kommt nicht ganz an die 2 ersten Teile heran. Da wäre mehr zur Verknüpfung von Fit um den Tests sowie Beispiele mit anderen Frameworks hilfreich gewesen. Dennoch kann ich das Buch ohne Einschränkung weiterempfehlen.

Zum Buch
Test Driven – Practical TDD and Acceptance TDD for Java Developers von Lasse Koskela, 2007 Manning, ISBN 978-1-932394-85-6, 544 Seiten