Softwareentwicklung ist Wissensarbeit. Dieser Umstand wird jedem schnell bewusst, der sich mit der Materie auseinandersetzt. Wer in diesem Bereich arbeitet beziehungsweise arbeiten möchte, ist auf Wissen angewiesen. Ganz gleich, ob die Arbeit auf professioneller Basis oder rein zum Vergnügen als Hobby betrieben wird.
Dieses Wissen wächst im Laufe der Zeit. Ganz logisch. Eine Ausbildung kann die Grundlage sein. Erfahrung ist in jedem Fall eine stete Erweiterung dessen, was wir zu wissen glauben. Das trifft natürlich nicht nur auf den Bereich der Softwareentwicklung zu. Dazu ist es häufig Gold wert, sich Wissen durch den Austausch mit anderen oder durch Artikel, Blogposts oder aus sonstigen Quellen anzueignen. Beispielsweise auf Konferenzen, in Fachzeitschriften oder Blogs.
Den Überblick behalten
Denn in der Softwareentwicklung, beziehungsweise der IT Branche im Allgemein, ist es sehr schwierig und aufwändig, den Überblick zu behalten. Neue Technologien entstehen fast wöchentlich. Ebenso häufig verschwinden vorhandene Techniken und Technologien auch wieder. Das Problem an der Sache ist, dass es sehr schwierig ist, sich sicher zu sein, eine Aufgabe bestmöglich zu lösen oder gelöst zu haben.
Hier ist nicht nach absoluter Perfektion gefragt. Ganz im Gegenteil. Aber jeder, der mit Quelltext zu tun hat oder ihn gar selbst schreibt, fragt sich des Öfteren, ob dieser gut ist. Zum einen kann das über Qualitätskriterien verschiedener Art sichergestellt werden. Sogenannte Metriken und methodische Vorgehensweise. Eine andere Möglichkeit kann aber im Einsatz von Bibliotheken liegen.
Diese sind selbstverständlich nicht der Weisheit letzter Schluss. Fügen Bibliotheken doch Abhängigkeiten und möglicherweise zusätzliche Fehler zum eigenen Code hinzu. Gute Bibliotheken haben allerdings einige Qualitätskriterien, die vor einem Einsatz geprüft werden können. Sie sind beispielsweise häufig im Einsatz, daher erprobt und haben eine große Community hinter sich. Das reduziert nicht nur die eventuell vorhandenen Fehler, sondern kann auch dazu beitragen, dass Fehler schneller erkannt, nachvollzogen und behoben werden.
Bibliotheken dieser Art sind sehr wertvoll für die eigenen Entwicklungsprojekte. Sie verhindern, dass das Rad immer wieder aufs Neue erfunden werden muss. Also wieder ein Problem weniger auf der eigenen To-Do-Liste.
Gute Bibliotheken zu finden ist eine Sache für sich. Die bereits angesprochenen Fachzeitschriften, Blogs und insbesondere Konferenzen sind ein guter Anlauf- und Startpunkt für die Suche. Eine Empfehlung ist in diesem Fall viel wert, weil sich schon andere mit der Materie auseinander gesetzt haben und so Tipps und Tricks verraten können, die selten in der Dokumentation der Bibliothek zu finden sind.
Ich möchte in diesem Gastbeitrag aber nicht nur darüber schreiben, dass Bibliotheken generell helfen können, sondern auch einen kleinen Auszug dessen vorstellen, was sich bei mir im Laufe der Jahre an guten Bibliotheken angesammelt hat. Da die Liste nahezu unendlich fortgeführt werden kann, möchte ich gerne drei Vertreter verschiedenster Kategorien kurz vorstellen.
AutoMapper
Den Anfang macht eine Bibliothek Namens AutoMapper [1]. Der Name verrät auf den ersten Blick, dass etwas automatisch geschehen soll und dass es sich dabei um ein Mapping handelt. Damit ist eine Abbildung gemeint, die auch in Form einer Transformation erfolgen kann. In diesem Fall ist das konkret eine Abbildung von einem Objekt auf ein anderes. Dieses Mapping kommt sehr häufig zum Einsatz.
Das ist sehr aufwändig und kann mitunter schnell in viel Aufwand ausarten. Besonders bei komplexen Objekten und gar Objekthierarchien. Werden dann auch noch, im Laufe der Entwicklung, Änderungen an den aufeinander abgebildeten Objekten vorgenommen, muss der Mapping-Code manuell nachgearbeitet werden. Das ist mühselig, zeitaufwändig, langweilig und damit fehleranfällig.
AutoMapper vereinfacht das deutlich. Viele Eigenschaften von Objekten werden automatisch aufeinander abgebildet. Beispielsweise weil sie gleich heißen oder einem Namensschemata entsprechen. Grundsätzlich gilt, dass AutoMapper alles aufeinander abbildet, was diesen Regeln entspricht. Auch bei Methoden. Heißt eine Methode wie eine Eigenschaft, eventuell mit einem Präfix Get davor, wird auch diese Abbildung vorgenommen. Die Methode sorgt in diesem Fall für den Wert der Eigenschaft, in dem sie von AutoMapper ausgeführt wird. Diese Abbildungsregeln gelten auch für Vererbungen oder Objektlisten. Der folgende Code-Ausschnitt bildet beispielsweise ObjektA auf ObjektB ab. Mit allen Eigenschaften und Methoden, die den integrierten Regeln entsprechen.
Mapper.CreateMap<ObjektA, ObjektB>();
// ObjektA => ObjektB
var objektB = Mapper.Map<ObjektA, ObjektB>(objektA);
Zuerst wird über CreateMap ein Mapping erzeugt, dass dann hinterher durchgeführt wird.
Das Schöne an der Bibliothek ist, dass nur Ausnahmen explizit über ein API angegeben werden müssen. Der Vorteil ist, dass diese Ausnahmen, so zumindest die Regel, deutlich seltener vorkommen als gewünschte Abbildungen. Auch das spart Aufwand. Zudem können diese Abbildungsregeln in Profilen hinterlegt werden, um diese auf diese Weise dynamisch zur Laufzeit auswählen und laden zu können. Beim Thema Mapping kann ich daher nur empfehlen, einen Blick auf AutoMapper zu werfen. Das nachfolgende Listing zeigt, wie so eine Ausnahme im Code konfiguriert werden kann.
Mapper.CreateMap<ObjektA, ObjektB>()
.ForMember(dest => dest.Name, src => src.Ignore())
Diese Art der Konfiguration, die über ein sogenanntes Fluent Interface durchführbar ist, findet sich überall bei AutoMapper wieder. In diesem Fall wird die Eigenschaft Name von ObjektB bei der Quelle, nämlich ObjektA, ignoriert. Es findet somit keine Abbildung statt. Auf diese Weise können alle Ausnahme und besonderen Regeln definiert werden.
Noda Time
Noda Time [2] kommt ursprünglich aus der Java-Welt. Dort heißt es allerdings Joda Time. Der erste Buchstabe gibt also einen Hinweis auf die verwendete Plattform .NET oder Java. Das wird bei der Namensgebung gerne gemacht.
Die Bibliothek hat sich zur Aufgabe gemacht, den Umgang mit Datums- und Zeitangaben im .NET Framework zu vereinfachen. Letzteres bietet lediglich die drei Typen DateTime, DateTimeOffset und TimeSpan an, um mit Zeitinformationen umzugehen. Das ist recht wenig und kann, um verschiedene Konzepte voneinander zu trennen, besser umgesetzt werden. Ein erster, konzeptioneller Unterschied zwischen Noda Time und den Datumsfunktionen, die bereits im .NET Framework vorhanden sind, ist die Trennung von Datums- und Zeitangaben. Für alles gibt es einen eigenen Typ. Die können, bei Bedarf und wenn es konzeptionell möglich ist, ineinander überführt werden. Der Vorteil ist die Spezialisierung. Ist nur eine Zeitangabe notwendig, müssen auch nur die dafür notwendigen Informationen in einem Datentyp vorhanden sein. Datum und eventuell auch ein Kalender sind zunächst nicht relevant.
Der größte, konzeptionelle Unterschied von Noda Time ist allerdings die Unterscheidung von „Meiner“ und „unserer“ Zeit.
Mit letzterem ist die globale Zeit gemeint, die weitläufig auch gerne als absolute Zeit benannt wird. Diese Zeit gilt weltweit. Beispielsweise ein fixer Punkt auf einer Zeitskala. Völlig unabhängig von Ort, Zeitzone oder Kalender. Mit „meiner“ Zeit ist die lokale Zeit, bezogen auf einen Betrachter, gemeint. Diese hat eine Zeitzone und einen Kalender. Denn eine bestimmte Uhrzeit an einem bestimmten Tag ist nur für eine konkrete Zeitzone gültig. Das Code-Fragment zeigt, wie eine Zeitzone über Noda Time ermittelt werden kann. In diesem Fall Europe/Berlin. Anschließend kann die Uhrzeit, die in dieser Zeitzone gilt, abgefragt werden.
var zone = DateTimeZoneProviders.Tzdb[„Europe/Berlin“];
var now = SystemClock.Instance.Now;
Console.WriteLine(„It is now {0}.“, now);
Console.WriteLine(„In Berlin, that’s {0}.“, now.InZone(zone));
Daneben bietet Noda Time noch eine gute Unterstützung für Zeitpunkte, Kalendersysteme, Zeitspannen und Arithmetik an. Hantiert eine Anwendung viel mit Zeitangaben, lohnt sich ein Blick auf Noda Time allemal. Eventuell ist viel eigener Code durch die Bibliothek ersetzbar.
DotNetZip
Als letzte Bibliothek im Bunde möchte ich DotNetZip vorstellen. Dabei handelt es sich, wie der Name vielleicht vermuten lässt, um eine Bibliothek für zip-Archive. Archive an sich, erst einmal völlig unabhängig vom verwendeten Format, sind längst in der Praxis angekommen. Da sie, in der Regel, komprimiert sind, ist der eingesparte Platzbedarf einer der Hauptgründe. Im Rahmen einer Anwendung kommen Archive aber auch gerne als Ressource oder auch einfach nur für den Versand in Frage. Denn das Handling von einem Archiv, statt dutzender Dateien, ist deutlich einfacher.
Bei der Arbeit mit Archiven stellt sich schnell die Frage nach der Kompatibilität. Ist das Archiv nur von einer bestimmten Bibliothek lesbar, ist das mitunter ein schwerwiegender Nachteil, der selten in Kauf genommen wird. Das hat auch nichts mit Sicherheit zu tun. Die wird nur durch eine ordentliche Verschlüsselung erreicht. Sehr erfreulich ist, dass DotNetZip das Zip-Archivformat unterstützt, dass bereits 1989 spezifiziert wurde. Seither wurden an dieser Spezifikation zwar viele Änderungen vorgenommen, von denen, beispielsweise ein 64 bit-Format und Unicode, DotNetZip aber auch unterstützt. Das macht zip-Archive, die durch die Bibliothek erstellt wurden, in welchen externen Programmen wie WinZip, lesbar. Und das plattformunabhängig unter Windows, Mac OS X und Linux.
DotNetZip ermöglicht es, einzelne Dateien oder ganze Verzeichnis, gerne auch rekursiv, zu einem Archiv hinzuzufügen. Das folgende Listing zeigt diesen Fall an einem Beispiel.
using (var zip = new ZipFile())
{
zip.AddDirectory(„Rechnungen“, “ Dateien“);
zip.Save(„Rechnungen.zip“);
}
Erzeugt wird die zip-Datei Rechnungen.zip. Diese enthält das gesamte Verzeichnis Dateien, das beispielsweise auf der lokalen Festplatte vorhanden ist. Im Archiv selber heißt das Verzeichnis allerdings Rechnungen. Der Verzeichnisname für das Ziel und die Quelle müssen nicht identisch sein.
Komfortabel ist auch der selektive Zugriff auf Dateien und die Möglichkeit, diese zu ändern. Es ist somit nicht erforderlich, dass immer das vollständige Archiv entpackt, geändert und wieder gepackt wird. Bibliotheken, die so vorgehen, kommen bei größeren Archiven häufig ins Straucheln, da diese Vorgänge einfach zu lange dauern. So einen möglichen Fall enthält das nachfolgende Listing.
using (var zip = new ZipFile(„Rechnungen.zip“))
{
zip.RemoveEntry(„Rechnungen/August-2014.pdf“);
zip.RemoveSelectedEntries(„*.docx“);
zip.Save();
}
Basis ist die Datei Rechnungen.zip. Zunächst wird eine einzelne Datei, in diesem Fall eine PDF-Datei mit einer beispielhaften August Rechnung aus dem Jahr 2014 gelöscht. Anschließend entfernt der Code aber auch alle Word-Dateien mit der Endung .docx. Nach dem Speichern enthält das zip-Archiv die angegebenen Dateien weniger und ist entsprechend kleiner vom Umfang her.
Weitere Features von DotNetZip sind ein Passwortschutz für Dateien, Verzeichnisse und Archive, die Möglichkeit zur Verschlüsselung, Kommentare zu archivierten Dateien und das Aufteilen von Archiven. Mit letzteren Feature ist auch der Umgang mit großen Datenmengen möglich.
Benötigt eine Anwendung eine Archivfunktion oder müssen fremde Archive gelesen werden, schickt sich DotNetZip an, diese Aufgabe schnell, unkompliziert und komfortabel zu lösen.
Fazit
Ich hoffe, ich konnte Ihnen mit diesem kleinen Überblick beziehungsweise Einblick weiterhelfen. Bibliotheken gibt es wie Sand am Meer. Große, kleine, komplexe, einfache, nützliche und weniger nützliche. Die Eigenschaften ergeben aber immer erst dann Sinn, wenn sie in Verbindung mit einem Problem und mit einem möglichen Ziel gesehen werden. Für den einen ist eine Bibliothek nutzlos, ein anderer suchte schon eine halbe Ewigkeit danach.
Eine ganze Serie über nützliche Bibliotheken aus dem .NET Universum schreibe ich für die dotnetpro [4] unter der Rubrik „Frameworks und mehr“ [5].
Quellen
[1]: Projektseite zu AutoMapper
http://automapper.org
[2]: Webseite zu Noda Time
http://nodatime.org
[3]: DotNetZip auf CodePlex
http://dotnetzip.codeplex.com
[4]: dotnetpro Autor Fabian Deitelhoff
http://www.dotnetpro.de/articles/author1452.aspx
[5]: Rubrik “Frameworks” im Blog von Fabian Deitelhoff
http://www.fabiandeitelhoff.de/publikationen/dotnetpro/rubrik-frameworks/
Der Autor
Fabian Deitelhoff lebt und arbeitet in Dortmund, der Metropole des Ruhrgebiets. Beruflich ist er als freier Autor, Pluralsight-Autor, Sprecher und Softwareentwickler im .NET Umfeld tätig. Sie erreichen Ihn über www.fabiandeitelhoff.de, Fabian@FabianDeitelhoff.de oder als @FDeitelhoff.
Schreiben Sie einen Kommentar