Seit ein paar Monaten wird der Begriff NoSQL (Not only SQL) immer häufiger verwendet. Wir sind mit unserer schemalosen Datenbank StupidDB vor eineinhalb Jahren bereits auf diesen Zug aufgesprungen und jetzt hat sie einen Überbegriff bekommen: auch StupidDB ist NoSQL!

Auf dem BarCamp in Nürnberg war NoSQL auch ein Thema und Jonathan Weiss hat in seiner Session gut dargestellt, dass relationale Datenbanken nicht immer die Lösung für alle Probleme sind. NoSQL Datenbanken speichern meist dokumentenorientiert und sind dadurch nicht an ein festes Schema gebunden. Relationale Datenbanken haben ein fixes Schema und erlauben dynamische Abfragen der Daten, bei NoSQL ist dies umgekehrt. Weitere Informationen zu NoSQL bei Wikipedia.

Im März Heft der dotnetpro stelle ich ausführlich den Einsatz von StupidDB vor. Das Heft ist am 18.2.2010 erschienen und sollte jetzt in jedem gut sortierten Kiosk erhältlich sein.

Für alle, die sich Heft nicht griffbereit haben, ich habe bereits Mitte letzten Jahres in einem Blogpost den Einsatz von StupidDB beschrieben. Hier sieht man zumindest die Grundzüge der StupidDB. Das aktuelle dotnetpro Heft lohnt sich jedoch trotzdem, da hier noch weitere Artikel zum Thema NoSQL zu finden sind. Unter anderem das Lounge Repository von Ralf Westphal und auch CouchDB.

Als neuester Vertreter in der NoSQL Bewegung gilt MongoDB. Eine Opensource Implementierung die nun auch Sourceforge einsetzt. Auch dafür gibt es schon Blogposts und Tests mit .NET.

Zudem hat Ayende Rahien im Herbst letzten Jahres auch seine Rhino Divan DB vorgestellt. Interessant klingt auch Object Lounge.

Es scheint also ein Bedarf an alternativer Datenpersistenz zu bestehen, wird sich zeigen wohin dieses Jahr die Reise bei NoSQL geht.

Wer sich den aktuellen Code einmal ansehen möchte, kann dies gerne unter folgendem Link ansehen:
https://stupiddb.svn.sourceforge.net/svnroot/stupiddb/trunk

Verwendet ihr schon NoSQL?

kick it on dotnet-kicks.de

Comments 2 Kommentare »

Im Teil 1 (MVP mit WinForms) habe ich die Grundgedanken zur Implementierung von MVP in WinForms vorgestellt, mit der man WinForm-Anwendungen mit UnitTests abdecken kann. In einer komplexeren WinForm-Anwendung gibt es neben dem Startform auch mehrere Unterforms, die durch das Hauptform aufgerufen werden müssen.

Das Beispielprojekt

Zur Demonstration habe ich ein Beispielprogramm mit MVP entwickelt, welches einen sehr einfachen Twitterclient darstellt. Das Beispiel wurde nach Contract-First komponentenorientiert gebaut und besteht neben der MVP-Komponente aus weiteren Komponenten.

Die weiteren Komponenten haben nichts mit MVP zu tun, sondern sollen nur zeigen, wie man MVP in diesem Umfeld integriert. -> Den kompletten Sourcecode downloaden

Die Funktionen des Twitter-Clients sollen sein:
1. Anzeige der 20 neuesten Meldungen aus der Timeline im Hauptfenster
2. Der Benutzer soll Status-Updates bei Twitter posten können
3. Die Zugangsdaten des Twitter-Accounts sollen gespeichert werden können

Die WinForm-Komponente

Um die Funktionen abzubilden, sind 3 Screens notwendig:
1. Hauptbildschirm mit der Timeline des Twitter-Accounts
2. Form für das Absenden eines Twitter-Status-Updates
3. Konfigurationsbildschirm für den Twitter-Account

Jedes WinForm besteht aus einer View-Klasse (dem WinForm), einem Model, welches als Singleton im IoC-Container konfiguriert wird und einem Presenter. Die einzelnen Funktionen in den Views sind im Beispielprojekt durch Tests abgedeckt und zeigen die notwendigen Tests für diese Art der Implementierung. Gerade durch geringen Funktionsumfang kann man das Muster der Verwendung gut erkennen.

In der MVP-Komponente befindet sich auch der “Inversion of Control”-Container, der die einzelnen Komponenten zusammenfügt. Dies könnte auch in einer extra Runner-Komponente ausgelagert sein.

Aufrufen eines weiteren WinForms

Alle Abhängigkeiten werden per Dependency-Injection-Container an den Presenter übergeben. Da das Hauptform alle weiteren Views und Presenter instanziert, müssten diese alle bereits beim Programmstart instanziert werden. Um dies zu verhindern, habe ich eine IPresenterFactory eingeführt, die zur Laufzeit weitere Presenter nachinstanzieren kann. Die Factory selbst hält eine Referenz auf den Container und wird bei Programmstart im Container hinzugefügt. Um sicherzustellen, dass weiterhin alle anderen Abhängigkeiten über den Konstruktor definiert werden, können aus dieser Factory nur Klassen instanziert werden, die IPresenter implementieren.

Fazit
Mit dieser Beispielanwendung kann man eine mögliche Implementierung von Model View Presenter in der Variante Supervising Controller sehen. Es ist also auch mit WinForms eine voll getestete MVP-Implementierung zu erstellen.

Anhang:
Kompletter Sourcecode der Beispielanwendung als ZIP

kick it on dotnet-kicks.de

Comments 3 Kommentare »

Wir haben wie viele von uns in der Webentwicklung vor vielen Jahren mit Scriptsprachen und mit prozeduralen – Spaghetti-Code ;) – angefangen. Mit der Zeit wuchs unsere Webpräsenz zu einer unüberschaubaren Anwendung mit manchen Seiten, die keiner von uns mehr anfassen wollte – aus Angst vor den Konsequenzen.

Um etwas Ordnung in die Webanwendungen zu bringen, haben wir also vor 4 Jahren angefangen, nach einem 3-Schichten-Modell zu entwickeln. Wir haben neue Funktionalitäten und neue Anwendungen nur noch so gebaut und wir waren für eine kurze Zeit zufrieden. Alles lief gut. Als wir den Umstieg auf .NET begonnen haben, haben wir weiterhin nach einem Mehr-Schichten-Modell gearbeitet, wir haben nur die Anzahl der Schichten erhöht.

Die Anwendungen wuchsen weiter, wir haben immer mehr Bereiche ausgelagert und diese hauptsächlich mit Webservices angesprochen. Währenddessen waren wir daran, unser Hauptprodukt, ein Portal für unseren Kunden mit der neuen Technologie entsprechend der alten Anforderung neu zu bauen. Und dann ist es passiert: ehe wir uns versahen, hatten wir ein riesiges Projekt, das alle mögliche Anwendungen eingebunden bzw. durch Webservices angesprochen hat. Die Grenzen waren fließend, eventuelle Änderungen an anderen Anwendungen konnten das Projekt unbuildbar machen, also ein ähnlicher Zustand wie vor paar Jahren zuvor.

Die Weiterentwicklung hat nicht nur in unserer Art zu Programmieren stattgefunden, wir selbst haben uns auch weiterentwickelt, wir haben die Community kennen gelernt. Bei den Open Space-Veranstaltungen haben wir Stefan und Ralf kennengelernt und durch sie eine andere Sichtweise der Dinge: die Modellierung einer Lösung durch Softwarezellen.

Wir haben sie zu uns eingeladen und uns die Idee erklären lassen. Das Stichwort heißt Holon. Wikipedia definiert ein Holon folgendermaßen:

Der Begriff Holon (von griech. ὅλος, hólos und ὀν, on „ganzes Seiendes“) wurde von Arthur Koestler geprägt und bedeutet ein Ganzes, das Teil eines anderen Ganzen ist. Es wird auch als “Ganzes/Teil” umschrieben.

Jede Anwendung ist ein Ganzes, die aus Teilen besteht, die ihrerseits auch als Ganze zu betrachten sind.

Seit dem Besuch von Ralf und Stefan haben wir uns die Artikelserie von Ralf von dotnetpro durchgelesen, die Webcasts (Teil 1, Teil 2) angeschaut und wir haben angefangen, diese Modellierung auszuprobieren.

Wir haben noch einen langen und interessanten Weg vor uns, aber eins ist jetzt schon sicher: wir werden versuchen unsere nächste Projekte durch Softzellen modellieren.

Solange die Komplexität nicht wieder die Überhand gewinnt ;)

kick it on dotnet-kicks.de

Comments 2 Kommentare »

Ich lese gerade das Buch Agile Principles, Patterns and Practices in C# from Robert C. Martin und Micah Martin. Dabei bin ich auf eine so tolle Metapher gestoßen, dass ich sie hier unbedingt niederschreiben wollte (die Übersetzung ist frei von mir):

Refaktorisierung ist, wie die Küche nach dem Abendessen aufzuräumen. Das erste Mal, wenn du das überspringst, bist mit der Kochen schneller fertig. Aber das Fehlen von sauberem Geschirr und sauberem Arbeitsplatz führt dazu, dass die Vorbereitung diesmal länger dauert. Am liebsten würdest du das Aufräumen wieder überspringen. Tatsache ist, dass du heute ohne das lästige Geschirrspülen wieder schneller fertig wärst. Aber der Schmutz wächst und wächst. Jedes Mal dauert es länger, das richtige Küchengerät zu finden, die vertrockneten Schmutzschichten vom Geschirr ab zu kratzen, und so weiter und so fort. Das Vorbereiten des Abendessens dauert ewig…
Das Überspringen der Abwasch macht das Kochen eigentlich nicht wirklich schneller.

Das Ziel von Refaktorisierung ist die Bereinigung des Codes, jeden Tag, jede Stunde, jede Minute. Wir wollen nicht den Code versauen. Wir wollen nicht ständig gezwungen zu sein, schmutzigen Bits und Bytes sauber zu schrubben. Wir wollen jeder Zeit in der Lage zu sein, unser System mühelos zu erweitern und zu verändern. Der wichtigste Faktor, der uns das möglich macht, ist die Sauberkeit des Codes.

Das Buch habe zwar noch nicht ganz durch, aber was ich bis jetzt gelesen habe, kann ich nur unterschreiben. Es beinhaltet die Prinzipien, wie man in einem agilen Team sauberen Code plant und Mustern und Beispiele, wie man ihn schreibt. Und wie ihr ja sieht, ist es in eine ganz tolle Art geschrieben :)

kick it on dotnet-kicks.de

Comments Keine Kommentare »

Wir setzen seit langer Zeit interne Tools mit WinForms um und hatten seit Anfang an Probleme bei der Testbarkeit dieser Anwendungen. Auch wenn man bei WinForms versucht, jeglichen Code aus der Codebehind-Datei zu entfernen, tut man sich mit dem Unit-Testing weiterhin schwer.

Auf der Suche nach einer Lösung zur besseren Testbarkeit stößt man immer wieder auf ein MVC- oder MVP-Modell, aber nirgends gibt es echte Beispiele in Verbindung mit WinForms. Ich möchte nun in einer Demo-Anwendung einen möglichen Ansatz zur Umsetzung des MVP-Patterns bei WinForms beschreiben.

Die einzelnen Bestandteile von MVP

Das Model repräsentiert den gesamten Zustand und die Logik der Ansicht. Das Model wird über den Presenter gefüllt. Die View enthält keinerlei Anwendungslogik, während der Presenter den Programmablauf steuert.

MVP gibt es in zwei Varianten – “Passive View” und “Supervising Controller”. Ich habe mich bei der Implementierung für “Supervising Controller” entschieden, da es auf den ersten Blick weniger Code erfordert. Der Unterschied von beiden Varianten besteht darin, dass bei “Passive View” die View weder Presenter noch Model kennt und als dumme View nur über den Presenter befüllt wird. Mir gefällt dabei jedoch nicht, dass der Presenter dabei die View genau kennen muss.

Bei “Supervising Controller” kennt nun jeweils die View als auch der Presenter das Model, darüber findet der Datenaustausch statt.

Die konkrete Implementierung

Der Presenter wird mit der View und dem Model instanziert.

10 public class MainPresenter : IMainPresenter

11 {

12 private readonly IMainView m_view;

13 private readonly IMainModel m_model;

14

15 public MainPresenter(IMainView view, IMainModel model)

16 {

17 m_view = view;

18 m_model = model;

19

20 InitializeModelAndRefreshView();

21 InitializeAndShowView();

Die View ist das WinForm und wird auch mit dem Model instanziert. Das Model selbst ist ein über den IoC-Container realisiertes Singleton.

10 public partial class MainView : Form, IMainView

11 {

12 private readonly IMainModel m_model;

13

14 public MainView(IMainModel model)

15 {

16 m_model = model;

17

18 InitializeComponent();

19 this.Closed += delegate { ViewClosed(this, new EventArgs()); };

Das Model beinhaltet nur Properties mit allen Daten, die zur Anzeige der View notwendig sind.

Wenn der Presenter Daten im Model ändert, ruft dieser explizit eine UpdateMethode in der View auf. Die View selbst stellt EventHandler zur Verfügung, auf die sich der Presenter hängt, um Aktionen auf der View weiter zu bearbeiten.

60 public event EventHandler<EventArgs> ViewClosed;

Im Presenter sieht dies folgendermaßen aus:

31 private void InitializeAndShowView()

32 {

33 m_view.Title = “ResourcerClient V1.0″;

34 m_view.ViewClosed += new EventHandler<EventArgs>(mainView_ViewClosed);

42 void mainView_ViewClosed(object sender, EventArgs e)

43 {

44 Application.Exit();

45 }

Damit ist die Grundlage des MVP Patterns bei WinForms angelegt. Der Presenter ist damit schon voll testbar, da er komplett von der View abgekoppelt ist. Bis jetzt sieht alles sehr einfach aus. Auch einige andere Beispiele aus dem Netz gehen soweit. Doch wie instanziert man jetzt eine weitere View bzw. einen weiteren Presenter?


Mehr dazu im zweiten Teil

kick it on dotnet-kicks.de

Comments 5 Kommentare »

Der vorherige DbC-Artikel ist ziemlich “abstrakt” ausgefallen, es haben einfach Beispiele gefehlt. Das möchte ich hiermit nachholen.

Erstens muss man die IDE anpassen: im März kommt .NET 4.0 raus und da wird Design by Contract mitgeliefert. Man kann das Konzept aber jetzt schon anwenden, wenn man die Assembly zusätzlich installiert. Danach muss man die dll referenzieren und im Eigenschaftenfenster des Projektes im neuen Tab Code Contracts das Runtime Checking einstellen.

Jetzt zum Code: Nehmen wir eine ganz einfache Klasse Bill deren Objekte mit einem IRepository gespeichert bzw. geladen werden.

    1 using System.Diagnostics.Contracts;

    2 namespace ContractsPrototyp

    3 {

    4     public class Bill

    5     {

    6         public int Id { get; set; }

    7         public string Number { get; set; }

    8         public double Value { get; set; }

    9     }

   10 

   11

   12     public interface IRepository

   13     {

   14         Bill GetBill(string number);

   15         void SaveBill(Bill bill);

   16     }

Die Kontrakte kann man in den einzelnen Methoden oder für eine ganze Klasse schreiben (unter dem Attribut ContractInvariantMethode) aber ich finde am schönsten, dass man die auch auslagern kann: durch eine gegenseitige Markierung können Kontrakt-Klassen und Interfaces als “Paare” definiert werden:

   11     [ContractClass(typeof(RepositoryContracts))]

   12     public interface IRepository

   13     {

   14         Bill GetBill(string number);

   15         void SaveBill(Bill bill);

   16     }

   17     [ContractClassFor(typeof(IRepository))]

   18     public class RepositoryContracts:IRepository

   19     {

   20         public Bill GetBill(string number)

   21         {

   22             Contract.Requires(!string.IsNullOrEmpty(number));

   23             return null;

   24         }

   25 

   26         public void SaveBill(Bill bill)

   27         {

   28             Contract.Ensures(bill.Id > 0);

   29         }

   30     }

Eine Vorbedingung wird mit Contract.Requires und eine Nachbedingung mit Contract.Ensures definiert. Beide Methoden bekommen boolische Ausdrücke. Diese Ausdrücke müssen frei von Seiteneffekten sein.

Die eigentliche Implementierung der Klasse schaut dann so aus:

   31     public class Repository:IRepository

   32     {

   33         public Bill GetBill(string nummer)

   34         {

   35             //Würde das Objekt aus Datenhaltung laden

   36             return new Bill();

   37         }

   38 

   39         public void SaveBill(Bill bill)

   40         {

   41             //Würde das Objekt speichern und ihm eine Id zuweisen

   42             if (BillIsValid( bill )) bill.Id++;

   43         }

   44 

   45         private static bool BillIsValid(Bill bill)

   46         {

   47             return !string.IsNullOrEmpty(bill.Nummer);

   48         }

   49     }

Woher können wir wissen, dass das funktioniert? Es ist einfach, wir schreiben ein Paar Tests dazu!
Bei Kontraktverletzung wird eine Exception geworfen. Um diese – und dadurch die genaue Verletzung – überprüfen zu können braucht man etwas Workaround:

   55     [TestFixture]

   56     public class BillTests

   57     {

   58         private IRepository m_repository;

   59         private string m_message;

   60 

   61         [SetUp]

   62         public void Setup()

   63         {

   64             m_repository = new Repository();

   65             m_message = string.Empty;

   66             Contract.ContractFailed += ( sender, e ) =>

   67             {

   68                 e.SetUnwind();

   69                 m_message = e.Message;

   70             };

   71         }

Danach sind die Tests dann einfach:

   73         [Test]

   74         public void Laden_mit_leerer_Nummer_verletzt_Kontrakt()

   75         {

   76 

   77             try

   78             {

   79                 m_repository.GetBill( null );

   80             }

   81             catch

   82             {

   83                 //Nichts

   84             }

   85 

   86             Assert.That( m_message, Is.EqualTo( "Precondition failed: !string.IsNullOrEmpty(number)" ) );

   87         }

   88 

   89         [Test]

   90         public void Speichern_Rechnung_ohne_Nummer_verletzt_Kontrakt()

   91         {

   92 

   93             try

   94             {

   95                 m_repository.SaveBill( new Bill{Value = 25} );

   96             }

   97             catch

   98             {

   99                 //Nichts

  100             }

  101 

  102             Assert.That( m_message, Is.EqualTo( "Postcondition failed: bill.Id > 0" ) );

  103         }

Ich hoffe, das Beispiel ist ausführlich genug, um die Vorteile von DbC zu highlighten. Stefan, vielen dank noch mal für den Artikel, ich habe mich natürlich von dir inspirieren lassen.

kick it on dotnet-kicks.de

Comments Keine Kommentare »

Endlich ist es geschafft. Ich habe das Buch “Clean Code” von Robert C. Martin a.k.a. Uncle Bob durchgelesen. Nach dem ersten Teil hier nun die versprochene Fortsetzung meiner Zusammenfassung:

10 Classes

Die erste Regel von Klassen lautet: Sie sollten klein sein.
Die zweite Regel von Klassen lautet: Sie sollten noch kleiner sein als das.

Klassen sollten eine hohe Kohäsion haben.
Kohäsion ist ein Maß dafür, wie stark die Methoden und Daten einer Klasse miteinander zu tun haben. Zur Verdeutlichung:
Eine Klasse, in der jede Membervariable von jeder Methode der Klasse verwendet wird, ist maximal kohäsiv.

Bei Klassen sollten folgende Prinzipien beachtet werden:

  • Das Single Responsibility Principle (SRP), welches besagt:
  • Eine Klasse oder ein Modul sollte nur einen Grund haben sich zu ändern. Eine Klasse sollte sich nur um EINE Sache kümmern.

  • Das Open Close Principle (OCP), welches besagt:
  • Klassen sollten offen für Erweiterungen sein, aber geschlossen für Modifikation.

  • Das Dependency Inversion Priniciple (DIP), welches besagt:
  • Klassen sollten von Abstraktionen abhängen und nicht von konkreten Klassen.

11 Systems

Separiere Konstruktion von Benutzung.
Realisiert werden kann das durch Dependency Injection.

Dependency Injection = Klassen bekommen ihre Abhängigkeiten von außen über den Konstruktor oder Setter übergeben. Dieses Pattern unterstützt das SRP, da sich die Klasse nicht mehr um das Instanzieren dieser Abhängigkeiten kümmern muss. Realisiert wird das ganze über Inversion of Control Container wie Windsor, Spring und wie sie alle heißen. Bei diesen Containern werden die Abhängigkeiten einmalig definiert, so dass man sich bei der Instanzierung nicht mehr darum kümmern muss.

Wenn Objekte zu einer bestimmten Zeit erstellt werden müssen, sollten Factories verwendet werden.

Systeme werden nicht von heute auf morgen gebaut. Sie werden nach und nach ausgebaut. Um sicherzustellen, dass dabei noch alles funktioniert, gibt es TDD, Refaktorisieren und Separation of Concerns.

12 Emergence

Viele Leute sagen, dass Kent Beck’s 4 “Rules of Simple Design” einem sehr helfen, gut designte Software zu erstellen.

Kent Beck sagt:
ein Design ist „simple“, wenn:

  • alle Tests durchlaufen
  • kein doppelter Code vorhanden ist
  • wenn es die Absicht des Programmierers ausdrückt
  • die Anzahl von Klassen und Methoden minimiert sind

in der Reihenfolge.

13 Concurrency

In Multithread-Anwendungen bekommt man schon bei minimaler Anforderung ein Problem mit der Komplexität. Da mit steigender Komplexität auch die Fehleranfälligkeit steigt, gibt es ein paar Prinzipien, die diese minimieren können:

Die Concurrency Defense Principles

  • Single Responsibility Principle
  • Trenne multithreaded Code von nicht-multithreaded Code

  • Limit the Scope of Data
  • Man sollte den Bereich, in dem multithreaded Code verwendet wird, möglichst klein halten.

  • Use Copies of Data
  • Verschiedene Threads sollten nicht mit demselben Objekt arbeiten. Wenn möglich sollte mit Kopien von diesem Objekt gearbeitet werden.

  • Independence
  • Threads sollten so unabhängig wie möglich sein

  • Library
  • Natürlich sollte man die Bibliothek, die man für Multithread-Anwendungen verwendet, sehr gut kennen.

14 Successive Refinement

Um Clean Code schreiben zu können, muss man erst Dirty Code schreiben und ihn dann bereinigen.

Einer der besten Wege, ein Programm zu ruinieren, ist, massive Änderungen an der Struktur vorzunehmen, um das Programm zu verbessern. Um das zu verhindern, nutzt man die Disziplinen von TDD. Eines der zentralen Doktrinen dieses Ansatzes ist es, das System zu jeder Zeit lauffähig zu halten. Mit TDD ist es also nicht erlaubt eine Veränderung am System vorzunehmen, die das System bricht.

15 JUnit Internals

JUnit Internals halt… (Kapitel überlesen)

16 Refactoring SerialDate

War mir eindeutig zu Java-lastig… (Kapitel überlesen)

17 Smells and Heuristics

In diesem Kapitel zeigt Uncle Bob eine Liste von Smells und wie man sie beseitigen kann. Er lobt das Buch “Refactoring” von Martin Fowler. Dieses Buch steht eh schon ganz oben auf meiner To-do-Liste. Das werde ich also demnächst angehen.

Zusammenfassung

An dieser Stelle ein Dank an mein Entwicklerteam, dass ich das Buch so lange in Beschlag nehmen durfte :) (Teil 2 ging irgendwie zäher). Einen großen Dank auch an Peter Bucher und Rene Drescher-Hackel für ihre Ergänzungen bzw. Einwände. Man darf sicherlich nicht alles so ganz ernst nehmen und man kann es auch übertreiben (siehe Pyramiden etc.). Natürlich sollte man nicht blind durch die Welt laufen, sondern auch Dinge hinterfragen, aber man muss sagen, dass die Punkte von CCD (das ja auf diesem Buch beruht) durchaus plausibel sind. Ich denke schon, dass CCD unerfahrenen aber auch erfahrenen Entwicklern einen SOLIDen Weg zeigt, den man gehen kann und der sogar schon gepflastert ist. Man kann sich natürlich auch mit der Machete durch dichten Dschungel schlagen, was natürlich cool ist :) – aber halt wesentlich langsamer. Es sei denn man ist Chuck Norris.

kick it on dotnet-kicks.de

Comments 1 Kommentar »

Seit Anfang des Jahres setzen wir nun SCRUM ein, wobei es, wie man jetzt merkt, doch nur SCRUMBUT war.

I call that phenomena “Scrumbut”. It shows up in the following way:
“We’re doing Scrum but…”
* our sprints are 12 weeks long…
* we do two normal sprints and one bugfix sprint…
* we do all our planning up front…
* we skip the daily meeting…
* our managers decide what’s in each sprint…
* we haven’t read the books yet…
* our team has 30 people…
http://blogs.msdn.com/ericgu/archive/2006/10/13/scrumbut.aspx

Auch bei uns wurden Anpassungen an SCRUM durchgeführt, was dazu geführt hat, dass die letzten Sprints immer schlechter wurden. Gerade die Retrospektive wurde fast nie durchgeführt, da es angeblich nichts zu besprechen gab.

Wir sind nun in Sprint 21 und nach 2 Open Spaces um ausreichenden Erfahrungsaustausch reicher. Wir halten wieder die Retrospektive-Meetings und bei dem letzten haben wir folgende Anpassungen beschlossen:

  • Es wurde eine “Definition-of-done” Richtlinie am Whiteboard erstellt.
  • Pair-Programming wird häufiger eingesetzt.
  • Zu jedem Backlog-Item werden gemeinsam die Architekturveränderungen und die notwendigen Tasks besprochen. Bisher wurde mit den Produkt-Backlogkarten direkt gearbeitet.

Ich rate allen, die SCRUM einführen wollen, sich wirklich so nah wie möglich an SCRUM zu halten. Die Sprints 1 – 15 wirkten bei uns auch sehr gut, doch erst danach fiel uns auf, dass gerade die Sprint-Retrospektive ein sehr wichtiges Meeting ist. All diese Regeln sind durch mehrjährige Erfahrungen entstanden und sie haben sich schon in größeren Firmen bewährt. Warum dann nicht davon profitieren?

kick it on dotnet-kicks.de

Comments 2 Kommentare »