Peter Bucher Ralf Westphal

Blog

Nutze den Augenblick
und teile der Welt mit, was Du zu sagen hast.

.NET Professionals im Profil: Ralf Westphal

Freitag, 15. Januar 2010, 09:37 Uhr
Permalink | Kommentare (0) | Kommentare als RSSRSS

Ralf Westphal ist freier Softwaretechnologievermittler, Mitgründer des Professional Developer College und Mitinitiator von Clean Code Developer. Er war von 1998 bis 2005 einer der unabhängigen Microsoft Regional Directors für Deutschland und wurde von Microsoft als MVP „Visual Developer Solution Architect“ ausgezeichnet. Sie erreichen ihn über seine Webseite.

Golo Roden: Ralf, wie bist Du zur Softwareentwicklung gekommen? Wie und wann hast Du angefangen?

Ralf Westphal: Wenn ich mich recht erinnere, habe ich 1980 mit dem Programmieren angefangen. Oder war es schon 1979? Jedenfalls stand am Anfang ein Büchlein mit einer Einführung in Pascal. Ganz ohne Computer habe ich das in einem Urlaub durchgearbeitet. Da ging es vor allem um Algorithmen: Sortieren, die Türme von Hanoi und solche Sachen. Danach dann die offizielle Pascal Sprachdefinition. Die hat mich mit der EBNF konfrontiert. Nach dem Urlaub begann der Informatikunterricht in der Schule. Für den hatte ich mich fit gemacht. Unterrichtssprache Pascal. Auf einer Dietz-Anlage mit Bernsteinterminals. Der Lehrer war durchaus bemüht und offen für unsere Ideen. War eine lustige Zeit.

Irgendwie in der Zeit habe ich mich dann auch um einen Computer zu Hause bemüht. Am Anfang war das ein Tandy TRS-80. Darauf habe ich Z-80-Assembler programmiert, zum Beispiel einen Texteditor. Danach kam ein Apple II mit CP/M-Betriebssystem, weil ich weiter Z-80-Assembler programmieren können wollte. Mit Apple Basic habe ich nur wenig gemacht – aber doch zumindest einen ersten Job realisiert. Und meinen ersten Artikel für die damalige Computer Persönlich-Zeitschrift von Markt + Technik habe ich auch über ein Programm in Apple Basic geschrieben. Da ging es irgendwie um die Komprimierung von Programmcode, weil der Hauptspeicher so begrenzt war. Der nächste Artikel hat sich auf der Basis von UCSD Pascal mit 3D-Grafiken beschäftigt.

Als ich 1983 zur Bundeswehr kam, habe ich den Apple mitgenommen und einige Verwaltungsaufgaben damit auf dem Geschäftszimmer erledigt. Ich wurde dort eingesetzt, weil ich durch die Computerarbeit flüssig mit einer Schreibmaschine beziehungsweise einer Tastatur umgehen konnte.

Und weiter? Hm ... in der Uni haben wir eher auf größeren Anlagen gearbeitet. Da erinnere ich mich an ein Seminar in Assembler. Ausbildungssprache Pascal. Gelernt habe ich dort nicht mehr viel. Privat ging es mit Turbo Pascal weiter. Das hatte ich seit meiner Schulzeit, fand es supercool und habe sogar ein Lehrbuch für die Schule dazu geschrieben. Leider ist das nie zum Einsatz gekommen.

Später bin ich auf C und Modula mit CP/M umgestiegen. Das war leading edge technology damals. Beides war von der Firma Lightspeed und konnte sogar zusammengelinkt werden.

„Auf der Arbeit“ bin ich eher mit Unix konfrontiert worden. Zum Beispiel habe ich für ein Forschungsinstitut einen Ganzseiteneditor gebastelt, mit dem man vernünftig – so wie damals mit WordPerfect – Prolog-Code schreiben konnte. VI war den Forschern und auch mir zu umständlich.

Weiter ging es mit 4GL-Sprachen und Smalltalk. Und schließlich ab 1990 C++ für ein bis zwei Jahre. Ab Visual Basic 1.0 dann Visual Basic bis zum Abwinken.

Golo Roden: Du hast Dich auf die .NET-Plattform spezialisiert. Warum gerade .NET und nicht beispielsweise JEE (Java Enterprise Edition)?

Ralf Westphal: Java hat mich 1995 interessiert. „Java in a Nutshell“ oder so hatte ich schon vor dessen Erscheinen bestellt. Ich fand die Sprache auch cool – sie bot damals wegen ihres Fokus auf die Webentwicklung nichts für die Desktop-Branchensoftwareentwicklung. Von 1987 bis 1998 habe ich ja mit einem Partner ein Branchensoftware-Schmiede gehabt – er macht das auch heute noch –, bei der wir MS-DOS- und später Windows-Anwendern etwas bieten mussten. Das Web war ja nur für mutige Early Adopters interessant. Nach einer 4GL-Lösung, die wir ab 1987 entwickelt hatten – und die auch heute noch bei einigen Anwendern im Einsatz ist! – hatten wir auf Visual Basic gesetzt. C++ war uns zu umständlich, Delphi noch nicht ausgereift genug. Also Visual Basic von 1.0 bis 6.0. Außerdem kam dann 1996 / 1997 oder so ASP um die Ecke, so dass wir im Web auch mit unseren Visual Basic-Kenntnissen arbeiten konnten. Java bot uns angesichts dessen zuwenig. Damit war die Weiche gestellt. Als ich 2000 .NET auf der PDC gesehen hatte, wusste ich, dass das der natürlich weitere Weg sein würde.

Golo Roden: Ein wesentliches Merkmal der IT ist, dass man beständig mit neuen Entwicklungen konfrontriert wird, und diesen folgen muss. Woher nimmst Du die Motivation, Dich quasi jeden Tag weiterzubilden und mit Neuem zu beschäftigen?

Ralf Westphal: Das ist mein Job. Dieselbe Antwort gibt dir ja auch ein Bäcker, wenn du ihn nach der Motivation fragst, die ihn jeden Tag Brötchen backen lässt. Im Vergleich zum Entwickler in einem Projekt empfinde ich also keine Spannung zwischen „Arbeit“ und „Fortbildung“. Meine Arbeit ist Fortbildung. Der Zweck: Anderen mit meinem Wissen zu helfen. Ich bin kein „Programmierer“, sondern eher „Softwaretechnologievermittler“. „Trainer“ wäre zu eng gefasst, „Lehrer“ zu institutionell, „Berater“ auch zu eng. Also „Technologievermittler“ und „One Man Think Tank“. Diese Bezeichnung habe ich nach einigem Grübeln gewählt für meine „Firma“ gewählt, weil sie ausdrückt, was und wie ich arbeite: In der Form bin ich Freiberufler, arbeite also allein. Zumindest habe ich solch einen Hut, den ich aufsetze. Inzwischen gibt es noch andere wie „Mitgründer des Professional Developer College“ oder „Mitinitiator von Clean Code Developer“. Wenn ich diese Hüte aufsetze, arbeite ich nicht allein, sondern mit Partnern. Ursprünglich war ich aber eben reiner „Einzelkämpfer“ seit 1998, also „One Man“ Show.

Der „Think Tank“ beschreibt eher den Inhalt meiner Arbeit. Mein Job ist das Nachdenken, das Tüfteln, Ausprobieren. Ich möchte es fast schon als Forschung bezeichnen. Meine Ergebnisse sind weniger Code, als vielmehr Konzepte, Ansätze. Damit erlaube ich mir etwas, das sich viele Unternehmen und Teams nicht erlauben. Während Kollegen eher „normale“ Beratung machen, bei der sie sich auf Technologien konzentrieren, deren Einsatz begleiten oder sie gar für ihre Kunden einsetzen, bewege ich mich oft eine Ebene darüber, das heißt im Konzeptionellen.

Natürlich programmiere ich auch. Jeden Tag. Ich habe also keine Angst, abzuheben. Doch wenn schon die Firmen ihren Kopf nicht aus dem Sand der Projekte heben können, dann will zumindest ich das tun. Das macht mir Spaß, das kann ich – so glaube ich – ganz gut. So sehe ich mich als Ergänzung zu Teams, die sie bei Bedarf „zuschalten können“. Die externe Forschungsabteilung, der Blick von außen, der Spiegel, der Fragensteller, der Impulsgeber.

Damit ich das alles sein kann, muss ich halt immer etwas Neues auf der Pfanne haben, lesen und nachdenken. Früher hatte ich da mal Angst, dass ich da an eine inhaltliche oder motivationale Grenze stoßen könnte. Bisher spüre ich davon nichts. Vor 18 Monaten hatte ich noch keine Ahnung, dass ich heute mit Clean Code Developer unterwegs sein würde. Was in 18 Monaten ist, weiß ich auch nicht. Ich bin aber gewiss, da wird mich etwas Neues, Spannendes beschäftigen, das ich dann in die Community tragen kann.

Golo Roden: Wenn sich ein Anfänger heute mit dem Thema Softwareentwicklung befassen will – welche Voraussetzungen sollte er Deiner Meinung nach dafür mitbringen, und was siehst Du als No-Go an?

Ralf Westphal: Welche Art Anfänger meinst du? Einen Schüler, der noch nicht so recht weiß, was er mal werden will? Oder jemanden, der schon in eine Informatikausbildung eingestiegen ist? Oder jemanden, der gerade damit fertig geworden ist?

So ganz allgemein und grundlegend würde ich mal sagen, dass jemand, der sich mit Softwareentwicklung beschäftigen will, Spaß am Nachdenken haben sollte. Das Denken, Nachdenken, Selbstdenken steht de facto leider nicht wirklich hoch im Kurs in unserer Gesellschaft. Zwar sollen Schüler das Denken lernen – dafür ist Schule ja da –, doch passiert das nicht verlässlich genug, meine ich. Solange noch Talentshows und Sport solchen Raum in den Medien einnehmen, wie sie es tun. Solange sich die Nation so unverhältnismäßig über etwas wie die Schweinegrippe echauffieren kann. Solange es gesellschaftsfähig ist, mit technischer, geschichtlicher, philosophischer Unbildung zu kokettieren, solange steht Nachdenken einfach nicht hoch im Kurs.

Das soll jetzt natürlich nicht bedeuten, dass die Welt mehr freiberufliche Nachdenker wie mich braucht. Ich meine nur, dass in der Softwareentwicklung, deren Materie das Virtuelle und Abstrakte ist, Nachdenken ganz wichtig und daher Spaß am Nachdenken Voraussetzung ist. Software entsteht zunächst im Kopf durch rigoroses, systematisches und kreatives Denken mit einer gehörigen Portion Reflexion und Skepsis.

Zum Spaß am Denken sollte dann noch Spaß am grundsätzlich Technischen kommen. Auch da steht es leider in der Grundausbildung schlecht. Technische Unbildung grassiert. Nicht nur ist den meisten schon der Dreisatz ein Buch mit sieben Siegeln, auch die mechanische oder elektronische Funktionsweise von Maschinen interessiert viele nicht. Was unsere moderne Welt zusammenhält – Technologie – wird nicht systematisch als interessant vermittelt. Fernseher und Computer und Handy benutzen alle gern – doch die nächsten Generationen selbst mitgestalten, dazu haben sie keine rechte Lust. Anders kann ich mir die sinkenden Studentenzahlen bei der Informatik nicht erklären.

Zum Spaß am Denken und an Technik im Allgemeinen – Grundfrage: Wie funktioniert das? – sollten noch Fertigkeiten der Visualisierung treten. Software entsteht im Kopf und muss dann kommuniziert werden. Nicht unbedingt in Form von Code, sondern zuerst einmal mit Bildern. Auch Nachdenken profitiert von Bildern. Wer ein gutes Vorstellungsvermögen hat – vor allem ein bildliches – und seine Vorstellungen dann auch noch anderen vermitteln kann, der hat einen Vorsprung. Das habe ich gerade gestern beim Unterricht in der School of .NET gesehen. Die Teilnehmer konnten sich eine Lösung für eine Übungsaufgabe so schwer vorstellen; ihnen fehlten Bilder für ein Modell. Deshalb gab es dann Probleme bei der Codierung.

Noch allgemeiner als Fertigkeiten zur Visualisierung sind solche zur Kommunikation schlechthin. Software ist kein Business für „lonesome rangers“. Der einsame Hacker ist out. In sind Entwickler, die fachliche und methodische Kompetenzen, die sie in einer Ausbildung erwerben, dank Softskills in ein Team einbringen können. Wissen und Ideen nicht nur visuell vermitteln können, sondern auch verbal, das ist wichtig. Zuhören können, emotionale Kompetenz, Selbstdisziplin, moderieren, ... das sind Fertigkeiten, die wir brauchen. Software entsteht im Team.

Die Motivation für eine Karriere in der Softwareentwicklung kommt also für mich aus dem Spaß am Denken, am Abstrakten und an Technik. Die Fähigkeit, sich dann auch erfolgreich einzubringen, machen Softskills aus. Fachkompetenz vermittelt – hoffentlich – eine Ausbildung.

Golo Roden: Gemeinsam mit Stefan Lieser hast Du die Initiative „Clean Code Developer“ ins Leben gerufen. Welche Bedeutung misst Du diesem Thema bereits für Anfänger bei?

Ralf Westphal: Die Bedeutung von Clean Code Developer für Anfänger ist nicht zu überschätzen! Hohe innere Qualität ist keine Sache für fortgeschrittene Entwickler. Sie muss vielmehr vom ersten Tag der Ausbildung an Thema sein. Das ist auch der Grund, warum mich so viele Lehrpläne von Berufsschulen und Universitäten traurig machen. Sie vermitteln einzelne technische Fertigkeiten – aber kein qualitätsorientiertes Bild von der Softwareentwicklung. Beispiel Berufsschule, Ausbildung zum Fachinformatiker Anwendungsentwicklung (FIAE): Nur ein Achtel des Unterrichts sind überhaupt der Softwareentwicklung gewidmet, der Rest beschäftigt sich mit Deutsch, Religion und anderen Themen. Von diesem Achtel beschäftigen sich in einem Semester vielleicht fünf Prozent mit dem Thema Testen. Das sind weniger als ein Prozent in einem Jahr und auf drei Jahre gerechnet vielleicht 0,5 Prozenz, wenn es hoch kommt. Was wollen wir denn da erwarten von ausgebildeten FIAE, wenn sie während oder nach der Ausbildung im Projekt sitzen? Fangen die dann plötzlich mit TDD an?

Für mich liegt die Ausbildung solange im Argen, wie das Thema Testen nicht von der ersten Stunde an konsequent während des ganzen Unterrichts präsent ist. Soviel zum Thema Korrektheit. Dasselbe gilt für die anderen CCD-Werte wie Evolvierbarkeit, Produktionseffizienz und Reflexion.

Vom ersten Tag an. Die ganze Ausbildung durch. Immer. Nur wer diese Werte konsequent bewusst hält, kann am Ende erwarten, sie auch unter Projektdruck nicht zu verraten.

Klar, man kann auch später noch dazu lernen. Aber dann ist es schwieriger. Dann sind eingefahrene Gewohnheiten zu entlernen. Das macht große Mühe – und die Codebasis ist schon ein Brownfield. Warum also nicht mit CCD bei den Anfängern beginnen?

Golo Roden: Bei der Vielzahl an Technologien, die es heute gibt: Womit sollte ein Anfänger heutzutage anzufangen?

Ralf Westphal: Keine Ahnung. Es gibt keinen richtigen Einstieg in Technologien – oder gar Produkte. Die unterliegen ja auch Moden. Selbst wer heute mit PHP beginnt, kann einen guten Job bekommen, glaube ich. Insofern ist die Frage, ob jemand dazu fähig ist, sich selbst und die Marktentwicklung zu reflektieren. Wer das kann, kann dann nämlich auch reagieren. Der fängt mit PHP an und sattelt später um auf Erlang oder so.

Was nutzbringend ist, hängt vom Umfeld ab. Für einen Studenten wäre es vielleicht nicht sehr nützlich, wenn er sich als einziger in seinem Umfeld mit Axum beschäftigt. Dann gehen ihm soziale Kontakte und dadurch Möglichkeiten zum Austausch verloren. Die sind nicht zu verachten.

Ich denke, jeder ist gut beraten, seine Neigungen zu erspüren. Mag man es lieber visuell oder lieber persistent? Mag man es lieber enterprisegroß oder branchensoftwareklein? Das lässt sich aber womöglich erst mit der Praxis erfahren. Als Anfänger muss man deshalb wahrscheinlich einfach mit irgendetwas anfangen.

Technologien sind auch nicht so wichtig. Wichtiger sind Paradigmen und Konzepte. Die Frage sollte also lauten, mit welchen der Paradigmen sollte sich ein Anfänger auseinandersetzen. Da liegt die Objektorientierung nahe. Aber ich füge gleich einmal die Komponentenorientierung hinzu. Da liegt Agilität nahe. Da liegt die asynchrone Programmierung nahe. Da liegen Algorithmen und Datenstrukturen nahe. Ja, auch und gerade die. Da liegen Kommunikationskonzepte wie Nachrichtenorientierung und ereignisgesteuerte Architekturen (EDA) nahe.

Aber ob man sich damit nun auf der Java- oder .NET- oder Ruby-Plattform beschäftigt, ist recht egal. Und ob es bei .NET nun NServiceBus oder MassTransit für EDA ist, ob O/R-Mapping mit OpenAccess oder NHibernate gelernt wird, ... das ist egal.

Die wesentliche Invariante ist: Alles ändert sich. Also nicht anhaften. Keine Paradigma, kein Konzept und schon gar kein Produkt auf einen Thron heben. Denn wo gestern ASP oder Java-Applets die Bringer waren, da ist heute Silverlight der Hit. Alles fließt – wusste schon Heraklit, der unsere Branche nicht kennen konnte-

Golo Roden: Welchen Rat würdest Du einem Anfänger abschließend mit auf den Weg geben?

Ralf Westphal: Widerstehe dem oft ignoranten Druck im Projekt. Da wird auf die Tube gedrückt, da wird keine Zeit für Fortbildung gegeben, da wird kein Wert auf Evolvierbarkeit gelegt. Vor 150 Jahren waren Arbeitsbedingungen in Fabriken mit 16 Stunden Arbeitszeit bei Dreck, Lärm und kärglicher Bezahlung unmenschlich. Heute ist es natürlich viel besser – und auf der anderen Seite immer noch schlimm. Anders schlimm, subtiler schlimm.

Heute stimmt zwar die Bezahlung und so ganz grundsätzlich meist auch die Arbeitszeit. Aber vieles andere stimmt immer noch nicht oder nicht mehr. Menschen wollen es bei der Arbeit nicht nur warm haben und Geld heimtragen, sondern auch Spaß haben und sich einbringen. Dazu sind viele Projekte nicht angetan. Leider.

So mancher Chef schaut – aus welchem Grund auch immer – nur darauf, dass möglichst schnell irgendwie der Kunde befriedigt wird. Das ist kurzfristiges Denken, bei dem Kreativität und Motivation und Qualität über kurz oder lang auf der Strecke bleiben.

Deshalb rate ich, hier sehr sensibel zu sein. Fortbildung ist nicht nur Sache des Mitarbeiters. Innere Softwarequalität ergibt sich nicht von selbst. Motivation ist nicht egal. Wo Projekte darauf keinen Wert legen, ist daher Gefahr im Verzug. Gefahr der baldigen Unzufriedenheit, weil die technische Schuldenlast den Spaß an der Arbeit vergällt. Wer im Brownfield-Morast steckt und auch noch unter Druck arbeitet, treibt auf den Burnout zu.

Aber nicht nur Unlust droht, sondern schlicht schlechtere Chancen auf dem Arbeitsmarkt. Wer keine Gelegenheit zur Fortbildung bekommen hat und nach zehn Stunden am Arbeitsplatz nicht mehr selbst die Energie aufbringen konnte, der fällt zurück. In fünf Jahren hat er den Anschluss verpasst. Heute zum Beispiel noch Visual Basic 6.0-Projekte zu warten, ohne aktiv an .NET-Projekten zu arbeiten, ist unverantwortlich, würde ich sagen. Da wird nicht nur die Visual Basic 6.0-Altlast fortgesetzt, sondern auch eine Entwickleraltlast produziert.

Letztlich ist das jedoch eine Entscheidung, die jeder Entwickler selbst treffen muss. Welche Arbeitsbedingungen will ich zu welchem Preis aushalten? Also: Augen offen halten. Was tut sich in der Softwarewelt? Wenn die Differenz zur eigenen Welt zu groß wird – das kann schnell geschehen –, dann handeln. Insofern sollten Softwareentwickler auch einiges an Veränderungsfreude mitbringen.

Review von Cloud Computing mit der Windows Azure Platform

Dienstag, 5. Januar 2010, 14:51 Uhr
Permalink | Kommentare (3) | Kommentare als RSSRSS

Nachdem ich vor knapp zwei Wochen einen Review über das Buch Pragmatic Unit Testing veröffentlicht habe, begann ich mit der Lektüre des nächsten Buchs: Cloud Computing mit der Windows Azure Platform von Holger Sirtl.

Der Untertitel verspricht Informationen zu der Entwicklung, der Integration und dem Betrieb cloud-basierter Anwendungen – was dann jedoch auf den ersten 75 Seiten mehr als ausreichend beschrieben wird, sind die allgemeinen Vor- und Nachteile von Clouds im Allgemeinen und von Windows Azure im Speziellen.

Obwohl dies prinzipiell nicht verkehrt ist, weist es die Tendenz für den weiteren Verlauf des Buchs: Der Inhalt, der auf rund 350 Seiten vermittelt wird, würde problemlos auf 200 Seiten passen, würden die ständigen Wiederholungen entfallen. Ungewollt beschleicht einen immer wieder das Gefühl, bestimmte Formulierungen schon einmal gelesen zu haben.

Sobald das Buch zu seinem fachlichen Teil kommt, steigt die Qualität des Inhalts deutlich an: Alle wichtigen Konzepte von Windows Azure werden erläutert und mit Beispielen demonstriert:

  • Web Role und Worker Role
  • Blobs, Tables und Queues
  • Live Services
  • .NET Service Bus
  • .NET Access Control
  • Deployment

Allerdings lässt das Buch auch hierbei einen kompakten Schreibstil vermissen und besteht zum Großteil aus den immer gleichen Formulierungen.

Vermisst habe ich bei dieser Ausführlichkeit einige grundlegende Erklärungen, speziell das Kapitel zu den Live Services erläutert zahlreiche Begriffe nur äußerst knapp und verwendet diese danach wie selbstverständlich – für jemanden, der noch nie mit Windows Live entwickelt hat, gestaltet sich dieses Kapitel dadurch verhältnismäßig schwierig.

Abgerundet werden diese Themen durch einige Beispiele für den Software plus Services-Ansatz, vom Desktopclient über Web- bis hin zu mobilen Anwendungen ist alles dabei, was für einen Entwickler interessant sein könnte. Auch das Thema Interoperabilität mit Java, PHP und Ruby wird angesprochen.

Insgesamt erhält man einen guten Überblick zu Windows Azure, dem es allerdings auf der einen Seite teilweise an Tiefe fehlt, und der auf der anderen zu sehr in die Länge gezogen ist. Sofern man sich damit arrangieren kann, ist das Buch kein schlechter Einstieg in Windows Azure – wer ein rundum empfehlenswertes Buch erwartet, sollte Abstand nehmen.

this oder kein this

Freitag, 1. Januar 2010, 09:37 Uhr
Permalink | Kommentare (2) | Kommentare als RSSRSS

Am 13. Oktober 2008 haben Peter Bucher und ich unter dem Titel Noch Fragen, Bucher? Ja, Roden! angekündigt, jeweils zum ersten eines jeden Monats einen Kommentar zu einem vorab gemeinsam gewählten Thema verfassen zu wollen. Bisher sind in dieser Reihe folgende Kommentare erschienen:

Heute, am 1. Januar 2010, ist es nun wieder so weit, und unser Thema für diesen Monat lautet:

this oder kein this

So wohl Peter wie auch ich haben uns unabhängig voneinander im Vorfeld unsere Gedanken gemacht, wie wir diesem Thema gegenüberstehen. Peters Kommentar findet sich zeitgleich in seinem Blog, folgend nun mein Kommentar zu diesem Thema:

Zumeist sind Schlüsselwörter innerhalb einer Programmiersprache mit einer eindeutigen Semantik belegt; auch C# stellt keine Ausnahme dieser Regel dar. Jedoch gilt dies zumindest in C# wohlgemerkt nicht für alle Schlüsselwörter, denn einige haben – je nach Kontext – verschiedene Bedeutungen.

Ein bekanntes und weit verbreitetes Beispiel hierfür ist das Schlüsselwort using, das so wohl als Direktive wie auch als Anweisung verwendet werden kann:

  • Als Direktive dient es zunächst dazu, andere Namensräume bekannt zu machen, so dass die darin enthaltenen Typen ohne Angabe ihres vollqualifizierten Namens genutzt werden können.
  • Die Direktive dient zusätzlich jedoch auch der Bildung von Aliasnamen, wobei dies wiederum so wohl für Namensräume wie auch für einzelne Typen möglich ist.
  • Als Anweisung schließlich definiert using in Verbindung mit der IDisposable-Schnittstelle einen Gültigkeitsbereich, an dessen Ende automatisch die Dispose-Methode des gekapselten Objekts aufgerufen wird.

Doch nicht nur using ist mit verschiedenen Bedeutungen belegt – ein weiterer Kandidat mit zahlreichen Varianten ist das this-Schlüsselwort:

  • In Verbindung mit Konstruktoren dient das this-Schlüsselwort dazu, den Aufruf an einen überladenen Konstruktor der gleichen Klasse weiterzuleiten.
  • Mit this ist es zudem möglich, Indexer zu definieren – also Eigenschaften, die über keinen eigenen Namen verfügen, allerdings parametrisiert mit einem Index aufgerufen werden können.
  • Seit C# 3.0 dient this als Kennzeichner für Erweiterungsmethoden, indem mit Hilfe dieses Schlüsselworts festgelegt wird, welches Argument dem aufrufenden Objekt entspricht.
  • Schließlich dient this – wie bereits in C++ und Java – auch als Referenz auf das eigene Objekt. Auf diese Art kann auf Elemente der Klasse zugegriffen werden, deren Namen durch gleichnamige Parameter ansonsten ausgeblendet und damit nicht zugreifbar wären.

Im Gegensatz zu using, dessen Angabe immer erforderlich ist, kann this gegebenenfalls entfallen: Während seine Verwendung bei der Verkettung von Konstruktoren, Indexern und Erweiterungsmethoden obligatorisch ist, kann die Eigenreferenz entfallen – sofern der Name des betroffenen Elements nicht ausgeblendet wird.

Die Frage lautet allerdings, ob es sinnvoll ist, this in den optionalen Fällen zu streichen. Zunächst scheint es so, schließlich erspart man sich einige Zeichen zu tippen, zu lesen und vermeidet unnötige Redundanz. Auch ReSharper empfiehlt bei Verwendung der Standardeinstellungen, redundante this-Schlüsselwörter zu entfernen.

Neben diesen Vorteilen birgt das Entfernen von this jedoch auch einen essenziellen Nachteil: Es ist nicht mehr auf einen Blick ersichtlich, ob ein Zugriff auf ein Element des aktuellen Objekts stattfindet. So ist bei der Zeile

_foo = new Foo();

nicht klar, ob es sich um eine statisches Feld oder ein Instanzfeld handelt. Wird das Schlüsselwort this jedoch konsequent verwendet, ist auf den ersten Blick eindeutig, dass es sich um ein statisches Feld handelt, ansonsten müsste die Zeile nämlich

this._foo = new Foo();

lauten. Während diese Mehrdeutigkeit bei Feldern noch zu vertreten sein mag, wird es bei Eigenschaften bedeutend schwieriger: So bestehen für die Zeile

Foo.Bar();

bereits drei Möglichkeiten, welcher Aufruf sich dahinter verbirgt: Zum einen könnte Foo eine Eigenschaft sein, an der eine Methode namens Bar aufgerufen wird. Es ist jedoch nicht eindeutig, ob es sich bei der Eigenschaft um eine statische oder eine instanzbehaftete Eigenschaft handelt.

Neben diesen zwei Möglichkeiten könnte es zudem sein, dass Foo gar keine Eigenschaft, sondern eine statische Klasse bezeichnet, die ihrerseits wiederum eine Methode Bar() enthält.

Der Unterschied zwischen einer statischen Eigenschaft und einer statischen Klasse lässt sich ohne weiteres nicht auflösen – zumindest der erste Fall kann aber durch Verwendung von this explizit gemacht werden. Bei der Zeile

this.Foo.Bar();

ist nämlich auf den ersten Blick ersichtlich, dass eine Methode an einer Eigenschaft aufgerufen wird, die instanzbehaftet ist.

Diese Beispiele zeigen, dass die konsequente Verwendung von this durchaus ihren Teil zu einer besseren Verständlichkeit des Quellcodes beitragen kann.

Da Code in der Regel derart geschrieben wird, dass er für die Zukunft wie auch für andere Entwickler gut lesbar ist, kann es durchaus eine vernünftige Entscheidung sein, this generell zu verwenden – insbesondere auch in den redundanten Fällen, um die Semantik des Codes explizit zu machen.

Für welche Variante auch immer ein Entwickler beziehungsweise ein Team sich entscheidet, wichtig ist – wie so oft, wenn es um das Thema Coderichtlinien geht – dass die einmal getroffene Entscheidung konsequent eingehalten wird. Alles andere führt über kurz oder lang zu Missverständnissen.

LightCore

Freitag, 1. Januar 2010, 00:00 Uhr
Permalink | Kommentare (1) | Kommentare als RSSRSS

Vor ungefähr neun Monaten habe ich in meinem Blogeintrag Microkernel im Eigenbau beschrieben, wie mit wenigen Zeilen ein eigener Microkernel unter .NET realisiert werden kann. Auch wenn diese Variante durchaus für einfache Szenarien genügt, bestehen in der Praxis häufig weitere Anforderungen.

Da in der Regel kein eigener Microkernel entwickelt werden soll, bleibt die Wahl der Qual, welcher Microkernel zum einen die eigenen Anforderungen erfüllt und zum anderen aber zugleich dem persönlichen Gusto am ehesten entspricht. Erschwert wird die Wahl dabei durch die Vielzahl der verfügbaren Systeme.

Wie viele andere Entwickler konnte auch ich mich in der Vergangenheit nicht eindeutig für ein einziges System entscheiden:

  • So hat mir autofac zwar mit seinem an C# 3.0 angelehnten Programmiermodell mit umfangreicher Nutzung von Lambdaausdrücken zugesagt, nicht jedoch von der Performance.
  • Unity hingegen gefällt mir ebenfalls von dem verwendeten Programmiermodell, jedoch habe ich mit den Microsoft Application Blocks in der Vergangenheit keine all zu guten Erfahrungen gemacht, weshalb ich bei Unity sehr skeptisch bin.
  • Spring.NET ist als Framework empfehlenswert, wenn nicht nur ein Microkernel, sondern auch Logging, O/R-Mapping, aspektorientierte Funktionen und ähnliches gewünscht werden – für alles andere ist es jedoch zu umfangreich und komplex.

Diese Liste könnte ich noch problemlos fortsetzen und um einige weitere Microkernel ergänzen.

Mit LightCore hat Peter Bucher nun einen weiteren Microkernel entwickelt, der zudem als Dependency Injection-Container dient. LightCore ist vollständig in C# geschrieben, folgt dabei den Richtlinien der Clean Code Developer-Initiative und ist weitestgehend mit Unittests abgedeckt.

Für sich genommen wecken diese Aspekte durchaus Interesse an dem zu Grunde liegenden Code – doch wirklich interessant wird LightCore durch seine Eigenschaften beziehungsweise Fähigkeiten, die LightCore von anderen Microkerneln abheben:

  • LightCore ist leichtgewichtig und besteht im Wesentlichen aus einer 27 KByte großen Assembly. Je nach Anforderungen kommen noch einige Assemblies hinzu, doch über 50 KByte wächst der Platzbedarf in keinem Fall.
  • LightCore ist verdammt schnell: Im Vergleich zu nativem .NET-Code ist die Erzeugung von 100.000 Objektinstanzen in LightCore lediglich um 7% langsamer – autofac bedarf dafür hingegen ein Vielfaches der Zeit.
  • LightCore ist einfach und flexibel zu konfigurieren: Zum einen kann die Konfiguration vollständig im Code erfolgen, zum anderen wird XAML als Konfigurationssprache unterstützt, wobei nahezu beliebige Datenquellen genutzt werden können.
  • LightCore unterstützt die Instanziierung von Objekten nicht nur per Reflection, sondern auch per Lambdaausdruck, wodurch die Performance im Vergleich zu der Reflection-basierten Variante deutlich zunimmt.
  • LightCore kann mit verschiedenen Lebenszyklen von Objekten umgehen: Transiente Objekte können dadurch ebenso erzeugt werden die Singletons, threadaffine Singletons und HttpRequest-bezogene Objekte.
  • LightCore ermöglicht die Registrierung von Typen an Hand eines Kontrakts, eines Namens oder einer Klasse. Zusätzlich können Argumente spezifziert werden, die während der Instanziierung an den jeweiligen Konstruktor übergeben werden.
  • LightCore unterstützt die Gruppierung von Registrierungen, so dass auf einfache Art zwischen verschiedenen Konfigurationen von Registrierungen gewechselt werden kann.
  • LightCore integriert sich in klassisches ASP.NET und ASP.NET MVC, so dass Dependency Injection auch in diesen Technologien ohne zusätzlichen Aufwand genutzt werden kann.
  • LightCore unterstützt das CommonServiceLocator-Projekt, das seinerseits eine Abstraktion über verschiedene Microkernel ermöglicht.

Dieser umfangreichen und bemerkenswerten Featureliste zum Trotz verfügt LightCore über ein ausgesprochen schlichtes API, so dass zur tatsächlichen Verwendung nur einige wenige Zeilen Code erforderlich sind.

Alles in allem ist LightCore also eine kompakte, performante, flexible und ausgereifte Komponente, die für meine Projekte zukünftig die Antwort auf die Frage nach einem geeigneten Microkernel darstellt.

Für die Zukunft wünsche ich LightCore daher alles Gute.

Review von Pragmatic Unit Testing

Samstag, 26. Dezember 2009, 12:26 Uhr
Permalink | Kommentare (1) | Kommentare als RSSRSS

Knapp mehr als drei Monate sind seit meinem letzten Review vergangen, in dem ich das Buch Painless Project Management with FogBugz besprochen habe. Viel ist seither geschehen – insbesondere habe ich die Interviewreihe .NET Professionals im Profil begonnen, für die inzwischen auch eine dedizierte Webseite besteht, auf der sämtliche Interviews verfügbar sind.

Am 1. November 2009 haben Peter Bucher und ich uns dann in unserem monatlichen Streitgespräch die Frage gestellt: Wie viel Sinn machen Unittests? Als Reaktion auf meinen Beitrag gab es zahlreiche Kommentare, wodurch ich mich bewogen sah, das Thema noch einmal zu überdenken.

Inzwischen stehe ich Unittests gänzlich anders gegenüber – meine Erfahrungen habe ich in den Blogeinträgen Auch Kirchen haben Kragsteine und Ein Ordnungssystem für Unittests beschrieben. Doch das war nur der öffentliche, nach außen sichtbare Teil meiner Beschäftigung mit Unittests.

Auf Empfehlung von David Tielke habe ich mich mit dem Buch Pragmatic Unit Testing von Andrew Hunt und David Thomas befasst.

Nachdem mich das Buch The Art of Unit Testing von Roy Osherove sehr enttäuscht hatte, war ich auf Davids Tipp mehr als gespannt. Um es kurz zu machen: Pragmatic Unit Testing ist wirklich empfehlenswert: Kompakt, direkt, pragmatisch und dennoch durchdacht erklärt es auf rund 190 Seiten nicht nur das Handwerkszeug, sondern auch – und das finde ich besonders wertvoll – zahlreiche Best Practices.

So wird zwar in den ersten drei Kapiteln darauf eingegangen, wie NUnit an und für sich funktioniert – danach ist dieses Thema jedoch abgehandelt und es geht in den folgenden sieben Kapiteln um die eigentlich relevanten Aspekte des Unittestings:

  • Welche Aspekte von Code erfordern besonderes Augenmerk beim Testen?
  • Welche Grenzwerte müssen gesondert beachtet werden?
  • Wie werden Stubs und Mocks eingesetzt?
  • Was zeichnet gute Tests aus?
  • Was muss beim Schreiben von Tests im Hinblick auf Teamentwicklung beachtet werden?
  • Wie wird Legacycode sinnvoll getestet?
  • Welche Rolle spielen Architektur und Refactoring für die Entwicklung von Tests?
  • Wie können UIs getestet werden?

All diese Themen sind ausgesprochen wichtig und werden kompakt, aber dennoch gut verständlich erläutert. Ein Anhang, der auf typische Stolperfallen und deren Vermeidung hinweist, rundet die zehn vorangegangenen Kapitel ab.

Alles in allem ist Pragmatic Unit Testing ohne Einschränkung empfehlenswert und so wohl für Einsteiger wie auch für Fortgeschrittene gleichermaßen geeignet. Wer sich also für den Einsatz von Unittests interessiert und noch auf der Suche nach einer geeigneten Lektüre ist, dem sei dieses Buch ans Herz gelegt.

.NET Professionals im Profil: herbivore

Dienstag, 15. Dezember 2009, 09:37 Uhr
Permalink | Kommentare (2) | Kommentare als RSSRSS

herbivore arbeitet als freiberuflicher Informatiker und ist Administrator von myCSharp.de. Nach ersten Schritten auf programmierbaren Taschenrechnern bekam er über das Informatikstudium Zugang zur strukturierten Programmierung. Inzwischen entwickelt er schwerpunktmäßig mit C++ und C#. Sie erreichen ihn über myCSharp.de.

Golo Roden: herbivore [tatsächlicher Name ist der Redaktion bekannt], wie bist Du zur Softwareentwicklung gekommen? Wie und wann hast Du angefangen?

herbivore: Bei mir hat alles mit einem programmierbaren Taschenrechner angefangen. Andere für den Privathaushalt erschwingliche Computer gab es zu diesem Zeitpunkt noch nicht. Ich hatte mir den Taschenrechner aber gar nicht gewünscht, weil man ihn programmieren konnte, sondern weil er zehn Speicherregister hatte. Meine Berechnungen damals hatten immer viele Nebenrechnungen, und ich kam mit dem einen Speicherregister meines alten Taschenrechners nicht mehr hin.

Der neue Taschenrechner war eine Offenbarung für mich. Ich stellte dann schnell fest, dass er 49 Programmschritte speichern konnte. Allerdings gingen diese nach dem Ausschalten verloren, so dass die Programme deshalb jedes Mal neu eingegeben werden mussten. Eine andere Speichermöglichkeit als einen Stift und ein Blatt Papier gab es nicht. Jedenfalls war die erste Programmiersprache, die ich lernte, die Programmiersprache dieses Taschenrechners.

Mein erster „echter“ Rechner – nur ein oder zwei Jahre später – hatte 32KB Hauptspeicher und man konnte einen handelsüblichen Kassettenrekorder als Hintergrundspeicher anschließen. 32KB Hauptspeicher waren damals unglaublich viel. Das Basismodell wurde mit 8KB Speicher ausgeliefert. Eine ausführliche Beschreibung des Hardware-Aspekts meiner ersten Schritte findet sich unter Eure ersten Rechner / Schritte mit Rechnern.

Auf diesem Rechner konnte man mit einem sehr einfachen Basic programmieren. Das habe ich mir selbst mittels des beigelegten Handbuchs beigebracht. Im Nachhinein bin ich glücklich, dass sich der dadurch verursachte Schaden in Grenzen gehalten hat – denn strukturierte Programmierung war das nicht. Ich wusste zu diesem Zeitpunkt aber noch nicht einmal, dass es so etwas überhaupt gibt.

Das lernte ich erst im Informatikstudium, das ich zwei Jahre später begonnen habe. Wenn man so will, war das Studium für mich der eigentliche Beginn dessen, was ich als Softwareentwicklung bezeichnen würde. Für mich standen ab dieser Zeit gute und saubere Lösungen im Vordergrund. Dass ein Programm einfach nur das machte, was es sollte, war mir nicht mehr genug.

Golo Roden: Du bist bei myCSharp.de der mit Abstand aktivste Benutzer, und zugleich jemand, der unglaublich kompetent ist. Wie bist Du zu diesem breitgefächerten Wissen und zu myCSharp.de im Speziellen gekommen?

herbivore: Mit dem Studium habe ich mein Hobby zum Beruf gemacht. Und jeder weiß, wieviel Energie man in eine Sache stecken kann, die einen wirklich interessiert und einem wirklich Spaß macht. Darum habe ich dankbar alle Möglichkeiten angenommen, mein Wissen zu erweitern. Mich haben viele unterschiedliche Themen interessiert, also habe ich mich auch mit sehr vielen verschiedenen Themen beschäftigt.

Das Lernen war bei mir immer ein Dreiklang aus Aufnehmen, Ausprobieren und Weitergeben. Natürlich muss man zu einem Thema erst einmal etwas lesen oder hören, um überhaupt eine Basis zu haben. Aber das allein genügt nicht – man muss das Gelernte auch ausprobieren und anwenden. Ich habe in meinem Leben bestimmt schon einige tausend Mini-Testprogramme geschrieben, um irgendwelche Zusammenhänge untersuchen zu können. Und zu guter Letzt trägt es zur Vertiefung und Verbreiterung des Wissen entscheidend bei, das Gelernte anderen zu erklären.

Um Wissen weiterzugeben, muss man es so formulieren, dass andere es verstehen. Dabei merkt man dann auch schnell, wenn einem selbst etwas noch nicht ganz klar ist, und man kann die Lücke schließen. Außerdem profitiert man von den Nachfragen, die andere stellen, weil man dadurch auf neue Aspekte aufmerksam wird.

Das ist auch der Grund, warum ich auf myCSharp.de lieber Fragen beantworte als Fragen zu stellen. Man lernt einfach mehr dadurch.

Dennoch bin ich ganz profan durch eine eigene Frage zu myCSharp.de gekommen, auf die ich eine gute Antwort gesucht und bekommen habe. Das hat mich motiviert, mich zu revanchieren, und auch ein paar Fragen zu beantworten. Auf myCSharp.de habe ich in Was bewegt euch zum Helfen im Forum? beschrieben, was mich zum Helfen motiviert.

Dabei war es inbesondere zu Anfang so, dass ich viele Antworten, die ich gegeben habe, selbst nicht kannte, bevor ich mich mit der Frage beschäftigt hatte. Hier kommen dann wieder die Mini-Testprogramme, aber auch das Stöbern und Nachschlagen in der Dokumentation und eigenes Nachdenken über die Frage ins Spiel.

Golo Roden: Ein wesentliches Merkmal der IT ist, dass man beständig mit neuen Entwicklungen konfrontiert wird, und diesen folgen muss. Woher nimmst Du die Motivation, Dich quasi jeden Tag weiterzubilden und mit Neuem zu beschäftigen?

herbivore: Die Motivation kommt aus der Einsicht in die Notwendigkeit. Wenn man nichts Neues lernt, fällt man zurück. myCSharp.de ist mein Weg, in dieser Hinsicht auf dem Laufenden zu bleiben. myCSharp.de macht mir zum Glück nach all der Zeit immer noch Spaß und ich bin täglich dort aktiv. Es ist ja nicht so wichtig zu wissen, dass es eine neue Entwicklung gibt, denn es gibt viele neue Entwicklungen und die meisten verschwinden scheller als sie gekommen sind – wenn aber wirklich etwas beginnt, sich durchzusetzen, häufen sich auf myCSharp.de die Fragen dazu. Dann weiß ich, dass es Zeit ist, mir dieses Thema genauer anzuschauen.

Die kurze Halbwertszeit des Wissens sollte es übrigens jedem leicht machen, sein Wissen mit anderen zu teilen. Ich hatte nie die Befürchtung, dass ich meinen Wissensvorsprung dadurch verlieren könnte, dass ich mein Wissen mit anderen teile, weil ich genau wusste, dass immer wieder neues Wissen dazu kommt. Und das hat sich auch in der ganzen Zeit, in der ich mich mit Informatik beschäftige, bewahrheitet. Man sollte also nicht auf seinem Wissen hocken, bis es wertlos geworden ist, sondern sein Wissen vorher weitergeben.

Golo Roden: Wenn sich ein Anfänger heute mit dem Thema Softwareentwicklung befassen will - welche Voraussetzungen sollte er Deiner Meinung nach dafür mitbringen, und was siehst Du als No-Go an?

herbivore: Ein Anfänger sollte Eigeninitiative und Experimentierfreude mitbringen. Konkretes Wissen ist weniger wichtig. Man braucht eher die Fähigkeit, sich Wissen zu erwerben. Man sollte sich nicht scheuen, Bücher gründlich durchzuarbeiten. Durchlesen alleine hilft nicht. Auch und gerade wenn es in dem Buch keine vorgegebenen Arbeitsaufgaben gibt, sollte man versuchen, das Gelesene sofort umzusetzen und sei es in Form der schon genannten Mini-Testprogramme. Und das auch nicht erst am Ende des Kapitels, sondern möglichst Seite für Seite.

Natürlich kann man durch Ausprobieren nicht alles erschlagen. Gerade bei Architekturfragen zählen abstraktes Denken und vor allem Erfahrung, die man sich natürlich erst nach und nach erwerben kann.

Golo Roden: Bei der Vielzahl an Technologien, die es heute gibt: Womit sollte ein Anfänger heutzutage anzufangen?

herbivore: Man sollte nicht gleich zu hoch hinaus wollen und sich nicht zu schade sein, ganz zu Anfang auch wirklich einfache Programme zu schreiben. Lieber in kleinen Schritten alles gründlich verstehen, als zu versuchen, durch unreflektiertes Zusammenkopieren von Code ein möglichst eindrucksvolles Programm zu Stande zu bringen. Insofern sind einfache Kommandozeilenprogramme für mich auch heute noch das Mittel der Wahl für den Einstieg. Allerdings darf man dabei nicht zu sehr in die imperative Programmierung verfallen.

Es ist wichtig, sich von Anfang an mit der Objektorientierung zu beschäftigen. Das bedeutet unter anderem, den Code an Hand von Klassen und nicht an Hand von Funktionen zu strukturieren. Funktionen in dem Sinne gibt es gar nicht mehr. Bei aller Ähnlichkeit zu einem Funktionsaufruf ist ein Methodenaufruf konzeptuell etwas ganz anderes, nämlich das Senden einer Nachricht an ein Objekt. Die Implementierung einer Methode ist dementsprechend die Vorschrift, wie ein Objekt auf eine solche Nachricht reagiert.

Im Prinzip ist der Begriff „objektorientiertes Programm“ ein Widerspruch in sich. Eigentlich gibt es in einer objektorientierten Anwendung nur eine Menge von Objekten, die miteinander kommunizieren. Der Anstoß, was die Objekte machen, kommt nicht mehr von einem fest vorgegebenen Programm, sondern aus den Nachrichten, die der Benutzer durch seine Eingaben an die Objekte schickt. Das nennt sich dann ereignisgesteuerte Programmierung und ergänzt die objektorientierte Programmierung ideal.

Wenn man Interesse, Spaß, Ausdauer und Beharrlichkeit mitbringt, wüsste ich keinen Grund, warum man keinen Erfolg in der Software-Entwicklung haben sollte. Ich persönlich finde das Vorhandensein eines mathematischem Hintergrunds hilfreich, aber es gibt auch viele, die ohne diesen gute Informatiker geworden sind.

Dependency Injection ist keine Silberkugel

Montag, 7. Dezember 2009, 07:01 Uhr
Permalink | Kommentare (3) | Kommentare als RSSRSS

Das Inversion of Control-Paradigma folgt in der Regel einer von zwei Varianten: Entweder wird ein dedizierter Service Locator in Form eines Microkernels verwendet, oder es wird auf ein geeignetes Dependency Injection-Framework samt entsprechendem Container zurückgegriffen.

Der wesentliche Unterschied zwischen diesen Varianten besteht in unterschiedlichen Graden der Explikation beziehungsweise Implikation, und in der Abhängigkeit von der Infrastruktur:

  • Während der Service Locator eine generische Factory darstellt und explizit beauftragt werden muss, eine Instanz zu einem gegebenen Kontrakt zu erzeugen, geschieht dies beim Einsatz eines Dependency Injection-Containers implizit.
  • Da der Aufruf des Service Locators explizit geschieht, bedeutet dies in Konsequenz, dass eine Referenz auf den Service Locator vorhanden sein muss – diese Referenz entfällt beim Einsatz eines Dependency Injection-Containers.

Aus diesen grundlegenden Unterschieden ergeben sich einige spezifische Vor- und Nachteile, interessant ist jedoch, dass der Service Locator in der Regel von Einsteigern, denen das Inversion of Control-Paradigma noch nicht vertraut ist, bevorzugt wird. Die Gründe hierfür liegen auf der Hand: Der explizite Aufruf einer Factory zur Erzeugung einer Instanz ist näher am klassischen Aufruf von new.

Je ausgiebiger sich ein Entwickler danach mit Inversion of Control auseinandersetzt, desto eher lernt er die Vorzüge von Dependency Injection schätzen. Dazu zählen unter anderem:

  • Es ist keine Referenz auf einen Service Locator oder ein ähnliches Konstrukt notwendig – der Dependency Injection-Container bleibt verborgen, so dass die Abhängigkeit von externen Komponenten vermindert wird.
  • Da die einzelnen Abhängigkeiten von außen über den Konstruktor oder entsprechende Eigenschaften aufgelöst werden können, ist es ein Leichtes, innerhalb eines Unittests passende Mockobjekte in eine Komponente hineinzureichen. Darüber hinaus kann in Unittests gänzlich auf den Dependency Injection-Container verzichtet werden, was den Aufwand zur Bereitstellung einer passenden Infrastruktur deutlich senkt.
  • Da die gesamte Verdrahtung der Anwendung implizit geschieht, sinkt der Aufwand für den einzelnen Entwickler deutlich.

Vor allem auf Basis dieser Gründe erscheint Dependency Injection dann häufig als die besser durchdachte Alternative zu einem Service Locator, so dass man als Entwickler versucht ist, sämtliche Abhängigkeiten mit Hilfe von Dependency Injection aufzulösen.

Doch Dependency Injection ist keine Silberkugel. Anders als häufig behauptet, verfügt Dependency Injection nämlich auch über einige Nachteile:

  • Zum einen ist es mit Dependency Injection nicht möglich, lokale Variablen zu instanziieren: Zugriff besteht – entweder über den Konstruktor oder über passende Eigenschaften – nur auf Felder. Der vermeintliche Ausweg, jede lokale Variable in ein Feld zu überführen, erweist sich als Irrweg: Schließlich weisen lokale Variablen und Felder eine unterschiedliche Semantik auf und sind nicht per se gegeneinander austauschbar.
  • Zum anderen ist die dynamische Erzeugung von Instanzen per Dependency Injection nicht möglich: Der Lebenszyklus einer injizierten Komponente ist weitestgehend an den der enthaltenden Komponente gebunden. Für dynamische Instanziierung – beispielsweise in Abhängigkeit von anderem Code – eignet sich Dependency Injection somit nicht.

Das heißt, dass immer dann, wenn lokale Variablen gefüllt oder mehrfach vorhandene Abhängigkeiten dynamisch aufgelöst werden sollen, Dependency Injection an ihre Grenzen stößt: In diesem Fall bleibt nichts anderes, als auf einen Service Locator oder ein ähnliches Konstrukt zu setzen.

Dies bedeutet jedoch, dass Dependency Injection nicht alle Probleme auf einen Schlag löst, ebenso wenig wie ein Service Locator dies macht. Vielmehr liegt die ideale Lösung darin, beide Ansätze miteinander zu vereinen, um das Beste aus beiden Welten nutzen zu können.

Kurzum: Dependency Injection ist kein Allheilmittel. Die Nutzung empfiehlt sich immer dann, wenn genau eine einzige Komponente verwendet werden soll, deren Lebenszyklus dem des enthaltenden Objekts gleicht. Für alle anderen Fälle eignet sich ein Service Locator besser.

Die beiden Konzepte konkurrieren also nicht exklusiv miteinander, sondern ergänzen sich gegenseitig: Dies kann sogar so weit gehen, dass der Service Locator mit Hilfe von Dependency Injection in die entsprechenden Komponenten injiziert wird, um die sonst vorhandene Abhängigkeit zu vermeiden.

Reflection – Fluch oder Segen?

Dienstag, 1. Dezember 2009, 09:37 Uhr
Permalink | Kommentare (1) | Kommentare als RSSRSS

Am 13. Oktober 2008 haben Peter Bucher und ich unter dem Titel Noch Fragen, Bucher? Ja, Roden! angekündigt, jeweils zum ersten eines jeden Monats einen Kommentar zu einem vorab gemeinsam gewählten Thema verfassen zu wollen. Bisher sind in dieser Reihe folgende Kommentare erschienen:

Heute, am 1. Dezember 2009, ist es nun wieder so weit, und unser Thema für diesen Monat lautet:

Reflection – Fluch oder Segen?

So wohl Peter wie auch ich haben uns unabhängig voneinander im Vorfeld unsere Gedanken gemacht, wie wir diesem Thema gegenüberstehen. Peters Kommentar findet sich zeitgleich in seinem Blog, folgend nun mein Kommentar zu diesem Thema:

Reflection ist ein zentrales Element in .NET: Die Tatsache, dass in MSIL eben nicht nur der eigentliche Code, sondern auch die dazugehörigen Metadaten enthalten sind, zeigt dies. Und – das ist auch gut so.

Denn Reflection bildet die Grundlage für zahlreiche Szenarien, die von vielen Entwicklern tagtäglich genutzt werden: Sei es der Einsatz eines Microkernels und damit verbunden das dynamische Laden und späte Instanziieren von Typen, sei es der Einsatz einer dynamischen Sprache oder der dynamischen Sprachfeatures von C# 4.0. All dies basiert letztlich auf Reflection.

Auch die Verwendung von Attributen zur Laufzeit wäre ohne Reflection nicht möglich, ebensowenig wie die Analyse von Assemblies, um an Hand der enthaltenen Typen und deren Methoden, Eigenschaften und Feldern gewisse Entscheidungen zu treffen.

Reflection ist also fraglos ein Segen – ohne sie wären all die genannten Punkte in .NET nicht oder zumindest nicht mit dermaßen geringem Aufwand möglich. Doch woher stammt dann der schlechte Ruf, der in Gesprächen über Reflection zugegebenermaßen häufig den Unterton bestimmt?

Prinzipiell sind gleich zwei Gründe für den schlechten Ruf von Reflection verantwortlich, wobei einer der beiden systemimmanent ist, der zweite jedoch zumindest teilweise nur die konkrete Implementierung in .NET betrifft:

  • Reflection ermöglicht den wahlfreien Zugriff auf Code, auch auf geschützte Elemente wie beispielsweise Variablen, die als private gekennzeichnet wurden.
  • Reflection ist langsam – so wohl die Analyse von Code wie auch dessen Ausführung betreffend.

Dass Reflection den wahlfreien Zugriff auf beliebigen Code ermöglicht, ist Fluch und Segen zugleich: Auf der einen Seite wird auf diese Art sämtliche objektorientierte Programmierung ausgehebelt, auf der anderen Seite kann es ungemein nützlich sein, von außen auch auf private Elemente zugreifen zu können – man denke nur an diverse Unittests.

Nebenbei bemerkt: Einen interessanten Ansatz, wie Unittests ohne den Einsatz von Reflection auskommen und dennoch Interna testen können, hat Ralf Westphal in seinem Blogeintrag Zustand als Abhängigkeit beschrieben.

Generell gilt für den Einsatz von Reflection zum Zugriff auf geschützte Elemente also die gängige Empfehlung: So viel wie nötig und so wenig wie möglich – mit Betonung auf zweiterem.

Doch all dies wohnt Reflection bereits vom Ansatz her inne: Dabei spielt es keine Rolle, ob es sich um Reflection auf Basis von .NET, Java oder einer beliebigen anderen Plattform handelt: Diese Nachteile und die damit einhergehenden Überlegungen gelten generell.

Mit dem Umstand, dass Reflection unter .NET ausgesprochen langsam ist, sieht es jedoch ein wenig anders aus: Reflection an sich ist immer langsamer als statisch kompilierter Code – das ist logisch, wenn man weiß, wie beispielsweise Aufrufe von Funktionen in beiden Fällen funktionieren: Der Lookup per Reflection kostet schlicht und ergreifend mehr Zeit.

Doch Reflection kann auch dazu genutzt werden, um Code zu analyiseren – und hier ist es tatsächlich die Implementierung von .NET, welche die Schuld dafür trägt. Zudem zeichnet sich die Reflection von .NET in diesem Zusammenhang auch dadurch aus, wenig flexibel zu sein.

So ist es beispielsweise nicht möglich, aus einer auf dem Desktop ausgeführten .NET-Anwendung die Assembly mscorlib.dll von Silverlight zu öffnen – es kann nämlich jeweils nur eine Instanz der mscorlib.dll in einen Prozessraum geladen werden, was die Analyse einer anderen als der eigenen mscorlib.dll unter .NET immer scheitern wird.

Abhilfe – so wohl für die Geschwindigkeit wie auch für die Flexibilität – schafft der Einsatz einer anderen Komponente für Reflection, wie beispielsweise Mono Cecil, die unter anderem auch von Werkzeugen wie dem Mono Migration Analyzer oder dem Mono Debugger eingesetzt wird.

Zusammenfassend kann man also sagen, dass Reflection per se so wohl Fluch wie auch Segen ist – und dass es vom konkreten Kontext abhängt: Für Latebinding, dynamische Sprachen und Analyse von Code ist Reflection unverzichtbar, doch für den darüber hinausgehenden Einsatz von Reflection sollte man sehr gute Gründe haben.

Ein Ordnungssystem für Unittests

Sonntag, 22. November 2009, 07:06 Uhr
Permalink | Kommentare (2) | Kommentare als RSSRSS

Auf den Tag drei Wochen sind vergangen, seit Ralf Westphal mich in Reaktion auf den Blogeintrag Wie viel Sinn machen Unittests? ermuntert hat, mich nochmals intensiv mit diesem Thema auseinanderzusetzen:

Unit Tests […] konsequent und kompetent mal für einen Monat einzusetzen. Mit der Kompetenz mag es da schwierig sein, weil man sich dann eine Veränderung der Handlungs- und Denkgewohnheit selbst beibringen muss... aber das ist zumindest ein Anfang.

Ich bin seinem Rat gefolgt und habe bemerkt, dass die wesentlichen Probleme für mich nicht technischer, sondern gedanklicher Natur waren. Zu viele unbeantwortete Fragen standen im Raum – Fragen, die zunächst einfach erscheinen, deren Beantwortung aber viel Nachdenken voraussetzt.

Man könnte mein Problem als die Herausforderung bezeichnen, ein tragfähiges Konzept für Unittests zu finden, das sich nahtlos in meine bisherige Arbeitsweise integriert, sie zwar erweitert, aber nicht von Grund auf umkrempelt.

Bemerkenswert fand ich, dass die wenigsten Entwickler, die ich mit diesen Fragen konfrontiert habe, ihre Antworten fundiert begründen konnten. Einige haben sich sogar daran gestört, dass ich diese Fragen überhaupt stelle, und haben eher dazu geraten, einfach loszulegen – frei nach dem Motto: TDD ist keine Wissenschaft!

Doch ohne fundierte Antworten auf grundlegende Fragen zu haben, die den eigenen Wissensdurst stillen, verbleibt immer ein ungutes Gefühl – ob das, was man macht, tragfähig für zukünftige Erweiterungen sein wird. Diese zukünftige Tragfähigkeit bedeutet mir sehr viel – anders wäre ich vermutlich auch von Extreme Programming nicht so begeistert.

Außerdem ist die Beantwortung solcher Fragen entscheidend, um klare Regeln und Richtlinien zu haben, auf deren Basis man Entscheidungen treffen kann: Je genauer diese Regeln und Richtlinien formuliert werden, desto größer wird die persönliche Liebe zum Detail, desto besser wird die Accuracy – meines Erachtens eine essenzielle Eigenschaft eines guten Enwicklers.

Die erste dieser Fragen, ob Code zum Zwecke einer besseren Testbarkeit angepasst werden darf, wurde bereits in Auch Kirchen haben Kragsteine diskutiert: Wie so oft ist es Ralf Westphal gelungen, eine anschauliche Analogie zur realen Welt zu finden, die das digitale Problem schlagartig löst.

Die zweite dieser Fragen, wie Unittests sinnvoll und übersichtlich organisiert werden können, wurde inzwischen auch beantwortet: Auch hierzu hat Ralf Westphal einen wesentlichen Teil beigetragen, aber auch Neno Loje, Bernd Marquardt und Peter Bucher haben mein nun gefundenes System beeinflusst.

Die grundlegende Erkenntnis ist zunächst, dass sich eine Testklasse nicht zwingend auf eine zu testende Klasse beziehen muss – dass also nicht zwingend eine 1:1-Beziehung zwischen beiden vorliegt. Statt dessen bezieht sich eine Testklasse auf ein sogenanntes System under test (SUT). Ein solches SUT kann durchaus eine Klasse sein – genausogut kann es aber auch eine einzelne Methode sein.

Die zweite Erkenntnis ist, dass ein Unittest ein SUT immer in einem gegebenen Kontext testet. Bei einer Methode ist das fast immer der Aufruf derselben, bei einer Klasse hingegen kann es verschiedene Ausgangssituationen geben: Ein Kontext wäre das Initialisieren der Klasse, ein weiterer die Arbeit mit der gerade initialisierten Klasse, wieder ein weiterer das Disposen einer bereits verwendeten Klasse.

Da sich in der Regel mehrere Unittests auf einen solchen Kontext beziehen, macht es durchaus Sinn, diese in einer Testklasse zusammenzufassen, deren Name den Kontext beschreibt, und deren Namespace den Platz des SUTs angibt.

Auf diese Art könnten Unittests, die den Aufruf der Methode ToDictionary in der Klasse goloroden.de.Common.ExtensionMethods testen, beispielsweise in der Testklasse

  • goloroden.de.Tests.Common.ExtensionMethods.WhenToDictionaryIsCalled

abgelegt werden. Die einzelnen Unittests beschreiben dann mit ihrem Namen innerhalb dieser Klasse nur noch die übergebenen Parameter sowie das erwartete Ergebnis:

  • WithNull_AnArgumentNullExceptionIsThrown()
  • WithAnEmptyString_AnArgumentExceptionIsThrown()

Der Vorteil dieser Terminologie liegt klar auf der Hand: Schlägt ein Unittest fehl, lassen sich aus Testklasse und –methode auf einen Blick alle relevanten Informationen ablesen: Der Aufruf welcher Codestelle verursacht in welchem Kontext mit welchen Parametern ein Problem?

Zudem fördert diese Terminologie das Prinzip von TDD, pro Unittest nur einen einzelnen Aspekt zu testen – versucht man, mehrere Aspekte in einem Unittest zusammen zu fassen, führt dies unweigerlich zu unhandlichen Methodennamen.

Nachdem ich auf dieser Basis nun eine Reihe von Unittests geschrieben habe, bemerke ich, dass sie mir bereits sehr ans Herz gewachsen sind. Interessant fand ich vor allem, dass ich allein durch das nachträgliche Schreiben von Unittests einen Fehler in einer zehnzeiligen Methode entdeckt habe, der trotz dem häufigen Einsatz dieser Methode in den vergangenen zwölf Monaten nicht aufgefallen ist.

Allein das gute Gefühl, zukünftig Änderungen und Erweiterungen an dieser Methode durchführen zu können, ohne Angst haben zu müssen, diesen Fehler unbemerkt wieder einzubauen, war die vergangenen drei Wochen allemal wert.

Insofern kann ich – auch wenn das Schreiben von Unittests für mich noch nicht intuitiv geschieht – guten Gewissens behaupten, dass Unittests sehr wohl Sinn machen. Dies zugebenermaßen sogar mehr, als ich noch vor vier Wochen gedacht hätte.

.NET Professionals im Profil: David Tielke

Sonntag, 15. November 2009, 09:37 Uhr
Permalink | Kommentare (1) | Kommentare als RSSRSS

David Tielke lebt in Winterberg, studiert Informatik an der Universität Marburg und beschäftigt sich vorrangig mit den Themen Softwarequalität und -entwicklung. Zudem gibt er sein Wissen über .NET im Rahmen des Microsoft Student Partner-Programms an andere Studenten weiter. Sie erreichen ihn über sein Blog.

Golo Roden: David, wie bist Du zur Softwareentwicklung gekommen? Wie und wann hast Du angefangen?

David Tielke: Ich habe im Laufe meines Bachelorstudiums gemerkt, dass einerseits zu wenig aktuelle Softwaretechnikinhalte behandelt wurden, und dass auf der anderen Seite die wenigen Inhalte, die es gab, vom Niveau her derart einfach gestaltet wurden, dass auch die BWL-lastigen Studiengänge diese hören konnten.

Man hatte zwar Grundlagen in Softwaretechnik und Programmierung gehört, allerdings gelang es weder mir noch meinen Kommilitonen eine „Brücke“ zwischen den beiden Bereichen zu schlagen. Irgendwann habe ich dann gemerkt, dass dies nicht besser wurde und begonnen, das ganze Thema in meiner Freizeit aufzuarbeiten.

Zu Beginn stand die Auswahl der Programmierplattform, und nachdem ich ein bisschen über Java und .NET recherchiert hatte, fiel die Wahl sehr deutlich auf .NET und C# als Sprache.

Als ich erste Erfolge beim Programmieren verzeichnen konnte, entwickelte sich eine wahre „Sucht“ nach Themen im Bereich .NET und den verwandten Microsoft-Technologien. Da das sehr viel Zeit kostete, kündigte ich meine Assistentenstelle beim Professor und suchte mir eine Stelle als .NET-Softwareentwickler.

Diese fand ich auch sehr schnell bei der Firma uniserve in Meschede, so dass ich nun quasi mein neues Hobby zum Beruf machen, endlich richtige Projekte entwickeln und damit auch noch mein Studium finanzieren konnte.

Schnell merkte ich aber, dass zu Softwareentwicklung weit mehr gehört als nur das Programmieren, und so versuchte ich, meine Projekte nach den Methoden durchzuführen, die ich in dem Fach Softwaretechnik gelernt hatte – leider mit mäßigem Erfolg.

Zum gleichen Zeitpunkt empfahl mich mein Professor, bei dem ich die Stelle gekündigt hatte, für eine Bachelor-Thesis bei einer Firma, die ebenfalls jüngst zu der Erkenntnis gekommen war, dass zu Softwareentwicklung mehr als Programmieren gehört.

Dort schrieb ich dann für ein halbes Jahr meine Bachelorarbeit und dabei konnte sehr viel über professionelle Softwareentwicklung aus allen möglichen Blickwinkeln lernen. Außerdem hatte ich viel Zeit, mich in die Bereiche Softwareprojektmanagement und Softwarequalität einzuarbeiten. Besonders die Methoden zur expliziten und impliziten Messung der Softwarequalität wie Unittests, Profiling, Metriken, ... haben mich sehr begeistert.

Da ich von 8 bis 17 Uhr für die eine, von 19 bis 0 Uhr für die andere Firma gearbeitet habe, habe ich dann versucht, das gelernte in meine Projekte bei uniserve einzubringen. Dort konnte ich dann von Woche zu Woche sehen, wie nicht nur die Qualität meiner Software besser wurde, sondern wie auch das ganze Projektmanagement schlagartig besser funktionierte.

Nach wenigen Wochen wurde mir klar, dass ich in meinem bald anstehenden Masterstudium mehr zu diesen Themen lernen wollte und fand nach kurzer Zeit einen entsprechenden Studiengang in Marburg, der genau diese Inhalte abdeckte.

Zeitgleich entdeckte ich das Microsoft Student Program, in welchem Microsoft eine kleine Gruppe .NET-interessierter Studenten mit Literatur, Lehrgängen und Software unterstützte, und diesen zudem die Möglichkeit gab, sich zertifizieren zu lassen. Nachdem die Bachelorarbeit beendet und mein Masterplatz in Marburg gesichert war, wurde ich auch im Student Program angenommen.

Heute habe ich mich in Marburg auf Softwarequalität und -entwicklung in verteilten Systemen spezialisiert, im Rahmen des Student Programs reise ich durch Deutschland und halte Workshops an Universitäten und Fachhochschulen, um andere Studenten auch für .NET – eine geniale Technologie – begeistern zu können, und baue schließlich bei uniserve systematisch eine Software für Kameramanagementsysteme auf.

Vor zwei Monaten wurde ich als Microsoft Certified Professional zertifiziert, und lerne derzeit für meine Microsoft Certified Technology Specialist Prüfung. Darüber hinaus versuche ich nach meinem Studium einen Promotionsplatz im Bereich „Softwarequalität in agilen Vorgehensmodellen“ zu bekommen, da in diesem Bereich die Forschung noch nicht weit fortgeschritten ist – aber bis dahin ist es noch ein langer Weg.

Golo Roden: Ein wesentliches Merkmal der IT ist, dass man beständig mit neuen Entwicklungen konfrontiert wird, und diesen folgen muss. Woher nimmst Du die Motivation, Dich quasi jeden Tag weiterzubilden und mit Neuem zu beschäftigen?

David Tielke: Mir fällt das Lernen sehr leicht, wenn ich mich für etwas begeistert habe. Bei .NET geht es sogar so weit, dass ich mir selbst die Frage stellen muss, wie ich verhindere, dass meine Motivation nicht überhandnimmt.

Früher als Kind und als Jugendlicher habe ich mich immer gefragt, wie bestimmte Dinge in der IT-Welt funktionieren, und mir vorgestellt, dass so etwas unglaublich kompliziert sein muss. Heute kann ich mit Stolz sagen, Teile dieser Welt zu beherrschen, und ich freue mich und habe unglaublichen Spaß daran, jeden Tag neue Dinge in diesem Bereich lernen und mein Wissen somit Stück für Stück aufbauen zu können.

Jeder, der den Entschluss fasst, in dieser Branche zu arbeiten, sollte sich der Tatsache bewusst sein, dass die Halbwertszeit von Wissen in der Softwareentwicklung nur ein bis zwei Jahre beträgt und man somit lebenslang neue Technologien lernen muss beziehungsweise darf. Die Frage ist nur, wie man an diese Herausforderung herangeht: Ich mache es mit Spaß und Begeisterung!

Golo Roden: Wenn sich ein Anfänger heute mit dem Thema Softwareentwicklung befassen will – welche Voraussetzungen sollte er Deiner Meinung nach dafür mitbringen, und was siehst Du als No-Go an?

David Tielke: Wie bei allen Themen ist es am wichtigsten, dass man Spaß und Begeisterung für die Thematik mitbringt. Ich kenne viele Softwareentwickler, für die das ganze „nur ein Beruf“ ist, und ich sehe seit Jahren, wie sie immer auf der Stelle treten und sich kaum noch weiterentwickeln, während junge und motivierte Entwicklerkollegen sie bereits eingeholt oder gar überholt haben.

Ebenfalls ist der Spaß am Lesen sehr wichtig: Ich denke, kaum ein guter Entwickler kommt ohne das regelmäßige Studieren von Büchern aus. Da dies meist in der Arbeitszeit nicht machbar ist, sollte man auch in seiner Freizeit gewillt sein, das ein oder andere Buch durchzuarbeiten – auch wenn man dafür nicht bezahlt wird. Aber auch hier gilt wieder: Einige „müssen“ diese Bücher durchlesen, andere „dürfen“ es. Ich zähle mich zu den letzeren.

Man sollte sehr früh versuchen, Praxiserfahrung zu sammeln, weil es etwas anderes ist, nach einem Pflichtenheft zu entwickeln, als nach Vorstellungen, die man selbst nur im Kopf hat. Die ganzen Dinge, die man in Vorlesungen in der Uni gelernt hat, sind nutzlos, wenn man nicht selbst am Kunden gesehen hat, wie schnell sich in einer Software alles ändern kann und wie praktisch es dann plötzlich ist, wenn man beispielsweise im Strategypattern nur eine Strategy ersetzen muss, um das Verhalten des ganzen Systems zur Laufzeit zu verändern.

Dabei ist es wichtig, immer am Ball zu bleiben und sich nicht entmutigen zu lassen, egal, wie kompliziert eine Technologie ist, oder wie lang die Debugsessions dauern. Man sollte seine Projekte und Arbeiten dabei sehr selbstkritisch betrachten, weil besonders bei Softwareprojekten immer Verbesserungen möglich sind.

Insbesondere sollte man auch Feedback und Kritik von anderen dankend aufnehmen und es als Chance sehen, sich weiterzuentwickeln. Wer seine Arbeit nicht gern zur Kritik stellt und mit Feedback nicht richtig umgehen kann, wird nie ein guter Softwareentwickler werden.

Golo Roden: Bei der Vielzahl an Technologien, die es heute gibt: Womit sollte ein Anfänger heutzutage anzufangen?

David Tielke: Wichtig ist auf jedem Fall, zunächst ein solides Fundament in C# und vor allem in objektorientierter Programmierung zu haben. Das Thema der Klassen und Interfaces fand ich besonders am Anfang eine Hürde, aber dank zahlreicher freier Literatur zu dem Thema im Internet ist das mit etwas Geduld zu meistern.

Danach sollte man zu einer Technologie greifen, die keine weiteren Vorkenntnisse voraussetzt, wie zum Beispiel Windows Forms als UI-Framework. Dort können dann all die Konzepte von C# wie Klassen, Events, Delegates, ... wiederholt und gefestigt werden. Auf diese Art hat man danach auf jeden Fall ein ausreichendes Grundverständnis für alle weiteren Technologien.

Des Weiteren sollte man auf jeden Fall einen kleinen Abstecher zu XML machen, weil das eine Technologie ist, auf die sehr viele andere Frameworks zurückgreifen und man einfach überall in .NET mit XML in Berührung kommt, beispielsweise bei den Konfigurationsdateien.

Danach sollte man die weiteren Punkte nach persönlicher Neigung angehen. Für fast alles weitere kommt man um das Erlernen einer oder mehrerer Zusatzpunkte nicht herum – XAML für WPF und Silverlight; SOAP für WCF; HTML, CSS und JavaScript für ASP.NET; SQL für ADO.NET; ...

Hierbei bietet es sich an, eine Technologie zu wählen, bei der man die eine oder andere Hilfstechnologie bereits beherrscht, oder bei der das Erlernen der Zusatzpunkte sehr leicht fällt.

Golo Roden: Du hast Dich auf Softwarequalität spezialisiert – wie kam es dazu? Und welche Rolle misst Du diesem Thema für Anfänger zu?

David Tielke: Zunächst fand ich bereits in den Univorlesungen das Testen von Software eine sehr spannende Sache, weil man so jederzeit in der Lage war, die Korrektheit des Gesamtsystems zu testen. Genau an dem Punkt, an dem ich in meinen eigenen Projekten feststellte, wie wichtig das gesamte Thema ist, kam mein Professor mit der Bachelorthesis zu dem Thema auf mich zu und, wodurch ich mich immer weiter in dieses Gebiet vertiefte.

Ich finde es beeindruckend, wie man mit Methoden und Techniken den stark kreativen Prozess der Softwareentwicklung an die gleiche Qualität wie bei der herkömmlichen industriellen Fertigung heranführen kann.

Auch wenn das Thema nicht direkt zu Beginn bei einem Anfänger auf der Liste stehen sollte, so kommt man daran über kurz oder lang nicht vorbei. Spätestens, wenn man in ein Team kommt, das schon seit Jahren qualitativ hochwertige Software entwickelt, muss man sich mit dem Thema Softwarequalität auseinandersetzen.

Allerdings ist es ebenso wichtig, erst einmal in die vielen Fallen zu treten, die da draußen in der Softwarewelt ausliegen, damit man wirklich versteht, welchen Sinn bestimmte Techniken haben.

Golo Roden: Welchen Rat würdest Du einem Anfänger abschließend mit auf den Weg geben?

David Tielke: Als Anfänger sieht man oft den Wald vor lauter Bäumen nicht. Leider gibt es für Einsteiger nur sehr wenig Literatur, meist wird man zudem direkt zu Beginn mit Techniken und Abkürzungen erschlagen und verliert dann ein wenig die Motivation.

Hier ist es wichtig, am Ball zu bleiben, denn nur die wenigsten verstehen alle Konzepte direkt von Anfang an. Zumeist liest man etwas und stolpert dann zu einem späteren Zeitpunkt in einem Projekt über eine Problemstellung die eine solche Lösung erfordert. Dann erinnert man sich meist und kann mit etwas Nachlesen das Problem lösen.

Falls man Schüler oder Student ist, sollte man versuchen, eine Nebentätigkeit zu bekommen – besonders für Studenten gibt es sehr viele Nebenjobs als Softwareentwickler – oder sich an Opensource-Projekten zu beteiligen, um möglichst schnell „richtige“ Praxiserfahrung zu sammeln. Das bringt nämlich wesentlich mehr als zu Hause im stillen Kämmerlein zu entwickeln.

Auch wenn Programmieren wichtig ist, muss man sich darum kümmern, auch die theoretischen Themen zu beherrschen, da diese für die Entwicklung von qualitativ hochwertiger Software enorm wichtig sind.

Wie in allen anderen Branchen ist auch in der Softwareentwicklung noch kein Meister vom Himmel gefallen. Wichtig ist, dass man sich stetig weiterentwickelt – der Rest kommt von ganz allein.

Performanceimplikationen von System.Transactions

Montag, 9. November 2009, 14:23 Uhr
Permalink | Kommentare (0) | Kommentare als RSSRSS

In meinem Blogeintrag Transaktionale Methoden habe ich vorgestellt, wie mit Hilfe von PostSharp ein TransactionalAttribute für .NET implementiert werden kann, das sich analog zu der @Transactional-Annotation von JEE verhält. Intern habe ich dabei den in .NET 2.0 eingeführten Namensraum System.Transactions verwendet.

Nun wurde als Kommentar zu diesem Blogeintrag die Frage gestellt, ob die Klasse TransactionScope generell verwendet werden könne, oder ob man besser auf die klassischen ADO.NET-Transaktionen zurückgreifen sollte, weil diese angeblich performanter seien.

Als Antwort auf diese Frage habe ich folgenden Kommentar verfasst:

die kurze Antwort lautet: Sofern Du den SQL Server einsetzt, kannst Du guten Gewissens auf System.Transactions setzen, bei anderen Datenbanken ist zumindest Vorsicht geboten.

Wie komme ich zu dieser Aussage?

Vor der Einführung des Namensraums System.Transactions in .NET 2.0 gab es zwei verschiedene Möglichkeiten, Transaktionen zu verwenden:

  • Einerseits konnten die klassischen ADO.NET-Transaktionen verwendet werden, die programmatisch angesprochen und gesteuert wurden.
  • Andererseits konnten die Enterprise Services verwendet werden, um deklarativ Methoden zu kennzeichnen, die transaktional ausgeführt werden sollten.

Beide Verfahren haben ihre jeweiligen Vor- und Nachteile: Da die klassischen ADO.NET-Transaktionen direkt auf der Datenbank ausgeführt werden, sind sie sehr performant, sind aber für verteilte Transaktionen ungeeignet.

Transaktionen, die hingegen über die Enterprise Services ausgeführt werden, verwenden implizit den Distributed Transaction Coordinator (DTC) von Windows und sind daher für verteilte Transaktionen geeignet. Da der DTC jedoch immer eingesetzt wird – auch dann, wenn eine lokale Transaktion genügen würde – ist die Performance nicht ganz so hoch wie bei den klassischen ADO.NET-Transaktionen.

Der Namensraum System.Transactions dient nun als Nachfolger für beide Varianten, weshalb prinzipiell so wohl lokale wie auch verteilte Transaktionen unterstützt werden. Die Logik, nach welcher der DTC hinzugezogen wird (oder eben nicht), ist dabei folgendermaßen aufgebaut:

  • Wenn eine Verbindung zum SQL Server aufgebaut wird, wird die Transaktion zunächst lokal ausgeführt. Sobald innerhalb der gleichen Transaktion eine weitere Verbindung zu einer Datenbank aufgebaut wird, wird die Transaktion verteilt ausgeführt. Damit dies funktioniert, enthält der SQL Server ein Feature namens Transaction Propagation, womit eine lokale in eine verteilte Transaktion umgewandelt werden kann.
  • Wenn eine Verbindung jedoch zu einer anderen Datenbank als einem SQL Server aufgebaut wird, geht .NET davon aus, dass Transaction Propagation nicht unterstützt wird, weshalb von System.Transactions direkt eine verteilte Transaktion gestartet wird – unabhängig davon, ob noch eine weitere Verbindung zu einer anderen Datenbank hergestellt wird oder nicht.

Die Konsequenz: Sofern innerhalb einer Transaktion nur eine einzelne Verbindung zu einem SQL Server hergestellt wird, verhält sich System.Transactions analog zu der klassischen ADO.NET-Transaktion – und verfügt damit über dieselbe Performance.

Der Overhead des DTC schlägt erst bei verteilten Transaktionen oder beim Einsatz einer anderen Datenbank zu.

Insofern kann man die Verwendung von System.Transactions beim Einsatz von SQL Server guten Gewissens generell empfehlen – bei allen anderen Datenbanken ist hingegen Vorsicht geboten, da hier automatisch der DTC zum Einsatz kommt, auch wenn keine verteilten Transaktionen genutzt werden.

Auch Kirchen haben Kragsteine

Samstag, 7. November 2009, 18:41 Uhr
Permalink | Kommentare (3) | Kommentare als RSSRSS

Vor knapp einer Woche habe ich mit meinem Blogeintrag Wie viel Sinn machen Unittests? – der im Rahmen der monatlichen Streitgespräche von Peter Bucher und mir erschienen ist – für einige Verwunderung gesorgt. Viele haben sich gefragt, warum gerade ich Unittests dermaßen skeptisch gegenüberstehe.

Ralf Westphal hat in seinem Kommentar vermutet, dass

etwas hinter den drei “problematischen Aspekten” das Grundproblem zu sein [scheint]

und ich muss zugeben, dass diese Vermutung nicht von der Hand zu weisen ist. Als problematisch habe ich an Unittests im Wesentlichen die Tatsache betrachtet, dass Code zum Zweck einer besseren Testbarkeit potenziell angepasst werden muss, da sich einige Konstrukte ansonsten nur schlecht oder gar nicht testen lassen.

Als Beispiel seien an dieser Stelle abstrakte Klassen angeführt, die per Definition nicht instanziiert und deshalb nicht direkt getestet werden können. Prinzipiell kann dieses Problem auf zwei Arten gelöst werden:

  • Entweder werden die bereits bestehenden abgeleiteten Klassen getestet – immerhin ist die abstrakte Basisklasse in diesen implizit enthalten.
  • Alternativ wird eine dedizierte abgeleitete Klasse erstellt, welche die abstrakte Basisklasse beerbt – die Basisklasse ist also auch in dieser Variante implizit enthalten.

Der relevante Unterschied zwischen beiden Varianten liegt in der Tatsache, dass die bereits bestehenden abgeleiteten Klassen eigene Funktionalität mitbringen, die den Test nicht unbedingt verfälschen, aber zumindest beeinflussen könnte: Es wird schwierig, den Test auf die abstrakte Basisklasse zu beschränken.

Eine dedizierte Klasse verfügt nicht über diese Nachteile: Sie sorgt lediglich dafür, dass die abstrakte Basisklasse in möglichst natürlicher Form instanziiert werden kann.

Technisch ist dieses Vorgehen unproblematisch, aber mental bereitete es mir Probleme: Seit Jahren wird Entwicklern vor allem in der akademischen Welt impliziert, dass Code nur dann “gut” ist, wenn er kompakt, elegant und im mathematischen Sinne schön ist.

Wie sind nun Änderungen, die nur um einer besseren Testbarkeit durchgeführt werden, mit diesem Paradigma vereinbar? Die kurze, aber schmerzhafte Antwort lautet: Gar nicht.

Wie bereits in Wie viel Sinn machen Unittests? angesprochen, beschreibt auch Roy Osherove in seinem Buch The Art of Unit Testing in dem Abschnitt Overcoming the encapsulation problem dieses Problem:

Some people feel that opening up the design to make it more testable is
a bad thing because it hurts the object-oriented principles the design is
based on. I can wholeheartedly say to those people, “Don’t be silly.”

Seine zugegebenermaßen sehr pragmatische Lösung

“Don’t be silly.”

dieses Problems stellt für mich keine zufriedenstellende Antwort dar – schließlich kommen die Bedenken nicht von ungefähr, und diese Antwort spiegelt dies in keinerlei Hinsicht wieder.

Auch die im Gespräch mit einigen anderen Entwicklern geäußerte Ansicht

Das ist halt so.

ist nicht zufriedenstellend. Diese Aussage beschreibt nämlich lediglich den Status Quo, begründet aber nicht, warum es in Ordnung oder vielleicht sogar gut ist, auf diese Art vorzugehen. Letztlich spiegelt diese Aussage lediglich das resignierte Abfinden mit einer – potenziell – unbequemen Tatsache dar.

Doch nun hat Ralf Westphal eine Begründung geliefert, die den Ansprüchen der Skeptiker – zumindest aus meiner Sicht – genügt:

das ist völlig ok. maschinen haben ja auch revisionsklappen für wartungsarbeiten. die haben sonst keine funktionalität. oder denk an kragsteine an alten kirchen, damit man gerüste anbringen kann.

Nach einigen Jahren des Zweifels und der Skepsis empfinde ich diese Analogie als eine wahre Erlösung – endlich wird begründet, warum ein solches Vorgehen in der Software in Ordnung ist.

Man mag einwenden, dass dieser Vergleich zur realen Welt doch offensichtlich und naheliegend sei, doch war in den vergangenen Jahren sonst niemand, mit dem ich mich über dieses Thema unterhalten habe, in der Lage, einen ähnlich klaren, einleuchtenden Vergleich zu ziehen.

Persönlich bemerke ich, dass diese Erkenntnis eine Art Wendepunkt darstellt – die mentale Barriere, mit der ich mich bislang gegen Unittests gesträubt habe, weil sie Anpassung von Code erfordern, ist aufgelöst. Alles, was bleibt, sind technische Probleme – und diese können mit Sicherheit gelöst werden.

Als Konsequenz werde ich das umsetzen, was Ralf Westphal vorgeschlagen und empfohlen hat:

Unit Tests […] konsequent und kompetent mal für einen Monat einzusetzen. Mit der Kompetenz mag es da schwierig sein, weil man sich dann eine Veränderung der Handlungs- und Denkgewohnheit selbst beibringen muss... aber das ist zumindest ein Anfang.

Wie es mir damit ergeht – darüber werde ich berichten …

Wie viel Sinn machen Unittests?

Sonntag, 1. November 2009, 09:37 Uhr
Permalink | Kommentare (20) | Kommentare als RSSRSS

Am 13. Oktober 2008 haben Peter Bucher und ich unter dem Titel Noch Fragen, Bucher? Ja, Roden! angekündigt, jeweils zum ersten eines jeden Monats einen Kommentar zu einem vorab gemeinsam gewählten Thema verfassen zu wollen. Bisher sind in dieser Reihe folgende Kommentare erschienen:

Heute, am 1. November 2009, ist es nun wieder so weit, und unser Thema für diesen Monat lautet:

Wie viel Sinn machen Unittests?

So wohl Peter wie auch ich haben uns unabhängig voneinander im Vorfeld unsere Gedanken gemacht, wie wir diesem Thema gegenüberstehen. Außerdem nimmt diesen Monat auch Christian Wenz wieder an unserem Streitgespräch teil.

Peters und Christians Kommentare findet sich zeitgleich in den entsprechenden Blogs, folgend nun mein Kommentar zu diesem Thema:

Unittests sind sinnvoll – nicht ohne Grund wird ihr konsequenter Einsatz empfohlen, unter anderem im Rahmen der Clean Code Developer-Initiative und des Extreme Programmings, von der dediziert auf Tests optimierten Entwicklungsmethode Test-Driven Development (TDD) ganz zu schweigen.

In der Theorie hören sich diese Ansätze zunächst auch sehr vielversprechend an. Schließlich ermöglicht der konsequente, durchgängige Einsatz von Unittests eine gefahrlose Änderung von bestehendem Code.

Unbeabsichtigte Seiteneffekte werden durch die Ausführung der Unittests sofort aufgedeckt und können somit vermieden werden. Zudem können gefundene Bugs unmittelbar durch neu geschriebene Unittests abgesichert werden, so dass sie sich nicht erneut einschleichen können.

So weit die Theorie, die Praxis sieht leider ein wenig anders aus. So leicht Unittests nämlich erklärt sind, so kompliziert ist ihre tatsächliche Umsetzung – vorausgesetzt, man strebt tatsächlich eine 100%ige Abdeckung an.

Problematisch sind in der Regel drei Aspekte:

  • Der bestehende objektorientierte Aufbau ist unter OOP- und stilistischen Aspekten sauber umgesetzt, läuft einer guten Testbarkeit allerdings zuwider.
  • Es bestehen zahlreiche Abhängigkeiten zu externen Komponenten, die sich nicht oder nur mit sehr viel Aufwand simulieren lassen.
  • Es bestehen Abhängigkeiten zur konkreten Laufzeitumgebung, die sich nicht oder nur mit sehr viel Aufwand nachbilden lassen.

Entwickler, die sich an Clean Code Developer orientieren,und die auch ansonsten versuchen, beispielsweise mit Werkzeugen wie FxCop ihren Stil und ihre Codequalität zu verbessen, streben in der Regel ein sauberes und durchdachtes objektorientiertes Design an.

Leider steht manchmal genau ein solches Design der Testbarkeit gegenüber. Häufig müssen beispielsweise im Sinne der Testbarkeit weitere Konstruktoren, zusätzliche Eigenschaften oder Schnittstellen zu einer Klasse hinzugefügt werden – obwohl dies aus einer rein objektorientierten Sicht keinen Sinn ergibt.

Roy Osherove beschreibt in seinem Buch The Art of Unit Testing in dem Abschnitt Overcoming the encapsulation problem dieses Problem:

Some people feel that opening up the design to make it more testable is
a bad thing because it hurts the object-oriented principles the design is
based on. I can wholeheartedly say to those people, “Don’t be silly.”

Leider kann ich mich seiner leichtfertigen Aussage “Don’t be silly” nicht so einfach anschließen – denn ein Unittest ist eben nicht einfach nur ein weiterer Verwender der API. Für den Unittest ist es nämlich im Gegensatz zu realen Entwicklern gleichgültig, ob eine API sinnvoll strukturiert ist oder nicht.

Daher empfinde ich es zumindest als bedenklich, ein durchdachtes, objektorientiertes und sauberes Design zu Gunsten einer besseren Testbarkeit zu ändern, wenn es dafür keine weiteren Gründe gibt.

Neben dem potenziell wenig Unittest-tauglichen objektorientierten Design stellt die Abhängigkeit von externen Komponenten ein weiteres häufiges Problem dar. Zu nennen sind hierbei unter anderem:

  • Datenbanken
  • Dateisysteme
  • Registry

Natürlich können all diese Abhängigkeiten entfernt, umgangen oder verschleiert werden – die Frage ist aber, zu welchem Preis dies geschieht. Es genügt nämlich nicht, Stubs und Mocks einzuführen, statt dessen muss die Umgebung auch nach jedem Test potenziell wieder zurückgesetzt werden: Schließlich soll jeder Test isoliert, das heißt unabhängig von seinen Vorgängern, ausgeführt werden.

Eine Datenbank wieder und wieder zurückzusetzen, ist technisch zwar machbar, kostet allerdings sehr viel Zeit. Damit wird das Ziel, alle Unittests bei jedem Build automatisch auszuführen, ab einem gewissen Punkt unerreichbar: Die zur Ausführung der Unittests benötigte Zeit liegt schlichtweg zu hoch.

Zudem können gar nicht alle externen Abhängigkeiten ohne weiteres aufgelöst werden – vor .NET 3.5 SP1 und der Einführung von System.Web.Abstractions war es zum Beispiel nur eingeschränkt möglich, den HTTP-Kontext einer Webanwendung zu simulieren.

Auch die Abhängigkeit von der Laufzeitumgebung an sich kann problematisch sein. So können sich beispielsweise HTTP-Anforderungen, die an eine Webanwendung gesendet werden, voneinander unterscheiden – je nachdem, welcher Webbrowser auf dem Client eingesetzt wird.

Um Webbrowser-spezifisches Verhalten zu simulieren, müssten die Eigenheiten des jeweiligen Webbrowsers im Unittest nachgebildet werden. Alternativ könnten der entsprechenden gewünschte Webbrowser automatisiert werden – was seinerseits allerdings einen ziemlichen Aufwand nach sich zieht.

Ebenfalls problematisch ist multithreaded Code, sofern bestimmte Konstellationen in den einzelnen Threads getestet werden sollen – da das Umschalten zwischen den Threads vom aktuellen Kontext des Prozessors beziehungsweise des Betriebssystems abhängt, kann sich das Verhalten von Ausführung zu Ausführung unterscheiden.

All diese Beispiele zeigen, dass es unter Umständen sehr aufwändig oder gar unmöglich sein kann, einen Unittest zu schreiben, der unter realitätsnahen Bedingungen ausgeführt wird.

Die Frage ist also nicht, ob eine 100%ige Testabdeckung wünschenswert ist – dies gilt rein von der Theorie her ohne jegliche Zweifel – sondern ob eine 100%ige Testabdeckung mit vernünftigem und vertretbaren Aufwand erreicht werden kann: Diese Frage kann durchaus mit Nein beantwortet werden.

Nichtsdestotrotz gibt es natürlich auch Code, der sich perfekt für Unittests eignet: So fallen beispielsweise sämtliche Algorithmen in diese Kategorie, da diese in der Regel kaum oder gar keine Abhängigkeiten zu anderen Komponenten aufweisen.

Daher ergibt es durchaus Sinn, Unittests zu schreiben – die Frage ist lediglich, wofür. Eine 100%ige Abdeckung mit Unittests erreichen zu können klingt zwar verlockend, der zur Erreichung dieses Ziels notwendige Aufwand lohnt in der Regel jedoch nicht.

Insofern muss im konkreten Kontext abgewogen werden, welche Komponenten als kritisch zu betrachten sind und der Abdeckung durch Unittests bedürfen. Selbst für diese Komponenten ist eine 100%ige Abdeckung noch ein ausgesprochen ehrgeiziges Ziel – daher empfiehlt es sich eher, eine zwar hohe, aber nicht perfekte Abdeckung wie beispielsweise 85% anzustreben.

Wie viel Sinn machen Unittests also nun? Zusammengefasst kann man sagen, dass Unittests – an der richtigen Stelle eingesetzt – durchaus Sinn ergeben, dass diese Stellen aber explizit ausgewählt werden sollten.

prio.conference 2009: Von der Idee zur fertigen UI – für Entwickler

Donnerstag, 29. Oktober 2009, 17:29 Uhr
Permalink | Kommentare (1) | Kommentare als RSSRSS

In den vergangenen beiden Tagen fand die prio.conference statt – zum ersten Mal seit ihrem Bestehen allerdings nicht im Kurhaus von Baden-Baden, sondern im Marriott Hotel in München.

Im Gegensatz zu vielen anderen Konferenzen ist die prio eine Konzeptkonferenz, das heißt, jedes Jahr beschäftigt sie sich mit nur einem ausgewählten Thema – dieses wird aber mit sehr viel Liebe zum Detail behandelt. Nachdem die Agenda in den vergangenen Jahren eher von abstrakten Themen wie Softwarequalität und Softwarearchitektur geprägt war, wurde für 2009 das Thema User Interface ausgewählt.

Wie bereits im vergangenen Jahr war ich auch in diesem Jahr mit einer Session im Konzept-Track vertreten. Meine Session

Von der Idee zur fertigen UI – für Entwickler

behandelte dabei die Frage, wie man zu einer gut bedien- und benutzbaren UI kommt, wenn man als Entwickler auf sich allein angewiesen ist und keinen dedizierten Designer zur Hand hat.

Kernelement dieser Session waren daher die beiden Begriffe User Model und Program Model, die für eine gute User Experience miteinander in Einklang gebracht werden müssen.

Auch dieses Jahr hat meine Session sehr viele Interessierte angezogen; die Session war mit ungefähr 120 Teilnehmern äußerst gut besucht. Im Wesentlichen habe ich in der Session die folgenden Punkte behandelt:

  • Entwickler vs Designer
  • UI-Design ist kein Grafikdesign
  • Was macht eine gute UI aus?
  • UIs kontrollieren
  • UIs sind nicht intuitiv
  • User Model vs Program Model
  • Usabilitytests
  • Auswahlmöglichkeiten
  • Konsistenz von UIs
  • Benutzer lesen keine Handbücher
  • Benutzer sind unsicher mit der Maus
  • Benutzer merken sich nichts

Insgesamt bin ich sehr zufrieden, wie alles gelaufen ist, und das Feedback, das ich bislang von den Teilnehmern erhalten habe, zeigt mir, dass die Session informativ und unterhaltsam zugleich war und positiv aufgenommen wurde.

Abschließend möchte ich noch dem Team von der prio, allen voran Ralf Westphal als Konferenzmanager, Tilman Börner als Chefredakteur der dotnetpro und den Damen der Veranstaltungsorganisation für die sehr beeindruckende Konferenz und die sehr gute Vorarbeit danken.

Stirnrunzeln über “Bugtracking ist sinnlos”

Mittwoch, 21. Oktober 2009, 09:33 Uhr
Permalink | Kommentare (5) | Kommentare als RSSRSS

Ilker Cetinkaya hinterfragt in seinem aktuellen Blogeintrag den Sinn von Bugtacking und schließt mit einem provokanten Fazit:

Bugtracking ist sinnlos!

Für ihn steht der Verwaltungsaufwand, der für ein entsprechendes System notwendig ist, in keinem Verhältnis zum Nutzen – zumindest dann nicht, wenn man ohnehin agile Methoden wie XP oder Scrum einsetzt.

Sein Vorschlag zum Umgang mit Bugs lautet:

Wenn ein Bug wirklich ein wichtiger Bug ist, dann wird er sofort gefixed. Alles andere ist entweder nicht wichtig oder wird dann erst wichtig, wenn die wichtigeren Dinge schon erledigt sind.

Doch nicht nur das Bugtracking, auch das –reporting hinterfragt Ilker. So schlägt er zusätzlich vor,

ein leichtgewichtiges Bugreporting [zu] etablieren und die Entscheidung über den Fix oder No-Fix des Bugs schnell herbei[zu]führen

Insgesamt verwundern mich diese Vorschläge sehr, denn es gibt einige Aspekte, die Ilker vollständig ignoriert: Die Entscheidbarkeit, die Nachvollziehbarkeit und zuletzt auch die Transparenz.

Er geht davon aus, dass für jeden Bug sofort entschieden werden kann, ob dessen Relevanz genügt, um zeitnah behoben zu werden. Die Entscheidung, ob ein Bug dermaßen relevant ist, dass er sofort beseitigt wird, wird in der Regel möglich sein.

Im Endeffekt bedeutet das nämlich, dass all jene Bugs gefixt werden, die bei Verwendung eines Bugtrackingsystems mit oberster Priorität und als höchst kritisch gekennzeichnet worden wären.

Die Frage ist aber, was mit einem Bug geschehen soll, der diese Kriterien nicht erfüllt. Dazu schlägt Ilker vor:

Ist er nicht wichtig genug (also ist entweder ein anderer Bug oder ein anstehendes Feature wichtiger), so wird der Report weggeworfen.

Interessanterweise schreibt er direkt im nachfolgenden Satz:

Der Benutzer wird benachrichtigt dass der Fehler momentan nicht korrigiert wird.

Beachtenswert an diesem Satz ist für mich das Wort momentan – das heißt, Ilker räumt ein, dass es sinnvoll sein könnte, den Bug zu einem späteren Zeitpunkt zu fixen. Doch wie merken sich die Entwickler diesen Bug und dessen Details, wenn sie ihn nirgends notieren dürfen?

Es liegt auf der Hand, dass dabei über kurz oder lang Bugs vergessen werden, oder dass zumindest Details verloren gehen, die zur Behebung potenziell wichtig gewesen wären.

Interessant finde ich auch, welches Resultat Ilker anführt: Durch den Verzicht auf Bugtracking und die sofortige Entscheidung wird direkt an den Benutzer kommuniziert, ob der von ihm gemeldete Bug behoben wird oder nicht. Dies nennt er:

Ehrlich, sachlich, klar.

Ohne Frage wird die Transparenz über die sofortige Entscheidung erhöht – jegliche sonstige Transparenz geht allerdings verloren – nicht nur für die Entwickler, auch für den Benutzer:

  • Ohne Bugtracking weiß niemand, welche Bugs vor langer Zeit abgelehnt wurden, insbesondere aus welchen Gründen dies geschehen ist.
  • Ohne Bugtracking weiß niemand, wie oft welcher Bug auftritt – dies kann man nur noch nach persönlichem Gutdünken schätzen.
  • Ohne Bugtracking bekommt der Benutzer nur die Aussage, dass sein Bug momentan nicht behoben wird – was damit zukünftig geschieht, kann er nicht nachverfolgen.
  • Ohne Bugtracking weiß niemand, wie viele gefundene, aber ungefixte Bugs es in einer Software gibt.

Diese Liste ließe sich noch lang fortsetzen. Worauf ich hinauswill, wird aber deutlich: Bugtracking ist nicht nur nicht sinnlos, es ist sogar enorm wichtig für den Erfolg eines Projekts!

In einem einzigen Punkt kann ich Ilker allerdings dennoch zustimmen:

[…] wenn man wirklich das Produkt stetig weiterentwickeln möchte auch immer sich zum Ziel setzen muss, ein möglichst fehlerfreies Produkt auszuliefern.

Dieser Aussage stimme ich vollkommen zu – lediglich die Konsequenzen, die er daraus zieht, kann ich weder nachvollziehen noch gutheißen.