Est-ce que je me trompe en pensant qu'avoir besoin de quelque chose comme AutoMapper est un indice de mauvaise conception?


35

Automapper est un "mappeur d'objet-objet" pour .Net, ce qui signifie copier des objets d'une classe dans une autre classe qui représente la même chose.

Pourquoi cela est-il utile? La duplication des classes est-elle toujours utile / bonne conception?


Une petite référence: devtrends.co.uk/blog/… Lisez en particulier la section "pourquoi ne pouvons-nous pas utiliser automapper?"
Jani Hyytiäinen

Réponses:


28

Une recherche rapide sur Google a révélé cet exemple:

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

montrant une utilisation parfaitement valide d'AutoMapper qui n'est certainement pas un exemple de conception médiocre. Dans une application en couches, vous pouvez avoir des objets dans vos données ou votre couche métier et vous n'avez parfois parfois besoin que d'un sous-ensemble d'attributs de ces objets de données ou d'une sorte de vue dans la couche d'interface utilisateur. Vous créez donc un modèle de vue contenant des objets avec exactement les attributs dont vous avez besoin dans votre interface utilisateur, et utilisez AutoMapper pour fournir le contenu de ces objets avec moins de code passe-partout.

Dans une telle situation, vos "objets de vue" ne sont pas une copie de la classe d'origine. Ils ont des méthodes différentes et peut-être quelques attributs en double. Mais cela n’est pas grave tant que vous utilisez ces objets de vue uniquement à des fins d’affichage d’interface utilisateur et ne commencez pas à les utiliser à mauvais escient pour la manipulation de données ou les opérations commerciales.

Un autre sujet que vous pourrez lire pour mieux comprendre ceci est le modèle de séparation des responsabilités de la requête Fowlers de la commande , par opposition à CRUD. Il vous montre des situations dans lesquelles différents modèles d'objet pour interroger des données et les mettre à jour dans une base de données ont du sens. Ici, le mappage d'un modèle d'objet à un autre peut également être effectué par un outil tel qu'AutoMapper.


1
Concernant votre premier exemple: ne pourriez-vous pas composer des objets au lieu de les dupliquer? Dans ce cas, vos objets d'interface utilisateur font référence à vos objets de données d'origine et n'exposent que les éléments nécessaires. Cela n'aurait-il pas de sens?
static_rtti

1
@static_rtti en théorie oui, mais vous ne voudrez peut-être pas nécessairement que votre classe d'origine soit publique ou exposée dans une assemblée
Jalayn,

2
@static_rtti: oui, cette approche est parfaitement valide et différente. La principale différence entre ces deux conceptions est la durée de vie des données / attributs. L'utilisation de copies fournit un instantané des données, contrairement aux propriétés faisant référence aux données d'origine. Les deux approches ont leurs avantages et leurs inconvénients, mais à mon humble avis, il n’ya ni «meilleur ni pire» en général. De plus, il peut y avoir des considérations de performances, qui peuvent ou non influencer la décision d'utiliser ou non.
Doc Brown

3
Découpler le plus possible est toujours une bonne idée. Non pas parce que c'est particulièrement bénéfique pour les petits projets, mais parce que les projets se développent.
Tamás Szelei

6
@fish: Je suis plutôt d'accord sur le fait, le découplage est souvent une bonne idée, mais à mon humble avis, il existe suffisamment de situations où garder les choses simples l'emporte sur une approche multi-couches super-découplée au service du découplage. La partie difficile est de ne pas manquer le point pendant la croissance d'un projet quand il faut commencer à refactoriser.
Doc Brown

45

La duplication des classes est-elle toujours utile / bonne conception?

Il est recommandé de disposer d'une classe de modèle de vue distincte pour une utilisation dans la couche d'interface utilisateur plutôt que d'utiliser la même classe que celle utilisée dans la couche de données. Votre interface utilisateur / page Web peut avoir besoin d'afficher d'autres informations qui ne sont pas strictement liées à l'entité de données. En créant cette classe supplémentaire, vous vous donnez la liberté de modifier facilement votre interface utilisateur à mesure que les exigences changent avec le temps.

En ce qui concerne l'utilisation d'AutoMapper, je l'évite personnellement pour 3 raisons:

Les échecs silencieux plus fréquents

Étant donné qu'AutoMapper mappe automatiquement entre les propriétés, la modification du nom d'une propriété sur une classe et non sur l'autre entraînera l'omission du mappage de la propriété. Le compilateur ne le saura pas. Automapper ne s'en soucie pas.

Absence d'analyse statique

Donc, vous avez une grande base de code à traiter. Il y a un million de classes avec un million de propriétés. On dirait qu'ils ne sont pas utilisés ou sont des doublons. Cet outil "Rechercher toutes les références" dans Visual Studio vous aidera à voir où les propriétés sont utilisées et à créer une carte dans votre tête indiquant comment toute l'application se bloque. Mais attendez, il n'y a aucune référence explicite à la moitié des propriétés, car Automapper est utilisé. Mon travail est maintenant beaucoup plus dur.

Besoins tardifs qui augmentent la complexité

Automapper est tout à fait dandy lorsque tout ce que vous voulez faire est de copier les valeurs d'une classe à une autre (comme c'est souvent le cas au début du développement), mais vous souvenez-vous de ces exigences qui changent avec le temps? Que faire si vous avez maintenant besoin d'obtenir des valeurs d'autres parties de votre application, par exemple spécifiques à l'utilisateur connecté ou à un autre état contextuel?

La façon dont AutoMapper crée les mappages de classe un-à-un au démarrage de l'application ne se prête pas bien à ce type de changements spécifiques au contexte. Oui, il y a probablement moyen de le faire fonctionner, mais je trouve généralement plus propre, plus simple et plus expressif d'écrire la logique moi-même.

En résumé, avant d’atteindre Automapper pour économiser 30 secondes de mappage manuel d’une classe à une autre, réfléchissez-y.

La programmation est l'art de dire à un autre humain ce que l'on veut que l'ordinateur fasse. - Donald Knuth

Dans cet esprit, demandez-vous "AutoMapper est-il utile aujourd'hui et sera-t-il demain?"


Si vous écrivez un service Web REST, avez-vous tendance à toujours vérifier chaque propriété pour vous assurer que votre modèle d'objet JavaScript est cohérent avec votre modèle d'objet .NET?
Den

3
@ Den - oui. Et vous écrivez des tests pour vous assurer que toutes les propriétés sont correctes (c'est-à-dire que votre test montrera toutes les propriétés que vous avez ajoutées à un endroit et qui ne sont pas propagées aux autres niveaux)
gbjbaanb

@ gbjbaanb J'utiliserais probablement la réflexion pour effectuer cette validation de manière générique. Peut-être explorer la possibilité d'étendre AutoMapper pour ajouter une validation. Eviterait certainement beaucoup d'assignations manuelles.
Den

Totalement en accord avec vous et pensez que seules les applications très simples peuvent utiliser automapper, mais lorsque les choses se compliquent, nous devons écrire une nouvelle configuration pour automapper, alors pourquoi ne pas les écrire dans un assistant ou un service de mappeur manuel.
ahmedsafan86

21

D'après mon expérience, quand quelqu'un s'est plaint de «trop de casse-tête» et veut utiliser AutoMapper, c'est l'un des cas suivants:

  1. Ils trouvent cela irritant d'écrire le même code à plusieurs reprises.
  2. Ils sont paresseux et ne veulent pas écrire de code qui fait Ax = Bx
  3. Ils sont trop pressés par le temps pour réfléchir à la question de savoir si écrire Ax = Bx à plusieurs reprises est une bonne idée, puis écrivez un bon code pour la tâche.

Toutefois:

  1. S'il s'agit vraiment d'éviter la répétition, vous pouvez créer un objet ou une méthode pour l'abréger. Vous n'avez pas besoin d'AutoMapper.
  2. Si vous êtes paresseux, vous le serez sans apprendre comment AutoMapper fonctionne. Au lieu de cela, vous adopterez le modèle de «programmation par coïncidence» et écrivez un code horrible dans lequel vous insérez la logique métier dans un profil AutoMapper. Dans ce cas, vous devriez changer votre attitude envers la programmation ou trouver quelque chose d'autre à faire en tant que profession. Vous n'avez pas besoin d'AutoMapper.
  3. Si vous êtes trop pressé, votre problème n'a rien à voir avec la programmation elle-même. Vous n'avez pas besoin d'AutoMapper.

Si vous avez choisi une langue de type statique, profitez-en. Si vous essayez de contourner les contrôles de la langue qui permettent d'éviter les erreurs dues à l'utilisation excessive d'API réfléchissantes et magiques telles qu'AutoMapper, cela signifie simplement que vous avez choisi une langue qui ne répond pas à vos besoins.

De plus, le fait que Microsoft ait ajouté des fonctionnalités au C # ne signifie pas qu’elles sont honnêtes dans toutes les situations ou qu’elles prennent en charge les meilleures pratiques. Reflection et le mot clé 'dynamic', par exemple, doivent être utilisés dans les cas où vous ne pouvez tout simplement pas accomplir ce dont vous avez besoin sans eux. AutoMapper n'est pas une solution pour tous les cas d'utilisation qui ne peuvent pas déjà être résolus sans cela.

Alors, la duplication des classes est-elle une mauvaise conception? Pas nécessairement.

AutoMapper est-il une mauvaise idée? Oui absolument.

L'utilisation d'AutoMapper indique des déficiences systémiques dans le projet. Si vous en avez besoin, arrêtez-vous et réfléchissez à votre conception. Vous trouverez toujours une conception meilleure, plus lisible, plus maintenable et plus sans bugs.


1
Bien dit, particulièrement 2.
Mardoxx

2
Je sais que c'est un très vieux fil, mais je ne suis pas d'accord avec 1. Vous ne pouvez pas créer de méthode de mappage abstrait. Vous pouvez pour 1 classe, mais si vous en avez 2, vous avez besoin de 2 méthodes. 3 - 3 méthodes. Avec AM, cela représente 1 ligne de code - définition du mappage. De plus, j’ai vraiment eu du mal avec un scénario dans lequel j’avais une liste <BaseType> contenant 10 sous-types DTO. Lorsque vous souhaitez mapper cela, vous avez besoin d'un type d'activation ET d'une méthode pour copier les valeurs de champ. Et si un des champs devait être cartographié séparément? Votre réponse n’est bonne que si vous avez peu de cours simples. AutoMapper gagne haut la main dans des scénarios plus complexes.
user3512524

1
(limite de caractères) Le seul piège d'AM, je pense, est la possibilité de changer le nom d'un bien dans une classe et non dans l'autre. Mais vraiment, à quelle fréquence faites-vous cela après la conception? Et vous pouvez écrire une méthode de test générique qui utilise la réflexion et compare les noms de propriétés. Comme tous les outils, AM doit être utilisé correctement - pas à l'aveuglette, pas dans toutes les situations, je suis d'accord. Mais dire "vous ne devriez pas l'utiliser" est tout simplement faux.
user3512524

7

Il y a un problème plus profond ici: le fait que C # et Java insister plus / tous les types doivent être distingués par leur nom plutôt que de la structure: par exemple , class MyPoint2Det class YourPoint2Dsont des types distincts , même si elles ont exactement les mêmes définitions. Quand le type que vous voulez est "quelque chose d'anonyme avec un xchamp et un ychamp" (c'est-à-dire un enregistrement ), vous n'avez pas de chance. Donc, lorsque vous voulez transformer un YourPoint2Den un MyPoint2D, vous avez trois options:

  1. Écrivez un passe-partout banal, fastidieux, répétitif et banal, dans le sens de this.x = that.x; this.y = that.y
  2. Générer le code en quelque sorte.
  3. Utilisez la réflexion.

Le choix 1 est assez facile à petites doses mais devient vite une corvée lorsque le nombre de types à cartographier est important.

Le choix 2 n’est pas souhaitable, car vous devez maintenant ajouter une étape supplémentaire à votre processus de génération pour générer le code et vous assurer que toute l’équipe reçoit le mémo. Dans le pire des cas, vous devez également lancer votre propre générateur de code ou votre propre modèle.

Cela vous laisse avec réflexion. Vous pouvez le faire vous-même ou utiliser AutoMapper.


3

Automapper est l'une de ces bibliothèques / outils où l'empereur tourne littéralement autour de lui. Lorsque vous dépassez le logo fastueux, vous réalisez qu'il ne fait rien que vous ne puissiez faire manuellement avec de bien meilleurs résultats.

Bien que je ne sois pas tout à fait certain de la manière dont cela se réfère aux membres auto-mappés, cela implique probablement une logique d'exécution supplémentaire et une réflexion possible. Cela peut constituer une pénalité de performance significative en échange d’un gain de temps. En revanche, le mappage manuel est exécuté bien avant la compilation.

Dans les cas où AutoMapper n'a aucune idée, vous devez configurer le mappage avec du code et des indicateurs de réglage. Si vous voulez vous occuper de tout l’installation et le travail du code, vous devez vous demander combien cela économise par rapport au mappage manuel.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.