Conseils simples sur l’architecture des applications

J’essaie de créer une petite application Web de démonstration couplée de manière lâche, hautement testable, dotée d’un code propre et agréable, etc. En bref, j’essaie de faire les choses de la bonne façon. 😉

J’ai actuellement trois projets dans ma solution Wolfie:

  • Wolfie.Core – contient des entités commerciales
  • Wolfie.Data – contient le code d’access aux données, références Core.
  • Wolfie.Web – sera un site Web de Nancy.

En l’état actuel des choses, le Core ne sait rien des autres projets. Data doit référencer Core car Core contient les types que Data renverra. Donc, à ce stade, je me rends compte que Web devra référencer à la fois Core et Data pour pouvoir fonctionner car le type d’entité est dans Core et les appels de firebase database sont dans Data.

Toutes les classes de référentiels dans Data ont des interfaces permettant de simuler les référentiels à des fins de test.

Je ne pense pas que je souhaite mettre un code ou des références spécifiques à une firebase database dans Core, et je souhaite que les règles commerciales de mon entité ne soient pas traitées dans Data.

Est-il correct de référencer les deux projets à partir du Web? ou un autre projet entre Web et les autres serait-il nécessaire pour que Web ne fasse référence qu’à un seul lieu et ne soit pas responsable de l’appel de méthodes Data, etc.

Ce que je vise, c’est une architecture dans laquelle mon application principale est indépendante des couches Web et des données.

J’espère avoir eu du sens et j’attends des réponses utiles.

Je pense que vous visez un objective raisonnable qui créera une architecture applicative solide. J’ai personnellement travaillé sur une application Web d’entreprise utilisant une architecture similaire à celle que vous décrivez, et cela a très bien fonctionné pour cette application.

Dans cette application, la logique métier du domaine était isolée dans son propre assembly “Domain” (votre assembly “Core”) et ne faisait référence à aucun élément en dehors du framework .NET. Afin de se connecter à des composants métier externes, tels que la firebase database et d’autres services Web, il existait un assemblage “Infrastructure” (votre assemblage “Données”). La clé de cette application est que chaque implémentation de l’assembly Infrastructure a été interfacée dans l’assembly Domain et a renvoyé des objects d’assembly Domain (exactement comme vous l’avez décrit). Bien entendu, cela nécessitait une référence d’infrastructure à domaine.

Pour lier le tout, un assemblage “WebApp” (votre assemblage “Web”) a référencé les assemblys Domain et Infrastructure et a utilisé un conteneur IoC pour résoudre toutes les dépendances de l’application. Lorsque les demandes arrivaient dans l’application Web, le contrat de “domaine” approprié était résolu afin de répondre à la demande, ce qui déclencherait la chaîne d’appels de résolution IoC. En dehors de l’enregistrement des implémentations d’infrastructure, l’assembly WebApp ne se soucie pas de son existence.

Si cette application a si bien fonctionné, c’est parce qu’elle a permis d’atteindre les objectives énoncés dans votre question:

  • Il n’y a pas de références externes dans le domaine métier.
  • L’application de domaine métier est complètement indépendante du front-end web et du back-end de la firebase database.

Cela confère de nombreuses possibilités de test à votre domaine métier et une grande souplesse quant à la manière dont les interfaces frontales s’interfacent avec votre domaine. En fait, cette flexibilité est ce qui le rend si testable. Cette flexibilité présente également d’autres avantages. Par exemple, avec votre domaine métier isolé, vous pouvez facilement coder un nouveau front-end CLI ou WPF raccordé à un système de fichiers sans modifier un bout de code de domaine si vous souhaitez déployer et exécuter votre client. localement sur une machine.

Bien que cet exemple puisse sembler un peu tiré par les cheveux, dans le cas de l’application que j’ai mentionnée plus haut, l’équipe de développement envisage de créer un frontal de services Web pour compléter le front-end de site Web MVC déjà existant. Il ne s’agit que d’une possibilité réaliste pour cette équipe car elle a configuré cette application comme vous le décrivez.

Je ne pense pas qu’il y ait quelque chose de fondamentalement faux avec ces deux références.

Mais, je considérerais ce que “Core” est. Est-ce votre logique de domaine? Si tel est le cas, je ne suis pas sûr que je serais dans une situation où votre assemblage d’access aux données connaît la logique de votre domaine et que votre couche d’interface graphique connaît les deux.

Si “Core” est une logique de domaine, vous pouvez y insérer des classes (par exemple, IRepository Pattern ) qui connaissent l’assemblage “Data”. Votre assemblage Web aurait alors connaissance de “Core”, mais pas de “Données”.

Pour faciliter cet arrangement, vous pouvez créer un quasortingème assemblage appelé “DataTransfer” et définir des objects (ou, mieux encore, des interfaces) que “Core”, “Données” et “Web” connaissent et utilisent tous pour communiquer entre eux. En fait, si vous voulez vraiment être découplé, la structuration de l’assemblage “Types” contenant des interfaces peut permettre de faire en sorte qu’aucun de vos trois assemblages d’origine ne se connaisse.

Mais ensuite, si “Core” est vraiment une bibliothèque plutôt que votre logique de domaine, il est probablement logique d’utiliser votre structure actuelle et de la revisiter ultérieurement si vous ajoutez suffisamment de fonctionnalités pour commencer à exploiter davantage d’assemblages / couches.

Edit: Pour aider à visualiser ce que je veux dire, je parle d’une situation en couches:

Web | v Core | v DataAccess 

plutôt que:

 Web | \ v \ Core | ^ | | v DataAccess 

Vous avez trois références lorsque vous pouvez le faire fonctionner avec deux. Un couplage extra / inutile précoce provoque des maux de tête plus tard.

Vous faites beaucoup de sens et votre raisonnement est très solide. Il est très courant, raisonnable et pragmatique de disposer d’une couche Web référençant à la fois le cœur et les données. Vous ne créez pas de références circulaires et ne le maintenez pas propre.

L’architecture est 1. données 2. logique métier 3. client. Les données sont des données. La logique métier fonctionne sur les données. Le client se connecte à la logique métier comme data-> logique métier-> client. Le client ne se connecte pas directement aux données. 3 couches. client de logique de données.

Je pense que cela a du sens. Tant que vous séparez le Web de la couche métier, cela vous permet de tester plus facilement la logique métier et d’exposer la couche métier via d’autres moyens (services Web, par exemple).