Irre ich mich, wenn ich denke, dass die Notwendigkeit von AutoMapper ein Zeichen für schlechtes Design ist?

35

Automapper ist ein "Objekt-Objekt-Mapper" für .NET. Dies bedeutet, dass Objekte aus einer Klasse in eine andere Klasse kopiert werden, die dasselbe darstellt.

Warum ist das jemals nützlich? Ist das Duplizieren von Klassen jemals nützlich / gutes Design?

static_rtti
quelle
Ein kleiner Hinweis: devtrends.co.uk/blog/… Lesen Sie insbesondere den Abschnitt "Warum können wir keinen Automapper verwenden?"
Jani Hyytiäinen

Antworten:

28

Eine schnelle Google-Suche ergab folgendes Beispiel:

http://www.codeproject.com/Articles/61629/AutoMapper

zeigt eine perfekt gültige Verwendung von AutoMapper, die definitiv kein Beispiel für ein schlechtes Design ist. In einer Anwendung mit mehreren Ebenen befinden sich möglicherweise Objekte in Ihren Daten oder in Ihrer Business-Ebene. Manchmal benötigen Sie nur eine Teilmenge der Attribute dieser Datenobjekte oder eine Art Sicht auf diese in Ihrer UI-Ebene. Sie erstellen also ein Ansichtsmodell, das Objekte mit genau den Attributen enthält, die Sie in Ihrer Benutzeroberfläche benötigen, und verwenden AutoMapper, um den Inhalt dieser Objekte mit weniger Boilerplate-Code zu versehen.

In einer solchen Situation sind Ihre "Ansichtsobjekte" kein Duplikat der ursprünglichen Klasse. Sie haben verschiedene Methoden und vielleicht ein paar doppelte Attribute. Dies ist jedoch in Ordnung, solange Sie diese Ansichtsobjekte nur für die Anzeige auf der Benutzeroberfläche verwenden und sie nicht für Datenmanipulationen oder Geschäftsvorgänge missbrauchen.

Ein weiteres Thema, das Sie möglicherweise lesen, um dies besser zu verstehen , ist im Gegensatz zu CRUD das Trennungsmuster "Fowlers Command Query Responsibility" . Es zeigt Situationen, in denen unterschiedliche Objektmodelle zum Abfragen und Aktualisieren von Daten in einer Datenbank sinnvoll sind. Hier kann die Zuordnung von einem Objektmodell zu einem anderen auch mit einem Tool wie AutoMapper erfolgen.

Doc Brown
quelle
1
Zum ersten Beispiel: Konnten Sie keine Objekte komponieren, anstatt sie zu duplizieren? In diesem Fall haben Ihre UI-Objekte einen Verweis auf Ihre ursprünglichen Datenobjekte und machen nur die erforderlichen Elemente verfügbar. Wäre das nicht sinnvoll?
static_rtti
1
@static_rtti in der Theorie ja, aber möglicherweise möchten Sie nicht unbedingt, dass Ihre ursprüngliche Klasse öffentlich ist oder / und in einer Assembly ausgestellt wird
Jalayn
2
@static_rtti: ja, das ist ein völlig gültiger, anderer Ansatz. Der Hauptunterschied zwischen diesen beiden Designs ist die Lebensdauer der Daten / Attribute. Bei Verwendung von Kopien erhalten Sie eine Momentaufnahme der Daten, bei Verwendung von Eigenschaften, die auf die Originaldaten verweisen, nicht. Beide Ansätze haben ihre Vor- und Nachteile, aber meiner Meinung nach gibt es im Allgemeinen kein "besser oder schlechter". Darüber hinaus kann es zu Leistungsüberlegungen kommen, die die Entscheidung, was verwendet werden soll, beeinflussen können oder nicht.
Doc Brown
3
So weit wie möglich zu entkoppeln ist immer eine gute Idee. Nicht weil es selbst für kleine Projekte von besonderem Nutzen ist, sondern weil Projekte wachsen.
Tamás Szelei
6
@fish: Meistens stimme ich zu, Entkopplung ist oft eine gute Idee, aber meiner Meinung nach gibt es genug Situationen, in denen die Vereinfachung einen mehrschichtigen, superentkoppelten Ansatz überwiegt, um der Entkopplung willen. Die Schwierigkeit besteht darin, während des Wachstums eines Projekts nicht den Zeitpunkt zu verpassen, an dem mit dem Refactoring begonnen werden sollte.
Doc Brown
45

Ist das Duplizieren von Klassen jemals nützlich / gutes Design?

Es hat sich bewährt, eine separate Ansichtsmodellklasse für die Verwendung in der Benutzeroberflächenebene zu verwenden, anstatt dieselbe Klasse zu verwenden, die in der Datenebene verwendet wird. Ihre Benutzeroberfläche / Webseite muss möglicherweise andere Informationen anzeigen, die sich nicht ausschließlich auf die Datenentität beziehen. Indem Sie diese zusätzliche Klasse erstellen, geben Sie sich die Freiheit, die Benutzeroberfläche einfach zu optimieren, wenn sich die Anforderungen im Laufe der Zeit ändern.

Ich persönlich vermeide die Verwendung von AutoMapper aus drei Gründen:

Stille Ausfälle häufiger

Da AutoMapper automatisch zwischen Eigenschaften abbildet, wird die Eigenschaftszuordnung übersprungen, wenn ein Eigenschaftsname für eine Klasse und nicht für die andere Klasse geändert wird. Der Compiler wird es nicht wissen. Automapper ist das egal.

Fehlende statische Analyse

Sie haben also eine große Codebasis erhalten, mit der Sie sich befassen müssen. Es gibt eine Million Klassen mit einer Million Eigenschaften. Es sieht so aus, als ob sie nicht verwendet werden oder Duplikate sind. Mit dem Tool "Alle Verweise suchen" in Visual Studio können Sie feststellen, wo Eigenschaften verwendet werden, und in Ihrem Kopf eine Übersicht darüber erstellen, wie die gesamte Anwendung zusammen hängt. Warten Sie, es gibt keine expliziten Verweise auf die Hälfte der Eigenschaften, da Automapper verwendet wird. Mein Job ist jetzt um einiges schwieriger.

Späte Anforderungen, die die Komplexität erhöhen

Automapper funktioniert einwandfrei, wenn Sie nur die Werte aus EINER Klasse in eine andere Klasse kopieren möchten (wie dies häufig zu Beginn der Entwicklung der Fall ist). Erinnern Sie sich jedoch an die Anforderungen, die sich mit der Zeit ändern? Was ist, wenn Sie jetzt Werte von anderen Teilen Ihrer Anwendung abrufen müssen, möglicherweise spezifisch für den angemeldeten Benutzer oder einen anderen Kontextstatus?

Das AutoMapper-Muster zum Erstellen der Eins-zu-Eins-Klassenzuordnungen beim Anwendungsstart eignet sich nicht gut für diese Art von kontextspezifischen Änderungen. Ja, es gibt wahrscheinlich Möglichkeiten, es zum Laufen zu bringen, aber ich finde es normalerweise sauberer, einfacher und ausdrucksvoller, die Logik selbst zu schreiben.

Kurz gesagt, bevor Sie sich an Automapper wenden, um 30 Sekunden Zeit für die manuelle Zuordnung einer Klasse zu einer anderen zu sparen, sollten Sie darüber nachdenken.

Programmieren ist die Kunst, einem anderen Menschen zu sagen, was der Computer tun soll. - Donald Knuth

Fragen Sie sich vor diesem Hintergrund: "Ist AutoMapper heute hilfreich und wird es morgen sein?"

Dave B 84
quelle
Wenn Sie also einen REST-Webdienst schreiben, überprüfen Sie in der Regel immer jede einzelne Eigenschaft, um sicherzustellen, dass Ihr JavaScript-Objektmodell mit Ihrem .NET-Objektmodell konsistent ist.
Den
3
@Den - ja. Und Sie schreiben Tests, um sicherzustellen, dass Sie alle Eigenschaften korrekt erhalten (dh Ihr Test zeigt alle Eigenschaften, die Sie an einem Ort hinzugefügt haben, die nicht auf die anderen Ebenen übertragen werden)
gbjbaanb
@gbjbaanb Ich würde wahrscheinlich nur Reflection verwenden, um diese Validierung auf generische Weise durchzuführen. Untersuchen Sie möglicherweise die Möglichkeit, AutoMapper zu erweitern, um eine Validierung hinzuzufügen. Würde definitiv viele manuelle Zuweisungen vermeiden .
Den
Stimmen Sie voll und ganz mit Ihnen überein und denken Sie, dass nur sehr einfache Apps Automapper verwenden können. Wenn die Dinge jedoch komplexer werden, müssen wir eine neue Konfiguration für Automapper schreiben.
Ahmedsafan86
21

Nach meiner Erfahrung hat sich jemand über "zu viel Heizplatte" beschwert und möchte AutoMapper verwenden.

  1. Sie finden es irritierend, immer wieder denselben Code zu schreiben.
  2. Sie sind faul und möchten keinen Code schreiben, der Ax = Bx ausführt
  3. Sie stehen unter zu großem Zeitdruck, um tatsächlich darüber nachzudenken, ob es eine gute Idee ist, Ax = Bx immer wieder zu schreiben, und schreiben Sie dann einen guten Code für die Aufgabe.

Jedoch:

  1. Wenn es wirklich darum geht, Wiederholungen zu vermeiden, können Sie ein Objekt oder eine Methode erstellen, um es zu abstrahieren. Sie brauchen keinen AutoMapper.
  2. Wenn Sie faul sind, werden Sie faul sein und nicht lernen, wie AutoMapper funktioniert. Stattdessen übernehmen Sie das Muster "Programmieren durch Zufall" und schreiben schrecklichen Code, in dem Sie Geschäftslogik in ein AutoMapper-Profil schreiben. In diesem Fall sollten Sie Ihre Einstellung zum Programmieren ändern oder sich eine andere berufliche Tätigkeit suchen. Sie brauchen keinen AutoMapper.
  3. Wenn Sie unter zu viel Zeitdruck stehen, hat Ihr Problem nichts mit der Programmierung selbst zu tun. Sie brauchen keinen AutoMapper.

Wenn Sie eine statisch typisierte Sprache ausgewählt haben, können Sie die Sprache nutzen. Wenn Sie versuchen, die Steuerelemente in der Sprache zu umgehen, die dazu beitragen, Fehler aufgrund übermäßiger Verwendung von Reflection- und Magic-APIs wie AutoMapper zu vermeiden, bedeutet dies lediglich, dass Sie eine für Ihre Anforderungen unbefriedigende Sprache ausgewählt haben.

Nur weil Microsoft Funktionen zu C # hinzugefügt hat, bedeutet dies nicht, dass sie in jeder Situation fair sind oder bewährte Methoden unterstützen. Reflection und das Schlüsselwort 'dynamic' sollten beispielsweise in Fällen verwendet werden, in denen Sie einfach nicht das erreichen können, was Sie ohne sie benötigen. AutoMapper ist keine Lösung für jeden Anwendungsfall, der ohne AutoMapper noch nicht gelöst werden kann.

Ist also die Duplizierung von Klassen ein schlechtes Design? Nicht unbedingt.

Ist AutoMapper eine schlechte Idee? Ja absolut.

Die Verwendung von AutoMapper weist auf systembedingte Mängel im Projekt hin. Wenn Sie es brauchen, denken Sie über Ihr Design nach. Sie werden immer ein besseres, lesbareres, wartbareres und fehlerfreieres Design finden.

Shashi Penumarthy
quelle
1
Gut gesagt, insbesondere 2.
Mardoxx
2
Ich weiß, dass dies ein sehr alter Thread ist, aber ich muss mit 1 nicht einverstanden sein. Sie können keine Methode zur abstrakten Zuordnung erstellen. Sie können für 1 Klasse, aber wenn Sie 2 haben, benötigen Sie 2 Methoden. 3 - 3 Methoden. Bei AM ist dies eine Codezeile - Definition des Mappings. Außerdem hatte ich wirklich mit einem Szenario zu kämpfen, in dem eine Liste <BaseType> mit 10 DTO-Untertypen gefüllt war. Wenn Sie dies abbilden möchten, benötigen Sie einen Einschalttyp UND eine Methode zum Kopieren von Feldwerten. Und wenn eines der Felder separat abgebildet werden muss? Ihre Antwort ist nur gut, wenn Sie nur wenige einfache Klassen haben. AutoMapper gewinnt zweifellos in komplexeren Szenarien.
user3512524
1
(char limit) Das einzige Problem von AM ist meines Erachtens die Möglichkeit, den Namen des Eigentums in einer Klasse und nicht in der anderen zu ändern. Aber wie oft machst du das wirklich, nachdem das Design fertig ist? Außerdem können Sie eine generische Testmethode schreiben, die Reflexion verwendet und Eigenschaftsnamen vergleicht. Wie alle Tools muss AM korrekt verwendet werden - nicht blind, nicht in allen Situationen, da stimme ich zu. Aber "Du solltest es nicht benutzen" zu sagen ist einfach falsch.
user3512524
7

Es gibt ein tieferes Problem hier: die Tatsache , dass C # und Java bestehen die meisten / alle Arten von Namen zu unterscheiden sein müssen , anstatt Struktur: zB class MyPoint2Dund class YourPoint2Dsind getrennte Arten , auch wenn sie genau die gleichen Definitionen haben. Wenn der von Ihnen gewünschte Typ "eine anonyme Sache mit einem xFeld und einem yFeld" (dh ein Datensatz ) ist, haben Sie kein Glück. Wenn Sie also eine YourPoint2Din eine verwandeln möchten MyPoint2D, haben Sie drei Möglichkeiten:

  1. Schreiben Sie ein langweiliges, sich wiederholendes, alltägliches Boilerplate nach dem Vorbild von this.x = that.x; this.y = that.y
  2. Generiere den Code irgendwie.
  3. Verwenden Sie Reflexion.

Wahl 1 ist in kleinen Dosen einfach genug, wird jedoch schnell zur Pflicht, wenn die Anzahl der zuzuordnenden Typen groß ist.

Wahl 2 ist weniger wünschenswert, da Sie jetzt Ihrem Erstellungsprozess einen zusätzlichen Schritt hinzufügen müssen, um den Code zu generieren, und sicherstellen müssen, dass das gesamte Team das Memo erhält. Im schlimmsten Fall müssen Sie auch Ihren eigenen Codegenerator oder Ihr eigenes Vorlagensystem rollen.

Das lässt dich nachdenken. Sie können es selbst tun oder AutoMapper verwenden.

Doval
quelle
2

Automapper ist eine jener Bibliotheken / Tools, in denen der Kaiser buchstäblich stumpf nackt herumläuft. Wenn Sie an dem glitzernden Logo vorbeikommen, stellen Sie fest, dass es nichts tut, was Sie nicht manuell tun können, mit viel besseren Ergebnissen.

Obwohl ich nicht ganz sicher bin, wie es auf Auto-Mapping-Mitglieder hindeutet, handelt es sich höchstwahrscheinlich um zusätzliche Laufzeitlogik und mögliche Überlegungen. Dies kann eine erhebliche Leistungseinbuße im Austausch für eine Zeitersparnis sein. Beim manuellen Mapping wird der Hinweis jedoch lange vor dem Kompilieren ausgeführt.

In Fällen, in denen AutoMapper keine Ahnung hat, müssen Sie die Zuordnung mit Code konfigurieren und Flags setzen. Wenn Sie die gesamte Setup- und Code-Arbeit erledigen möchten, müssen Sie sich fragen, wie viel Sie durch manuelles Mapping sparen.

user148298
quelle