Freitag, 26. August 2011

Continuations in C#–Mein Ansatz

Ralf Westphal hat unter http://ralfw.blogspot.com/2011/08/jenseits-von-solid.html einen interessanten Artikel zum Thema Continuations veröffentlicht. Leider hört Ralf auf, bevor er den entstandenen Code lesbar gemacht hat.

Ich denke, man kann Continuations textuell in Code darstellen. Beim Lesen des Artikels hatte ich folgende Syntax im Kopf:

Mein Beispiel ist analog zu dem von Ralf. Der einzige Unterschied ist, dass mein Beispiel die Validierung der Order an ein spezialisiertes Objekt delegiert wird.

Dieser Code erfordert im Prinzip nur folgende Methoden:

Beide Methoden geben das übergebene Objekt wieder zurück, so dass die Sequenzen prinzipiell beliebig lang sein können. Das Prinzip ist folgendes: Wenn das übergebene Objekt null ist, passiert nichts, ansonsten wird die Operation ausgeführt. Die Extensionmethode “When” erhält von der Operation zusätzlich einen bool zurück. Ist dieser false, wird an die folgende Operation null übergeben und die Bearbeitung der Sequenz faktisch abgebrochen.

Allerdings kann man den Code noch ausbauen. Das werde ich in den nächsten Posts tun.

Der Code, dem dieser Post zugrunde liegt, befindet sich unter https://github.com/mzywitza/Monastry.Continuations/blob/Post_1/src/Monastry.Continuations.Tests/Class1.cs. Es ist nicht nötig, das komplette Repository zu klonen, da ich UppercuT verwende und das Projekt daher etwas größer ist. Zudem befindet sich der Code (noch) in komplett in der verlinkten Datei.

Freitag, 24. Juli 2009

CCD Reflektion – Roter Grad Tag 4

Gestern kam ich endlich wieder zum Programmieren; und das sowohl beruflich als auch privat.

Bei meinem derzeitigen beruflichen Projekt, der Erweiterung eines vor Jahren von mir erstellten Reporting Tools, konnte ich meine ersten “richtigen” Erfahrungen mit LINQ sammeln und habe dadurch den Input zum heutigen Post erhalten.

Eigentlich beginnt es damit, dass ich den Gedanken, meine vorhandene Datenbankstruktur mit NHibernate zu mappen, aufgegeben habe. Einerseits stand da Zeitdruck dahinter, da ich gewisse Meilensteine zügig erreichen muss, zum Andern musste ich erkennen, dass ich bei einem vollständigen DB-Schema fast zwangsläufig in einem “anemic model” Ende, dass lediglich eine DTO-Schicht über der Datenbank darstellt.

Also habe ich die Umstellung auf ein ORM verschoben. Mittelfristig muss das Modell sowieso komplett umgebaut werden und das ist der geeignete Zeitpunkt, ein Klassenmodell als Ursprung aller Modelle zu verwenden.

Bis dahin muss ich aber trotzdem auf die Daten zugreifen. Ursprünglich hatte ich den Datenzugriff über DataSets realisiert, aber genau diesen Ansatz will ich ablösen. Nacktes ADO.NET (DataReader und Commands) will mir auch nicht recht gefallen, also habe ich alle Tabellen mit Hilfe des VS-Designers in Linq2Sql erstellt.

Vom Ergebnis bin ich hin und her gerissen. Der Code, den auf Basis diesen Ansatzes erstellen konnte, ist kurz und gut lesbar. Beim Bereitstellen der Daten für das Reporting ist der Abgleich von Daten aus verschiedenen Quellen eine Hauptanforderung und Linq2Objects liefert hier mächtige Werkzeuge an die Hand.

Andererseits ist die Vermengung von Linq2Objects und Linq2Sql wiederum sehr komplex und durch die Kopplung an die Datenbank fast unmöglich isoliert zu testen.

Was ist also mein Fazit zu Linq? Linq2Objects ist sehr mächtig und erlaubt effektiv funktionales Programmieren in C#.

Auf Datenbanken werde ich mit Linq in Zukunft aber nur sehr isoliert zugreifen. Hier meine ich vor allem den Ansatz, Repositories zu benutzen, damit es möglich ist, den Datenzugriff in Tests durch Stubs oder Mocks zu simulieren.

Dienstag, 21. Juli 2009

CCD Status

Vielleicht lesen einige dieses Blog und fragen sich, ob ich nicht mehr über CCD blogge…

Tatsache ist, dass ich gestern und heute nicht zum Programmieren kam. Andere Prioritäten haben Vorrang, also momentan kein Development und kein CCD.

Freitag, 17. Juli 2009

CCD Reflektion – Roter Grad Tag 3

Mein Arbeitstag war heute relativ ruhig, aber auf der Heimfahrt habe ich noch einen Issue von ActiveRecord abgearbeitet. Dabei bin ich auf die Grenzen der Prinzipien gestoßen.

Es geht um diesen Code:

if (model.HasManyAtt.RelationType == RelationType.Map && model.HasManyAtt.Index == null)


{


    throw new ActiveRecordException(String.Format(


                                        "A HasMany with type Map requires that you specify an 'Index', use the Index property {0}.{1}  ",


                                        model.Property.DeclaringType.Name, model.Property.Name));


}


 


if (model.HasManyAtt.RelationType == RelationType.List && model.HasManyAtt.Index == null)


{


    throw new ActiveRecordException(String.Format(


                                        "A HasMany with type List requires that you specify an 'Index', use the Index property {0}.{1}  ",


                                        model.Property.DeclaringType.Name, model.Property.Name));


}



Das erste if-Statement war bereits vorhanden, dass zweite ist durch Copy/Paste entstanden. Ich war nun wirklich im Zweifel, ob ich nicht eine private Methode extrahieren soll.



Ich habe mich dagegen entschieden. Es handelt sich um zwei Statements, die ich durch einen Aufruf ersetzen könnte, und dass auch nur, wenn ich die Prüfung in einer Lambda-Expression vornehmen. Da die Klasse sowieso über 20 Methoden hat, hätte die Auslagerung die Lesbarkeit eher verringert als erhöht.



Also habe ich heute gegen DRY verstoßen und (meiner Meinung nach) trotzdem richtig gehandelt.



Ach ja, mein virtuelles Armband trage ich immer noch rechts und habe einen Issue für das Refaktorisieren der semantischen Prüfungen eröffnet.

CCD Reflektion – Roter Grad Tag 2

Dieser Bericht kommt etwas später, da ich gestern keine Zeit hatte, einen Post zu verfassen. Die Reflektion habe ich schon durchgeführt, nur eben ohne Keyboard unter den Fingern.

Zunächst hatte ich mir nur vorgenommen, meine Commitrate weiterhin hoch zu halten, aber im Laufe des Tages wurde DRY ein Thema. Meine Haupttätigkeit war das Erstellen eines Modells für die Persistenz mit NHibernate.

Das hört sich zunächst nach einer relativ schwierigen Tätigkeit an, um DRY zu verletzen. Wäre es auch, wenn da nicht die Tests wären: Ich teste jede Klasse grundsätzlich, ob alle (halb-)öffentlichen (public und protected) Properties persistiert werden, um auszuschließen, dass eine Property beim Mapping vergessen wurde.

Diese Tests gleichen sich bei den Klassen strukturell sehr stark:

  1. Objekt erzeugen
  2. Objekt persistieren
  3. Id auslesen
  4. Objekt aus Session-Cache entfernen
  5. Objekt mit Id erneut laden
  6. Die Objekte Property für Property per Reflection vergleichen

Bei der ersten Klasse habe ich das so geschrieben, bei der zweiten kopiert, gepastet und … nachgedacht: Da war doch was. So schnell kann man in die Clipboard-Falle gehen.

Also habe ich den Test in eine generische, abstrakte Basisklasse ausgelagert. Die einzige Operation, die bei jeder gemappten Klasse unterschiedlich ist, ist das Erzeugen des zu speichernden Objekts. Aber dafür gibt es schließlich abstrakte Methoden.

Was habe ich dadurch gewonnen? Schließlich ist es nur Testcode… ;-)

Spass beiseite, ich bin der Meinung, dass auch auf Testcode die ganze Breitseite von Clean-Code-Techniken angewandt werden muss. Schließlich sind zumindest bis zur Produktivnahme die Tests der am häufigsten ausgeführte Code der Anwendung.

Zumindest wenn man TDD und CI verwendet…

Mittwoch, 15. Juli 2009

CCD Reflektion – Roter Grad Tag 1

Wie in meinem vorherigen Post versprochen, habe ich mir ein virtuelles rotes Armband übergestreift und begonnen, bewusst auf die Einhaltung der CCD-Prinzipien zu achten. Allerdings nicht nach dem Gießkannenprinzip; dafür sind mir die meisten Techniken und Ideale bereits zu sehr in Fleisch und Blut übergegangen. Stattdessen habe ich mir einen einzelnen Punkt ausgesucht, den ich am heutigen Tag besonders beachtet habe: Die Nutzung des Versionskontrollsystems.

Ich nutze ausschließlich Subversion, also ein zentrales VCS. Mit der Zeit habe ich das regelmäßige Committen immer mehr schleifen lassen. Die Ursache kann ich nur erraten, aber ich denke, dass es mit meiner Arbeit am Castle-Projekt zu tun hat. Ich mache diese Arbeit fast immer offline und kann daher nur selten meine Änderungen committen. Dazu kommt, dass der Castle-Build auf meinem Laptop mehr als 10 Minuten dauert.

Das hat sich auf meine Arbeit übertragen, wo ich diese Probleme eigentlich nicht habe. Dennoch kam ich dort auch nur auf im Schnitt 2 Commits im Monat. Also höchste Zeit, aus dem Trott herauszukommen.

Mein Ziel war also, nicht nach jedem neuen Feature/User-Story, sondern (viel) öfter zu committen. Obgleich ich es (eigentlich) übertrieben finde, habe ich heute also nach jedem TDD-Zyklus committed.

Warum so oft? Damit der Commit genauso natürlich wird wie das Starten der Unit Tests, des lokalen Builds und das Holen von Kaffee. Nach unten wird sich die Commitrate wahrscheinlich von alleine regulieren. Und wenn nicht, ist es auch nicht schlimm… :-)

Fazit .Net OpenSpace Süd 2009

Letztes Wochenende war der .Net OpenSpace Süd in Blaustein bei Ulm. Es war mein erster OpenSpace überhaupt und ich fand es klasse, auch wenn es zu wenig Schlaf gab…

Zu den Slots, die ich besucht habe, gibt es noch ein paar Dinge zu ergänzen, was ich in den nächsten Wochen hier tun werde.

Ansonsten werde ich schauen, wann es wieder Events gibt. Leipzig wohl eher nicht, sondern kleinere Treffen, vielleicht in Köln oder Frankfurt.

Halt: Was ist denn nun mein Fazit?

Hmm…am ehesten, dass auch die “Community-Helden*” nur mit Wasser kochen. Wenn man sich das vor Augen hält und immer neuen Input sucht, kann man auch diesen Level erreichen.

*u. a. Stefan und Albert und die ganzen MVPs