Assisted Inject

Veröffentlicht: 9. November 2011 von pmischke in Dependency Injection

Es geht weiter mit einem Dependency Injection Thema, das ich hier „Asssited Inject“ nenne. Ich kann nicht ausschließen, dass es noch weitere Namen für diese Technik gibt. Mir ist sie zuerst bei dem Guice Framework und eben diesem Namen über den Weg gelaufen:

http://code.google.com/p/google-guice/wiki/AssistedInject

Es geht um folgendes Problem:

  • Ich möchte mehrere Objekte eines Typs erzeugen.
  • Mein Typ hat Abhängigkeiten zu anderen Objekte, die über den Konstruktor vom DI Container gesetzt werden sollen. Diese Abhängigkeiten sind im einfachsten Fall für alle Objekte identisch (also Singleton Scope). Das muss nicht so sein, ist aber für das Assisted Inject irrelevant, also nehme ich den einfachsten Fall an.
  • Mein Typ hat daneben weiter Konstrutor-Argumente, die der Client des Objekts im Moment der Erzeugung spezifizieren soll. Diese Argumente (im folgenden Parameter genannt) sind wahrscheinlich für jedes Objekt verschieden. Dadurch entsteht hier der Bedarf, mehrere Objekte zu erzeugen, selbst wenn die Objekte keinen modifizierbaren Zustand besitzen.

Worin genau besteht das Problem? Nun ja, zum einen möchte ich natürlich, dass der DI Container die Objekte erzeugt. So kann er sich um die notwendigen Abhängigkeiten kümmern. Zum anderen sollen aber die Clients die Objekte erzeugen, um ihnen Parameter zum Zeitpunkte der Erzeugung mitgeben zu können. Wer soll also jetzt die Objekte erzeugen?

Das Pattern „Assisted Inject“ zur Lösung des Konflikts sieht wie folgt aus: Der DI Container erzeugt zunächst eine Factory für die Objekte. Diese Factory wird mit den Abhängigkeiten versehen, die später die Objekte erhalten sollen. Die Clients bekommen nun vom DI Container die Factory zur Verfügung gestellt. Zum gewünschten Zeitpunkt erzeugen die Clients dann die Objekte durch Aufruf einer Factory Methode. Die Factory Methode erhält die gewünschten Parameter und reicht diese zusammen mit den Abhängigkeiten – die der Factory bekannt sind – an den Konstruktor weiter.

Diese Lösung lässt sich leicht „von Hand“ programmieren und ist nicht von der Verwendung eines bestimmten DI Containers abhängig.

Es mag jedoch lästig erscheinen, die zusätzliche Factory zwischen Client und dem benötigtem Typ zu schreiben. Sie enthält im Prinzip nur „Boilerplate Code“ zum Durchreichen der Parameter und Abhängigkeiten. Wer Guice verwendet, bekommt dazu Hilfe angeboten. Eine Erweiterung zu Guice kann die Factory zur Laufzeit dynamisch generieren. Es genügt, ein Interface für die Factory Methode zu schreiben (siehe Link oben).

Auch für CDI existiert solch eine Erweiterung.

http://www.warski.org/blog/2010/12/improving-autofactoriesassisted-inject/

Der Autor dieser Erweiterung moniert in seinem Blog einen Mangel des vorgestellten Patterns. Im Konstruktor des verwendeten Typs sind Parameter und die echten Abhängigkeiten vermischt. Es ist nicht explizit mit OO Mitteln modelliert, was Abhängigkeiten und was Parameter sind. Daher muss man auch bei Verwendung einer der Erweiterung die Konstruktor-Parameter annotieren, die keine Abhängigkeiten sind. Ansonsten kann der DI-Container bzw. die Erweiterung diese nicht unterscheiden. Der Autor der CDI Erweiterung versucht diese Unschönheit durch kombinierte Verwendung von Kontruktor- und Feld-Injektion zu modellieren. Konstruktor-Injektion für die Paramter und Feld-Injektion für die Abhängigkeiten. Das ist in meinen Augen nicht unbedingt eine Verbesserung. Ich bin an sich kein Freund von Feld-Injektion. Und dann auch noch gemischt mit Konstrutor-Injektion scheint mir das ziemlich gekünstelt. Der Code wird dadurch nicht unbedingt verständlicher.

Ich möchte hier eine alternative Java Implementierung des Assited Inject Patterns vorstellen. Mir gefällt diese Implementierung aus zwei Gründen. Erstens ist der Unterschied zwischen den Abhängigkeiten und Parameter explizit mit OO Mitteln modelliert. Zweitens ist der Boilerplate Code etwas reduziert, dass vielleicht die Notwendigkeit für den Einsatz von Erweiterungen entfällt. Der Trick der Implementierung besteht in der Verwendung einer inneren Klasse.

public class PaymentFactory {

    private final CreditService creditService;

    @Inject
    public PaymentFactory(CreditService creditService) {
        this.creditService = creditService;
    }

    public class Instance implements Payment {

        public Instance(Date startDate, Money amount) {
            // ...
        }

        public void doSomething() {
            creditService.serviceCall();
        }

    }

}

public class Client {

    private final PaymentFactory paymentFactory;

    @Inject
    public Client(PaymentFactory paymentFactory) {
        this.paymentFactory = paymentFactory;
    }

    public void createPayment() {
        Money amount = null;
        Date startDate = null;

        Payment myPayment = paymentFactory.new Instance(startDate, amount);
    }

}

Da diese Lösung mit einer konkreten Factory ohne Interface arbeitet, kann man sich die Factory Mehtode sparen und die Java Syntax für Konstruktion von inneren Klassen verwenden. Unschön ist, dass sich die Factory nicht austauschen lässt (z.B. durch einen Mock für Tests) und dass alle Clients abhängig von der konkreten inneren Klasse sind. Wem das nicht gefällt kann auch ein Interface einziehen, muss dafür aber die Factory Methode ergänzen:

public class InnerClassPaymentFactory implements PaymentFactory {

    private final CreditService creditService;

    @Inject
    public InnerClassPaymentFactory(CreditService creditService) {
        this.creditService = creditService;
    }

    @Override
    public Payment create(Date startDate, Money amount) {
        return new Instance(startDate, amount);
    }

    public class Instance implements Payment {

        public Instance(Date startDate, Money amount) {
            // ...
        }

        public void doSomething() {
            creditService.serviceCall();
        }

    }

}

public class Client {

    private final PaymentFactory paymentFactory;

    @Inject
    public Client(PaymentFactory paymentFactory) {
        this.paymentFactory = paymentFactory;
    }

    public void createPayment() {
        Money amount = null;
        Date startDate = null;

        Payment myPayment = paymentFactory.create(startDate, amount);
    }

}

Beiden Lösungen ist gemein, dass der Unterschied zwischen Parametern und Abhängigkeiten explizit modelliert ist. Die Parameter sind die Konstruktor Argumente des betrachteten Typs (hier Payment). Die Abhängigkeiten tauchen nun als Abhängigkeiten der Factory auf. Das Pattern besteht ja genau in dem Trick, die Abhängigkeiten des Typs zu Abhängigkeiten der Factory zu machen. Die Regeln für Sichtbarkeit bei innere Klassen in Java erlauben es, dass die Instanzen des Typs Zugriff auf die Abhängigkeiten der Factory haben. Das Durchreichen der Abhängigkeiten entfällt.

Dependency Injection considered useful

Veröffentlicht: 12. August 2011 von pmischke in Dependency Injection

Im folgenden möchte ich gerne den Übergang vom letzten Eintrag Dependency Inversion Principal (DIP) zum Dependency Injection (DI) Container schaffen. Mit dem Titel meines Posts beziehe ich mich auf

Der Post von Nat Pryce ist ein wenig provokant aufgezogen und führte daher zu viel Diskussion in der Kommentar Sektion. Das abschließende Fazit von Nat lautet

Let me clarify… the title — „Dependency Injection“ considered harmful — refers to the fact that I consider the term „Dependency Injection“ harmful — it is misleading and as a result DI frameworks often do not actually do DI at all because they focus on „injection“ and not the clear, explicit management of dependencies between objects.

Zum einen geht es Nat also um die Wahl des Namens. Insbesondere um den Ausdruck „Injection“ für die Technologie, sprich die DI Container. Aber noch wichtiger kritisiert er, dass in Folge dessen die DI Container nicht dazu genutzt werden, die OO Konzepte hinter DI umzusetzten. Das sind Konzepte wie eben das DIP und die im Post genannten Verweise auf das GOOS Buch. Stattdessen wird die Technologie ohne Rücksicht auf die Konzepte verwendet. Im Gegenteil werden durch die Technologie sogar OO Prinzipien wie Kapselung ausgehebelt.

In das gleiche Horn stößt

Die wichtige Aussage von Mark Seemann in diesem Zusammenhang ist

What’s really lacking, at least in the .NET world, is an understanding that DI is really about principles and patterns, and not about technology.

As .NET developers we have been raised by Microsoft to believe that every problem can be addressed with a tool. When it comes to loose coupling, DI Containers look like enabling technology, but it’s really, really important to realize that the solution doesn’t lie with the tool. It lies in the understanding that DI (or Inversion of Control) is a fundamentally different way to reason about and design software.

This relates very closely to the SOLID principles – in fact, DI is just an elaboration of the ‚D‘ in SOLID, so it’s far from new knowledge. In my opinion, SOLID very nicely captures the essence of OOP, and if you write SOLID code, you also utilize DI. Technology in the shape of a container is totally optional at this point.

Auch Mark sagt, dass wichtige an DI sind die Konzepte, insbesondere das D aus den SOLID Prinzipien, also das DIP. Im übrigen ist der Irrglaube der heilbringenden Technologie in der Java Welt genauso verbreitet.

Fassen wir also zusammen: OO Konzepte wie das DIP sind notwendige Voraussetzung für erfolgreiche Anwendung von Dependency Injection. Bis zu dieser Stelle sind Nat, Mark, wahrscheinlich viele andere auch und ich alle der selben Meinung. Bei der Rolle der Technologie in Form des DI Containers gehen die Meinungen jedoch auseinander.

Nat hält den Container für eine Behinderung. Darum verzichtet er ganz auf ihn und schreibt die separierten Kompositionslogik lieber selbst. Die Kompositionslogik ist dadurch klar in Code ausgedrückt, gut sichtbar und unterliegt dem normalen Refactoring. Die Argumente sind durchaus nachvollziehbar. Ja, es ist wichtig, die Abhängigkeiten explizit im Code auszudrücken. Daher befürworte ich, dass die JSR-330 DI Container die @Inject Annotation am Konstrutor erzwingen, auch wenn man das per Konvention regeln könnte, wie es einige .NET DI Container machen. Auf die Idee, die Kompositionslogik selber zu schreiben, würde ich nicht kommen. In der Kompositionslogik finden sich wiederkehrende Muster. Zum Teil sind diese Muster bereits hier und da dokumentiert, zum Teil auch nicht (Vielleicht ist das ein oder andere Muster demnächst in diesem Blog zu finden 🙂 ). Wie dem auch sei, sollte man die wiederkehrende Logik doch allgemein und wiederverwendbar lösen und nicht in jeder Anwendung neu. Das ist doch genau die Leistung des DI Containers, oder?

Mark beschäftigt sich sehr intensiv mit Containers, hat ein Buch dazu in Vorbereitung. Das ist alles andere als Ablehnung. Dennoch hält er den DI Container für optional (siehe Zitat oben).

Und wie stehe ich zu DI Containern? Natürlich kann der DI Container missbraucht werden, wie jede Technologie. Aber die Möglichkeit zum Missbrauch ist für mich noch kein Grund zur Ablehnung. Sauberes OO Design ist nach wie vor die notwendige Voraussetzung für ein nachhaltiges System. Der DI Container kann meiner Erfahrung nach zum Katalysator für gutes OO Design werden und macht sich damit zum Pflichtbestandteil. Gutes Design kommt schließlich nie zum Null-Tarif. Der Aufwand, entkoppelte Module zu komponieren sinkt aber deutlich beim Einsatz eines DI Containers. Mit dem sinkenden Aufwand erhöht sich das Kosten-Nutzen-Verhältnis und damit meine Bereitschaft, diesen Aufwand zu treiben. Der DI Container ist also kein Selbstzweck, sondern Mittel zum Zweck. Der Theorie nach ist er optional, in der Praxis nicht!

Dependency Inversion – ganz neu entdeckt

Veröffentlicht: 7. Juli 2011 von pmischke in Dependency Injection

So, jetzt geht’s los! Dies ist der erste Post im Themenfeld „Dependency Injection“. Ich hoffe, es gelingt mir, dieses hoch interessante Thema weiter zu verfolgen.

Am Anfang steht das „Dependency Inversion Principle“ (DIP) von Robert Martin. Genauer gesagt war es 1995, was aus meiner beruflichen Perspektive schon sehr weit am Anfang ist. Trotzdem sieht es nicht so aus, als ob dieses Prinzip in der Software-Entwicklung allgemein verinnerlicht ist. Mir geht es nicht anders. Lange Zeit hatte ich nur ein sehr oberflächliches Verständnis des DIP. Seit kurzem bin ich einen Schritt weiter.

Aber was ist das DIP eigentlich? Es gibt viel Material dazu im Netz. Eine umfangreiche und verständliche Erklärung findet Ihr zum Beispiel hier:

Wir lernen also,

A. High-level modules should not depend upon low-level modules. Both should depend upon abstractions.

Ich finde es ganz interessant, sich zunächst einmal zu vergegenwärtigen, warum wir diese Abhängigkeiten von oben nach unten überhaupt haben. Martin weist im Original Artikel darauf hin. Die traditionelle strukturierte Programmierung lehrt uns, große Probleme in mehrere kleine Probleme aufzuteilen und dann die große Lösung aus den kleinen Lösungen zusammen zu setzen. So ergeben sich die Hierarchien, in denen das oberste Modul letzendlich von allen anderen abhängt. Jede Änderung wirkt sich die Hierarchie hoch durch das ganze System. Eigentlich ziemlich unschön, aber dieses Prinzip sitzt sehr fest in unseren Köpfen. Die objektorientierte Programmierung hat bisher nur wenig daran geändert.

Obwohl der objektorientierte Werkzeugkasten mehr zu bieten hat. Das DIP zeigt, dass die Abhängigkeiten von oben nach unten durch Abstraktionen umgekehrt werden können. Für die Abstraktionen nehmen wir Schnittstellen, also Interfaces in Java und C#. Weiter heißt es im DIP

B. Abstractions should not depend upon details. Details should depend upon abstractions.

Was bedeute das? Dieser seltsam wirkende zweite Teil hat etwas mit C++ zu tun. Ja genau, um 1995 hab auch ich mit C++ entwickelt, aber das ist Geschichte. Mit den Interfaces aus Java kann ich meine Module perfekt entkoppeln, ohne mir darüber Gedanken zu machen.

Mit diesem Erkenntnisstand bin ich lange gut gefahren. Zumindest dachte ich das. Bei dem Versuch, meine Kollegen vom DIP und dem guten Design zu überzeugen, welches sich damit erreichen lässt, kam dann folgender Einwand. Die Schnittstelle macht nur mehr Arbeit. Änderungen fanden vorher nur in den beiden Module statt. Und nun muss ich immer drei Stellen ändern. Die Schnittstelle, das implementierende Modul und das nutzende Modul. Ja das stimmt zwar… aber nur wenn sich die Schnittstelle ändert. Ich kann also leicht meine Bugs in der Implementierung fixen. Bei wirklichen Änderungen habe ich zugegebenermaßen nicht viel gewonnen. Tja, dagegen kann man nichts machen.

Dumm nur, das unser Geschäft quasi ausschließlich aus Änderungen besteht. Und eigentlich kann ich Bugs auch gut ohne separierte Schnittstelle in dem Modul fixen, wenn die Signaturen der Methoden nicht betroffen sind. Was bringt mir das DIP also?

Der Schlüssel liegt in dem zweiten Teil des DIP, den ich so schnell beiseite gelegt hatte. Abstraktionen dürfen nicht von Details abhängen! Anders ausgedrückt, die Schnittstelle muss überhaupt eine Abstraktion sein. In der IDE schnell mal den „Extract Interface“ Wizzard starten, erzeugt zwar eine Schnittstelle, aber keine Abstraktion. Diese Schnittstellen unterscheiden sich nicht einen Deut von den öffentlichen Methoden eines Moduls, das ohne Schnittstelle genutzt wird. Es stellt sich genau der Effekt ein, dass alle Änderungen trotz Schnittstelle nach oben durchschlagen.

Ich möchte einfaches Beispiel geben.

public Customer findCustomerById(long id);

Diese Abstraktion hängt von Details ab. Nämlich von dem Detail, dass ich den long Typ für meine IDs verwende. Bei der Umstellung auf UUID wird wahrscheinlich einiges an Code geändert werden.

public Customer findCustomerById(ID id);

Diese Abstraktion hängt nicht von Details ab. Wenn mein eigener Typ ID den Typ der Implementierung versteckt, ist das nutzende Modul von einer Umstellung entkoppelt. Wenn sich das Wesen der Methode nicht ändert, wird sich auch die Schnittstelle nicht ändern. Eine Methode, die einen Kunden zu einer gegebenen ID findet, wird immer eine ID als Parameter bekommen und einen Kunden zurück liefern. Egal, wie die Implementierung aussieht.

Es ist nicht einfach, die echte Abstraktion zu finden, die hinter einer Schnittstelle liegt. Die IDE kann das nicht leisten. Hier ist das Gehirn gefragt. Und nicht zu knapp. Aber es lohnt sich. Die echte Abstraktion bringt Stabilität in die Schnittstelle. Häufige Änderungen an der Schnittstelle sind ein Hinweis auf mangelnde Abstraktion. Der zweite Teil des DIP ist für mich inzwischen wichtiger geworden, als der erste. Ohne Abstraktion funktioniert die Schnittstelle nicht.

Auch unter Silverlight stellt sich die Frage, wie automatisiert getestet werden kann. Stefan Lieser schreibt in seinem Artikel Automatisiertes Testen und Silverlight darüber, dass die von Microsoft bereitgestellte Lösung nicht ausreichend ist. Da ich das genauso sehe, suchte ich nach einer Lösung mit der die Tests auch im Continuous Integration System ausgeführt werden können.

Glücklicherweise erlaubt es das Silverlight Unit Test Framework eigene Unittest Werkzeuge hinzuzufügen. Für NUnit gibt es das Projekt nunit-silverlight. Somit ist es möglich, NUnit anstelle von MSTest zu verwenden. Dazu ist laut Dokumentation nur (neben dem Hinzufügen der notwendigen DLLs) nur folgender Code notwendig:

Das löst aber leider noch nicht das Problem, dass für das Ausführen der Tests der Silverlight Testrunner im Browser ausgeführt werden muss. Um dieses Problem zu lösen, gibt es sogenannte Silverlight Test Runner. Eines dieser Werkzeuge ist Lighthouse. Dieser Runner ermöglicht es Silverlight Unittests von der Kommandozeile aus auszuführen. Voilà alles gelöst. Fast.

Denn leider kann Lighthouse in der jetzigen Fassung keine NUnit Tests ausführen. Aber es ließ sich leicht anpassen, dass Lighthouse nunit-silverlight verwenden kann. Hierzu muss der NUnit-Provider von nunit-silverlight hinzugefügt werden. Dazu ist in der Klasse MyUnitTestSystem.cs im Projekt Lighthouse.Silverlight.Core folgende Zeile hinzuzufügen:

Und noch eine Fehlerquelle gilt es auszuschließen: Lighthouse verwendet intern auch einen Browser zum Starten des Silverlightkontextes auch wenn dies nicht sichtbar ist. Sollte Lighthouse im CI verwendet werden, so muss auch auf dem CI-Server ein Browser samt Silverlight Runtime installiert sein.

Und: Lighthouse generiert (unabhängig vom verwendeten Testframework) NUnit-Testreports. Diese lassen sich sehr einfach u.a. im Hudson/Jenkins darstellen, wie man sieht:

Das ganze lässt sich dann noch schön in einen Maven Build Prozess einbetten, aber das wird ein anderer Post.

Die hier vorgestellte Lösung löst meiner Meinung nach das Problem, vernünftig Unittests mit NUnit für Silverlight zu schreiben, welches Stefan Lieser in seinem Artikel Automatisiertes Testen und Silverlight beschrieben hat. Auch die Einbindung in Resharper funktioniert auf Anhieb.

Pattern Driven Development ist keine Lösung

Veröffentlicht: 30. Dezember 2010 von Christian Raschka in Uncategorized

„A pattern addresses a recurring design problem that arises in specific design
situations, and presents a solution to it.“ (Aus Buschmann, F., Meunier, R., Rohnert, H., Sommerlad, P., Stal, M. (1996) A
System of Patterns. John Wiley & Sons.)

Hm… ein Pattern soll uns helfen ein Problem zu lösen. Die Frage ist nur welches? Und woran erkenne ich, wenn ich denn eins habe, welches Pattern mir dabei hilft es zu lösen? Diese Fragen sind scheinbar nicht einfach zu beantworten, anders kann ich es mir nicht erklären, warum es so viel Literatur über Antipatterns gibt. Viele vermeintlich gute Muster werden sehr schnell zu Problemstellen ganzer Softwarebausteine. Denn leider gibt es in den seltensten Fällen eine optimale Lösung. Alle Lösungen (und auch die meisten Patterns) beinhalten „Kosten“. Diese werden zwar bei sinnvoller Anwendung der Muster meist durch die Vorteile aufgehoben. Doch ob und wann dieser Zustand eintritt ist nicht bekannt.

Was also passiert ist folgendes: Man nimmt sich eine Liste von „Best-Practices„, nennen wir diese in diesem Fall „Pattern-Katalog“. Wenn ich nun nach diesen Mustern entwickle kann mir doch eigentlich nichts passieren, oder doch? Leider eben schon. Und ich meine dabei nicht einmal nur das Singleton-Pattern. Viele der Lösungen sind möglicherweise zu kompliziert oder führen Abhängigkeiten ein, die es ohne Anwendung des Pattern gar nicht gegeben hätte.

Um dies zu untersuchen, hatten wir folgende Idee: Wir machen „Brain-Driven-Development“. Anstatt irgendwelche Probleme zu suchen, die dann mittels Pattern gelöst werden können, verwenden wir unseren Verstand. Zugegebenermaßen klingt dies etwas provozierend aber ich möchte erläutern, was ich damit meine.

Wir wollen eine Software erstellen, die ein bestimmtes Problem löst und dazu eine grafische Benutzeroberfläche bereitstellt. Die meisten würden an dieser Stelle wohl sehr schnell in den Raum schreien, wir brauchen dazu MVC (oder MVP, MVVM …). Aber wie kann ich das an dieser Stelle schon wissen? Die Anforderung war noch gar nicht so weit, um zu wissen, dass dies notwendig ist.

Wie wäre denn mein folgender Vorschlag: Wir lassen mal außen vor, was wir über (GUI-) Patterns wissen. Nur kurz. Und dann fangen wir an. Wir erstellen uns Schnittstellen der Aufgaben, die die GUI später anzeigen soll. Wie diese zu implementieren sind, ist uns an dieser Stelle egal. Und dann entwerfen wir die GUI. Möglicherweise brauchen wir Dummyimplementierungen der Schnittstellen damit wir vernünftig arbeiten können, aber das sollte ja kein Problem sein. Und wenn wir fertig sind, fangen wir an die Implementierung dieser Schnittstellen zu modellieren…

Was haben wir damit erreicht? Eine Trennung von Anzeigelogik und Geschäftslogik? Jawohl. Also ja doch MVC? Nein, denn es wird wahrscheinlich keine Klasse geben, die Controller heißt. Aber vielleicht ja doch. Und eventuell stellt sich hinterher heraus, dass eine Klasse die Aufgabe eines Presenters erfüllt, dann nenne ich diese um, damit andere dies auch erkennen. Und dann kommt auch der volle Nutzen von Patterns zum Tragen.

Wer also gut Software erstellen möchte, sollte nicht auf Teufel komm raus versuchen Patterns anzuwenden. Lieber sollte man versuchen, seinen Verstand einzusetzen und dann möglicherweise auch Patterns.

Wir lösen am liebsten die schwierigen Probleme

Veröffentlicht: 21. Dezember 2010 von pmischke in Uncategorized

Vor einiger Zeit las ich einen Artikel von Oren Eini, in dem er eine Architektur mit rich client und server back end vorstellt (siehe unten). In diesem Artikel findet sich folgendes Zitat:

The actual code is pretty boring. […] However, this is more important than you might think. An architect’s job, I’d argue, is to make sure that the developers in the project are as bored as possible. Most business problems are boring, and by removing technological complexities from the system, you get a much higher percentage of developer time spent working on boring business problems instead of interesting technological problems.

Hier sehe ich einen gewissen Interessenkonflikt. Zusammenfassend könnte man demnach auch sagen, dass gute Architektur zu langweiligem Code führt. Es hat aber niemand großen Spaß daran, langweiligen Code zu schreiben.

Wird die Rolle des Architekten nicht von einem Entwickler eingenommen, wäre dieser bei den Entwicklern bestimmt schnell „unten durch“. Wer lässt sich schon gerne die langweiligen Aufgaben zuschieben? Es ist fraglich, wie lange der Architekt seine Autorität aufrecht erhalten kann, bevor die Entwickler eigene Architekturen aufziehen.

Wird die Architektur hingegen von den Entwicklern selbst gemacht, ergibt sich der angesprochene Interessenkonflikt. Warum sollte ich dafür sorgen, dass meine Arbeit langweilig wird?

Ich glaube, die Lösung des Konflikts liegt im Wertesystem. Einfachheit wird in der Softwareentwicklung vielfach mit langweilig gleich gesetzt. Hohe Komplexität ist interessant, spannend und herausfordernd. Hohe Komplexität zu beherrschen,  ist unser Ding. Vielleicht sollten wir uns aber auf die positiven Aspekte von Einfachheit besinnen. Einfachheit ist verständlich, ästhetisch, genial. Weitere Plädoyers für Einfachheit finden sich bei Wikipedia und Wikiquote.

Glück auf!

Veröffentlicht: 19. Oktober 2010 von Christian Raschka in Uncategorized

Willkommen im neuen Blog für mehr Qualität und Professionalität in der Softwareentwicklung. Aber wozu brauchen wir mehr Qualität? Wir wollen „Programme“ erstellen, die dem Kunden einen Mehrwert bringen. Dazu ist es notwendig möglichst wenig Kosten zu verursachen. Es kommt also nicht darauf an, möglichst viele neue Technologien, Prinzipien oder Buzzwords zu verwenden. Dies bringt dem Kunden erstmal nichts. Und trotzdem ist es oft sinnvoll einige dieser Dinge zu benutzen, weil sie uns in einem bestimmten Kontext eventuell einen Mehrwert bringen. Dies kann gesteigerte Evolvierbarkeit oder mehr Korrektheit. Aber vielleicht auch einfach schnelleres und kostengünstiges Entwickeln. All dies muss abgewägt sein. Und  genau dies möchten wir in diesem Blog erreichen: Kritisches Auseinandersetzen und Abwägen von aktuellen Softwareentwicklungsthemen.

Wir wollen ja letztendlich Programme und Produkte fabrizieren und dazu gehört es schließlich Code auf die Straße zu bringen. Dazu haben wir verschiedene Autoren gewinnen können, die zu pragmatischem Erstellen von Software schreiben werden. Nicht regelmäßig – aber regelmäßig mit hoher Qualität. Dazu gehören:

  • Sebastian Jancke, Software-Architekt, Trainer
  • Peter Mischke, Software-Architekt, Trainer und Scrummaster
  • Christian Raschka, Software-Architekt, Trainer und Sprecher
  • Uli Schulze-Eyßing, Software-Architekt und Berater
  • Christian Strebe, Software-Entwickler

Also dann freuen Sie sich gemeinsam mit mir auf gesteigerte Produktivität und Qualität aus dem Kombinat Programmproduktion West (KPPW)!

Mit sozialistischem Gruß

Christian Raschka