Archiv

Archive for Juli 2012

5 Bücher die jeder Software-Entwickler kennen sollte

30. Juli 2012 3 Kommentare

Ich werde immer mal wieder nach Buchempfehlungen gefragt. Passende Tipps zu geben ist nicht einfach, da je nach Arbeitsgebiet und Vorwissen ganz unterschiedliche Themen im Blickpunkt stehen. Es gibt aber einige Bücher die ich immer wieder empfehlen kann. Die darin behandelten Themen sind nicht technologiespezifisch sondern behandeln wichtige Konzepte und Techniken. Die 5 Bücher die ich hier nenne ergänzen sich, bieten aber auch für sich alleine einen Mehrwert.

Hinweis: Seit Januar 2014 gibt es hier eine aktualisierte Liste mit noch besseren Büchern.

 

Refactoring

Trotz seines Alters ist Refactoring nach wie vor das Standardwerk zur Restrukturierung von Code. Der ausführliche Katalog mit Strategien zur Verbesserung der Codebasis ist aus meinem täglichen Entwicklerleben nicht wegzudenken.

Dies bedeutet keinesfalls dass ich alle darin vorgestellten Methoden auswendig kenne. Aber Refactorings wie das umbenennen von Variablen oder das Extrahieren von Methoden sind Dinge die jeder beherrschen sollte. Diese sind sehr einfachen und verbessern den Code doch enorm.
(ISBN: 978-0-201-48567-7 | detaillierte Rezension)

 
 

The Art of Unit Testing

The Art of Unit TestingRoy Osherove liefert das aus meiner Sicht bisher beste Buch über Unit Testing. Es gibt viele Bücher die gut sind, seine Erklärung von komplexeren Themen wie dem Mocken von Abhängigkeiten ist aber immer noch unerreicht.

Das Buch bietet viele praxisrelevante Beispiele die zeigen wie man auch komplexere Bereiche testen kann. Gerade diese Teile sind in der Praxis meist der Grund weshalb man den Vorsatz Unit Tests zu schreiben aufgibt. Wie bei allem gilt aber auch hier, dass man selber denken muss und Tipps auch kritisch hinterfragen soll.
(ISBN: 978-1-933988-27-6 | detaillierte Rezension)

 

Dependency Injection in .Net

Wendet man Unit Tests konsequent an wird der Code oft modularer. Um diese schön getrennten Teile zu einer Anwendung kombinieren zu können fallen schnell einmal die Begriffe Dependency Injection und Inversion of Control. Das Buch von Mark Seemann liefert einem eine sehr gute Einführung und auch das nötige Hintergrundwissen um eine praxistaugliche Anwendung aufzubauen.

Mir gefällt daran das nicht nur gezeigt wird worauf man achten muss sondern auch wie man merkt dass man auf dem falschen Weg ist.
(ISBN: 978-1-935182-50-4 | detaillierte Rezension)

 
 

Clean Code

Unit Tests, Refactorings und Dependency Injection sind Techniken die den Code sauberer machen. Wenn einem diese Richtung gefällt ist Clean Code von Robert C. Martin der nächste Schritt.

Sein Buch geht den Weg weiter und verbindet verschiedenste Erkenntnisse in der Software-Entwicklung der letzten Jahre zu einem Ganzen. Bei Clean Code ist es aus meiner Sicht aber besonders wichtig das man das Ziel bei all den Regeln nicht aus den Augen verliert. Verständlicher Code sollte immer vor einer in Stein gemeisselten maximalen Anzahl Zeilen für eine Methode gehen.
(ISBN: 978-0-13-235088-4 | detaillierte Rezension)

 
 

Debug It

Trotz Unit Tests wird man immer mal wieder vor einem Bug stehen. Wer gerne alternativen zu mehrstündigen Einsätzen des Debuggers hätte sollte sich dieses Buch anschauen. Paul Butcher liefert mit seinem Buch viele Tipps und Tricks damit man bei der Bugbeseitigung nicht nur im Dunkeln herum stochert.

Das Buch zeigt was die wesentlichen Schritte der Fehlerbehebung sind und worauf man nicht verzichten darf. Ein beherzigen dieser Vorschläge kann einem Stunden bei der Fehlersuche ersparen.
(ISBN: 978-1-9343-5628-9 | detaillierte Rezension)

 
 

Soweit meine Liste von Büchern die ich als „Must-Read“ bezeichne. Ich würde mich freuen zu erfahren was andere Entwickler als unverzichtbare Bücher auflisten.

 

Weniger Code dank AutoMapper

17. Juli 2012 Kommentare aus

AutoMapper ist ein einfach zu verwendender Objekt-Objekt Mapper. Wer mehr als einmal ein Geschäftsobjekt auf ein DTO oder Viewmodel abbilden musste dachte sich wohl: Warum muss ich diesen Code selber schreiben? Mit AutoMapper gibt es genau dafür eine Lösung.

 

Installation

Wie bei fast allen Bibliotheken kann man auch hier wieder NuGet zur Installation verwenden. Wer die Package Manager Konsole der GUI-Anwendung vorzieht bekommt AutoMapper mit diesem Befehl:

PM> Install-Package AutoMapper

 

Ausgangslage mit ganz einfachen Daten

Als Beispiel für den manuellen Weg wie man ein Objekt auf ein anderes überträgt dienen uns die beiden Klassen Basic und BasicDto:

public class Basic
{
    public string A { get; set; }
    public string B { get; set; }
    public string C { get; set; }
}

public class BasicDto
{
    public string A { get; set; }
    public string B { get; set; }
}

private readonly Basic basic = new Basic() { A = "[A]", B = "[B]", C = "[C]" };

Bisher werden die meisten Entwickler wohl einen Code geschrieben haben der diesem hier sehr ähnlich ist:

[TestMethod]
public void MappingTheOldWay()
{
    BasicDto dto = new BasicDto();
    dto.A = basic.A;
    dto.B = basic.B;

    Assert.AreEqual("[A]", dto.A);
    Assert.AreEqual("[B]", dto.B);
}

Mit AutoMapper muss man erst ein Mapping definieren und danach das gewünschte Ausgangsobjekt übergeben:

[TestMethod]
public void MappingSimpleObjectWithAutomapper()
{
    Mapper.CreateMap<Basic, BasicDto>();

    BasicDto dto = Mapper.Map<Basic, BasicDto>(basic);

    Assert.AreEqual("[A]", dto.A);
    Assert.AreEqual("[B]", dto.B);
}

So lange man nur wenige Werte übertragen muss ist ein Helfer wie AutoMapper zugegebenermassen kein grosser Gewinn. Anders sieht es aus wenn die Objekte komplexer und umfangreicher werden.

 

Nicht alle Werte automatisch übernehmen

Per Konvention werden automatisch alle Werte übernommen bei denen im Ausgangs- und im Zielobjekt ein Feld mit gleichem Namen existiert. Will man dieses Verhalten ändern kann man AutoMapper sehr einfach anpassen:

[TestMethod]
public void MappingNotAllValues()
{
    Mapper.CreateMap<Basic, BasicDto>()
        .ForMember(dest => dest.B, opt => opt.Ignore());

    BasicDto dto = Mapper.Map<Basic, BasicDto>(basic);

    Assert.AreEqual("[A]", dto.A);
    Assert.IsNull(dto.B);
}

Mit dest wir hier das Zielobjekt (Destination) referenziert und für das Property B eine entsprechende Option (opt) gesetzt. Die Bezeichner „dest“ und „opt“ kann man nach Belieben umbenennen. Ich halte mich hier an die im Wiki verwendeten Namen.

 

Werte verändern

AutoMapper lässt einem Werte nicht nur direkt übernehmen, sondern erlaubt einem auch diese nach Belieben zu verändern:

[TestMethod]
public void MappingModifyValues()
{
    Mapper.CreateMap<Basic, BasicDto>()
        .ForMember(dest => dest.A, 
            opt => opt.MapFrom(src => String.Format("{0} {1}", src.A, src.C)));

    BasicDto dto = Mapper.Map<Basic, BasicDto>(basic);

    Assert.AreEqual("[A] [C]", dto.A);
    Assert.AreEqual("[B]", dto.B);
}

Wie viel Funktionalität man in ein Mapping stecken will sollte man sich aber gut überlegen. Bei zu vielen Sonderfällen hat man immer noch die Möglichkeit selber den passenden Code zu schreiben und für diesen Fall auf AutoMapper zu verzichten.

 

Verschachtelte Objekte

Richtig interessant wird es wenn das Ausgangsobjekt aus mehreren Objekten besteht. Benennt man die Felder im Zielobjekt nach dem Muster KlassennameFeldname übernimmt AutoMapper wiederum die ganze Arbeit:

public class Customer
{
    public string LastName { get; set; }
    public string FirstName { get; set; }
    public int Number { get; set; }
    public Address Address { get; set; }
}

public class Address
{
    public string Street { get; set; }
    public int Zip { get; set; }
    public string Place { get; set; }
    public string Country { get; set; }
}

public class CustomerDto
{
    public string LastName { get; set; }
    public string FirstName { get; set; }
    public string AddressStreet { get; set; }
    public int AddressZip { get; set; }
    public string AddressPlace { get; set; }
    public string NotMapped { get; set; }
}

[TestMethod]
public void MappingComplexObjects()
{
    Mapper.CreateMap<Customer, CustomerDto>()

    Address address = new Address() { Street = "Main", Country = "CH" };
    Customer customer = new Customer() { LastName = "Graber", Address = address };

    CustomerDto dto = Mapper.Map<Customer, CustomerDto>(customer);

    Assert.AreEqual("Graber", dto.LastName);
    Assert.AreEqual("Main", dto.AddressStreet);
    Assert.IsNull(dto.NotMapped);
}

Gefällt einem dies nicht kann man die Felder per opt.MapFrom wie schon erklärt aus einem beliebigen Feld (oder Wert) übernehmen.

 

Konfiguration überprüfen

Im vorherigen Beispiel wurde das Feld NotMapped nicht gesetzt. Da es im Ausgangsobjekt kein entsprechendes Feld gibt wird es von AutoMapper auch nicht gefüllt. Falls man dies als Fehler ansieht kann man die Konfiguration durch AutoMapper überprüfen lassen:

[TestMethod]
public void ValidateMapping()
{
    Mapper.CreateMap<Customer, CustomerDto>();
    Mapper.AssertConfigurationIsValid();
}

Durch das nicht vorhandene Feld NotMapped wird man beim Ausführen diese Fehlermeldung erhalten:

Test method TestProject1.UnitTest1.ValidateMapping threw exception:
AutoMapper.AutoMapperConfigurationException:
Unmapped members were found. Review the types and members below.
Add a custom mapping expression, ignore, add a custom resolver, or modify the
source/destination type

 

Wohin mit der Konfiguration?

Es genügt AutoMapper beim Start der Applikation über die Methode Mapper.CreateMap() zu konfigurieren. Je nach Anwendungstyp kann man dies einmalig in der Main-Methode oder in der Datei Global.asax machen. So wird der notwendige Code für AutoMapper gegenüber den hier gezeigten Beispielen noch einmal kleiner.

 

Fazit

Mit AutoMapper hat man ein Werkzeug zur Verfügung mit dem man nicht mehr selber den ganz banalen Mapping-Code schreiben muss. Wird es komplexer bietet einem AutoMapper eine Vielzahl von Einstellungsmöglichkeiten. Allerdings gilt es wie bei jedem Werkzeug genau zu prüfen ob und in welchem Umfang der Einsatz sinnvoll ist.

Schlagworte:
Folgen

Erhalte jeden neuen Beitrag in deinen Posteingang.

Schließe dich 296 Followern an