5 votes

Votre application ASP.NET MVC est-elle correctement structurée ?

J'ai suivi les tutoriels (en particulier ceux utilisant Linq-To-Entities) et je comprends les concepts de base, cependant certaines choses me posent problème.

Les tutoriels impliquent généralement uniquement des modèles simples et des formulaires utilisant uniquement des instructions de création, de mise à jour et de suppression de base. Les miens sont un peu plus compliqués, et je ne suis pas sûr de la manière dont je m'y prends parce que lorsque vient le moment de gérer les relations entre une demi-douzaine d'objets de base de données, les tutoriels s'arrêtent.

Pour la méthode de publication, la méthode habituelle pour effectuer des opérations CRUD

entities.AddToTableSet(myClass);
entities.SaveChanges();

Ne fera pas ce que je veux, car une classe entièrement implémentée n'est pas envoyée à la méthode du contrôleur. Je peux envoyer des champs individuels, des collections de formulaires, ou plusieurs objets DTO et ensuite appeler une méthode sur un service ou un dépôt pour prendre les informations que je reçois d'une publication de formulaire, avec les informations dont il a besoin pour interroger ou créer lui-même, et ensuite à partir de toutes ces choses, créer mon objet de base de données que je peux enregistrer.

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Add(int id, [Bind(Exclude = "Id")] ClassA classA,
                        [Bind(Exclude = "Id")]ClassB classB)
{
   // La validation se fait ici

   if(!ModelState.IsValid)
      return View();

   try
   {
      _someRepositoryOrService.Add(id, classA, classB);
      return RedirectToAction("Index", new { id = id });
   }
   catch(Exception ex)
   {
      // La journalisation et la gestion des exceptions se font ici
   }
}

public void Add(int id, ClassA classA, ClassB classB)
{
    EntityA eA = new EntityA
    {
        // Définir un tas de propriétés en utilisant les deux classes et
        // toutes les requêtes nécessaires
    };

    EntityB eB = new EntityB
    {
        // Définir un tas de propriétés en utilisant les deux classes et
        // toutes les requêtes nécessaires
    };

    _entity.AddToEntityASet(eA);
    _entity.AddToEntityBSet(eB);
    _entity.SaveChanges();
}

Suis-je en train de gérer cela correctement ou en train de dénaturer le framework? Je n'utilise jamais vraiment un objet entité directement, chaque fois que j'en interroge un je mets les informations dont j'ai besoin dans un DTO et base mes Vues là-dessus. Il en va de même pour la création. Est-ce permis, ou mon évitement d'utiliser directement des entités va-t-il à l'encontre du but d'utilisation du framework?

Édition : Je suis également préoccupé par cette approche car elle nécessite des constructeurs vides pour effectuer correctement les requêtes LINQ en raison de ce message d'erreur :

Seuls les constructeurs sans paramètres et les initialiseurs sont pris en charge dans LINQ to Entities.

Ce n'est pas un gros problème puisque je n'ai rarement besoin de logic dans les constructeurs, mais est-ce un problème de ne pas avoir de constructeurs et uniquement des propriétés publiques?

4voto

Michael Maddox Points 7345

Je dirais qu'utiliser des DTO et envelopper Entity Framework avec vos propres méthodes d'accès aux données et de couche métier est une excellente option. Vous finirez peut-être par écrire beaucoup de code, mais c'est une meilleure architecture que de prétendre que le code généré par Entity Framework est votre couche métier.

Ces problèmes ne sont pas vraiment liés à ASP.NET MVC de quelque façon que ce soit. ASP.NET MVC ne donne pratiquement aucun conseil sur la manière de gérer votre modèle / accès aux données et la plupart des exemples et tutoriels pour ASP.NET MVC ne sont pas des mises en œuvre de modèle dignes de la production, mais simplement des exemples minimaux.

Il semble que vous êtes sur la bonne voie, continuez.

En fin de compte, vous utilisez Entity Framework surtout en tant que générateur de code qui ne génère pas un code très utile, alors vous voudrez peut-être envisager d'autres générateurs de code, outils ou frameworks qui correspondent mieux à vos besoins.

4voto

queen3 Points 8810

_someRepositoryOrService.Add(id, classA, classB);

Je dirais que vous couplez vos repositories avec la couche de présentation. Cela ne devrait pas être le cas. Vos repositories devraient seulement travailler avec les entités. Ensuite, remarquez comment votre méthode Add

public void Add(int id, ClassA classA, ClassB classB)

enfreint le Principe de Séparation des Responsabilités (SoC). Elle effectue deux tâches :

  1. mapper les données de la vue en entités
  2. sauvegarder dans le repository

Évidemment, la première étape devrait être réalisée dans la couche de présentation. Envisagez d'utiliser des model binders pour cela. Cela peut également vous aider à résoudre le problème des constructeurs, puisque vos model binders peuvent être conscients des exigences de construction.

Consultez également cet excellent article de Jimmy Bogard (co-auteur de ASP.NET MVC In Action) sur ViewModels. Cela pourrait vous aider à automatiser le mapping. Il suggère également une technique inversée - faire en sorte que vos contrôleurs travaillent avec les entités, pas avec les ViewModels ! Les filtres d'actions personnalisés et les model binders sont vraiment la clé pour éliminer les routines qui ne doivent pas vraiment appartenir aux contrôleurs, mais plutôt à des détails d'infrastructure entre la vue et le contrôleur. Par exemple, voici comment j'automatise la récupération des entités. Voici comment je vois ce que les contrôleurs devraient faire.

L'objectif ici est de faire en sorte que les contrôleurs se concentrent sur la gestion de la logique métier, en mettant de côté tous les détails techniques qui n'appartiennent pas à votre activité. Ce sont des contraintes techniques dont vous parlez dans cette question, et vous les laissez se glisser dans votre code. Mais vous pouvez utiliser des outils MVC pour les déplacer au niveau de l'infrastructure.

MISE À JOUR : Non, les repositories ne devraient pas gérer les données de formulaire, c'est ce que je veux dire par "couplage avec la présentation". Oui, les repositories sont dans le contrôleur, mais ils ne travaillent pas avec les données de formulaire. Vous pouvez (bien que vous ne devriez pas) faire en sorte que le formulaire fonctionne avec les "données des repositories" - c'est-à-dire les entités - et c'est ce que font la plupart des exemples, par exemple NerdDinner - mais pas dans l'autre sens. Cela est dû à la règle générale - les couches supérieures peuvent être couplées avec les couches inférieures (la présentation couplée avec les repositories et les entités), mais jamais une couche inférieure ne doit être couplée à une couche supérieure (les entités dépendent des repositories, les repositories dépendent du modèle de formulaire, etc).

La première étape devrait être réalisée dans le repository, c'est vrai - sauf que le mapping de ClassX vers EntityX ne fait pas partie de cette étape. C'est une préoccupation de mapping - une infrastructure. Voyez par exemple cette question sur le mapping, mais en général, si vous avez deux couches (UI et repositories) elles ne devraient pas se soucier du mapping - un service/helper de mapping devrait le faire. En plus du blog de Jimmy, vous pouvez également lire ASP.NET MVC In Action ou simplement regarder leur CodeCampServer pour voir comment ils font le mapping avec des interfaces IEntityMapper passées aux constructeurs des contrôleurs (notez que c'est une approche plus manuelle et moins automatisée que AutoMapper de Jimmy Bogard).

Une autre chose. Renseignez-vous sur la Conception Orientée Domaine, recherchez des articles, apprenez-en à partir d'eux, mais vous n'avez pas à tout suivre à la lettre. Ce sont des lignes directrices, pas des solutions strictes. Voyez si votre projet peut gérer cela, voyez si vous pouvez gérer cela, etc. Essayez d'appliquer ces techniques car ce sont généralement d'excellentes façons approuvées de faire du développement, mais ne les appliquez pas aveuglément - il vaut mieux apprendre en chemin que d'appliquer quelque chose que vous ne comprenez pas.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X