{"id":419,"date":"2025-03-22T22:02:42","date_gmt":"2025-03-22T21:02:42","guid":{"rendered":"https:\/\/wmg-studio.com\/?p=419"},"modified":"2025-03-22T22:03:19","modified_gmt":"2025-03-22T21:03:19","slug":"419","status":"publish","type":"post","link":"https:\/\/wmg-studio.com\/index.php\/2025\/03\/22\/419\/","title":{"rendered":"Architecture en couches"},"content":{"rendered":"\n<!DOCTYPE html>\n<html lang=\"fr\">\n<head>\n  <meta charset=\"UTF-8\" \/>\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"\/>\n  <title>Refactorisation d\u2019un monolithe vers une architecture en couches \u2013 Version Actualis\u00e9e<\/title>\n  <style>\n    \/* ---------------------\n      RESET & BASE\n    ----------------------*\/\n    *, *::before, *::after {\n      margin: 0;\n      padding: 0;\n      box-sizing: border-box;\n    }\n\n    \/* ---- Body ---- *\/\n    body {\n      \/* D\u00e9grad\u00e9 plus doux et moderne *\/\n      background: linear-gradient(120deg, #89f7fe, #66a6ff);\n      font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;\n      color: #2c3e50;\n      line-height: 1.6;\n      margin: 0;\n      padding: 0;\n    }\n\n    \/* ---- Container ---- *\/\n    .container {\n      max-width: 1000px;\n      margin: 3rem auto;\n      padding: 2.5rem;\n      background: #ffffff;\n      border-radius: 1.2rem;\n      box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);\n      animation: fadeIn 0.6s ease-in-out;\n    }\n\n    \/* ---------------------\n      HEADINGS\n    ----------------------*\/\n    h1 {\n      font-size: 2.4rem;\n      margin-bottom: 1.5rem;\n      text-align: center;\n      font-weight: 700;\n      color: #273c75;\n      position: relative;\n      text-shadow: 1px 1px 2px rgba(0,0,0,0.15);\n    }\n\n    h1::after {\n      content: '';\n      display: block;\n      margin: 0.5rem auto;\n      width: 80px;\n      height: 4px;\n      background: #273c75;\n      border-radius: 2px;\n    }\n\n    h2 {\n      font-size: 1.8rem;\n      margin-top: 2rem;\n      margin-bottom: 1.2rem;\n      font-weight: 600;\n      color: #2980b9;\n      text-shadow: 1px 1px 2px rgba(0,0,0,0.1);\n    }\n\n    h3 {\n      font-size: 1.4rem;\n      margin-top: 1.4rem;\n      margin-bottom: 0.8rem;\n      color: #2c3e50;\n      font-weight: 600;\n    }\n\n    \/* ---------------------\n      TEXT ELEMENTS\n    ----------------------*\/\n    p {\n      margin-bottom: 1.2rem;\n      text-align: justify;\n    }\n\n    ul {\n      margin: 1rem 0 1rem 2rem;\n      list-style-type: disc;\n    }\n\n    li {\n      margin: 0.5rem 0;\n    }\n\n    \/* ---- Code styling ---- *\/\n    code {\n      display: block;\n      background: #2f3640;\n      color: #f5f6fa;\n      padding: 1rem;\n      border-radius: 5px;\n      font-family: Consolas, Courier, monospace;\n      font-size: 0.95rem;\n      line-height: 1.4;\n      margin: 1rem 0;\n      overflow-x: auto;\n      box-shadow: inset 0 0 10px rgba(0,0,0,0.15);\n    }\n\n    \/* Inline code styling *\/\n    code.inline {\n      display: inline-block;\n      padding: 0.2rem 0.4rem;\n      font-size: 0.9rem;\n      box-shadow: none;\n    }\n\n    section {\n      margin-bottom: 2.5rem;\n    }\n\n    \/* ---------------------\n      ANIMATIONS\n    ----------------------*\/\n    @keyframes fadeIn {\n      from {\n        opacity: 0;\n        transform: translateY(10px);\n      }\n      to {\n        opacity: 1;\n        transform: translateY(0);\n      }\n    }\n  <\/style>\n<\/head>\n<body>\n  <div class=\"container\">\n    <h1>Refactorisation d\u2019un monolithe vers une architecture en couches<\/h1>\n\n    <!-- EXERCICE INTRO -->\n    <section>\n      <h2>Exercice initial<\/h2>\n      <p>\n        Pour introduire notre d\u00e9marche, voici une situation\u202f: vous disposez d\u2019un programme regroupant toutes les fonctionnalit\u00e9s\n        dans un seul bloc de code, sans r\u00e9elle organisation. Les vues (affichage), la logique m\u00e9tier (calculs, r\u00e8gles sp\u00e9cifiques)\n        et l\u2019acc\u00e8s aux donn\u00e9es (requ\u00eates SQL, connexion \u00e0 la base) sont entrem\u00eal\u00e9s.\n      <\/p>\n      <p>\n        <strong>Votre mission :<\/strong> rep\u00e9rer dans ce \u00ab\u202fmonolithe\u202f\u00bb quelles sont les parties qui correspondent respectivement\n        \u00e0 l\u2019interface (pr\u00e9sentation), au traitement m\u00e9tier et \u00e0 la persistance de donn\u00e9es. Prenez des notes, car la suite\n        du cours explique comment migrer progressivement vers une architecture plus modulaire.\n      <\/p>\n      <p>\n        En d\u2019autres termes, nous allons scinder ce monolithe en couches distinctes\u00a0: la pr\u00e9sentation, la couche de service,\n        la couche m\u00e9tier, et la couche d\u2019acc\u00e8s aux donn\u00e9es. Cette s\u00e9paration offre une meilleure maintenabilit\u00e9,\n        facilite les tests, et rend le projet pr\u00eat pour des \u00e9volutions futures (ajout de nouvelles fonctionnalit\u00e9s,\n        changements de base de donn\u00e9es, etc.).\n      <\/p>\n    <\/section>\n\n    <!-- PARTIE 1 -->\n    <section>\n      <h2>1) Qu\u2019est-ce qu\u2019une architecture en couches\u202f?<\/h2>\n      <p>\n        De nos jours, la plupart des applications professionnelles optent pour une forme de s\u00e9paration en couches.\n        Il existe plusieurs patrons d\u2019architecture, mais l\u2019objectif commun est de garder le code le plus organis\u00e9 possible.\n      <\/p>\n      <p>\n        Dans le mod\u00e8le le plus classique, on retrouve :\n      <\/p>\n      <ul>\n        <li>La <strong>Couche de pr\u00e9sentation<\/strong> \u2013 tout ce qui concerne l\u2019interface utilisateur<\/li>\n        <li>La <strong>Couche de service<\/strong> \u2013 la \u00ab\u202fpasserelle\u202f\u00bb qui relie l\u2019UI \u00e0 la logique m\u00e9tier<\/li>\n        <li>La <strong>Couche m\u00e9tier<\/strong> \u2013 o\u00f9 r\u00e9sident les r\u00e8gles, calculs et traitements centraux<\/li>\n        <li>La <strong>Couche d\u2019acc\u00e8s aux donn\u00e9es<\/strong> (DAL) \u2013 responsable du dialogue avec la base de donn\u00e9es<\/li>\n      <\/ul>\n      <p>\n        Cette structure est largement utilis\u00e9e parce qu\u2019elle r\u00e9duit le couplage et permet d\u2019ajouter ou de remplacer\n        plus facilement certains composants (une base de donn\u00e9es diff\u00e9rente, un nouveau front-end, etc.).\n      <\/p>\n    <\/section>\n\n    <!-- PARTIE 2 -->\n    <section>\n      <h2>2) Pourquoi s\u00e9parer en plusieurs couches\u202f?<\/h2>\n      <p>\n        Lorsque tout est dans un seul bloc de code, la moindre modification peut avoir des r\u00e9percussions inattendues.\n        Les tests sont compliqu\u00e9s, et il est difficile pour les \u00e9quipes de se r\u00e9partir le travail. Avec une architecture\n        en couches :\n      <\/p>\n      <ul>\n        <li><strong>Couplage minimal :<\/strong> chaque couche ne d\u00e9pend que de l\u2019interface de la couche inf\u00e9rieure.<\/li>\n        <li><strong>\u00c9volution ma\u00eetris\u00e9e :<\/strong> on peut changer la technologie d\u2019une couche sans tout r\u00e9\u00e9crire.<\/li>\n        <li><strong>Tests isol\u00e9s :<\/strong> on teste la logique m\u00e9tier sans forc\u00e9ment avoir besoin de lancer\n            l\u2019interface ou la base de donn\u00e9es.<\/li>\n        <li><strong>Travail en \u00e9quipe :<\/strong> les d\u00e9veloppeurs front-end et back-end peuvent avancer en parall\u00e8le.<\/li>\n      <\/ul>\n    <\/section>\n\n    <section>\n      <h3>Zoom sur la couche de pr\u00e9sentation<\/h3>\n      <p>\n        Cette couche correspond \u00e0 l\u2019interface visible, qu\u2019elle soit en console, en desktop ou en web.\n        Avec ASP.NET Core, elle comprend souvent les contr\u00f4leurs MVC, les vues, les ressources statiques (HTML, CSS, JS)\n        et peut s\u2019appuyer sur des frameworks comme Angular. L\u2019essentiel est de limiter la \u00ab\u202flogique m\u00e9tier\u202f\u00bb \u00e0 ce niveau,\n        pour ne laisser que la gestion des \u00e9crans, des formulaires et de l\u2019interaction avec l\u2019utilisateur.\n      <\/p>\n      <p>\n        <em>Exemple :<\/em> un contr\u00f4leur MVC qui re\u00e7oit une requ\u00eate, appelle la couche de service pour obtenir les donn\u00e9es,\n        puis renvoie la vue au client.\n      <\/p>\n    <\/section>\n\n    <!-- PARTIE 3 -->\n    <section>\n      <h2>3) Couche de service : le maillon essentiel<\/h2>\n      <p>\n        La couche de service agit comme un interm\u00e9diaire entre l\u2019interface et la logique m\u00e9tier.\n        Elle peut s\u2019impl\u00e9menter via des Web APIs (REST) ou des biblioth\u00e8ques partag\u00e9es. Son r\u00f4le est de\n        proposer des m\u00e9thodes claires (souvent sous forme d\u2019API) pour cr\u00e9er, lire, mettre \u00e0 jour ou supprimer\n        des entit\u00e9s, sans que la pr\u00e9sentation n\u2019ait \u00e0 conna\u00eetre les d\u00e9tails de l\u2019impl\u00e9mentation.\n      <\/p>\n      <p>\n        \u00c0 l\u2019\u00e8re du microservice, cette couche peut \u00eatre expos\u00e9e sous forme de services ind\u00e9pendants,\n        s\u00e9curis\u00e9s par des tokens JWT ou d\u2019autres m\u00e9canismes d\u2019authentification (par exemple, CAS dans le cadre d\u2019ASP.NET).\n        <strong>Le plus important<\/strong> est de prot\u00e9ger les endpoints sensibles (avec <code class=\"inline\">[Authorize]<\/code>),\n        de tracer les actions (logging) et de g\u00e9rer les transactions ou la validation des donn\u00e9es.\n      <\/p>\n      <p>\n        <em>Exemple :<\/em> un service \u00ab\u202fDemandeService\u202f\u00bb qui offre des m\u00e9thodes <code class=\"inline\">CreateRequest<\/code>,\n        <code class=\"inline\">GetRequest<\/code>, etc. Les contr\u00f4leurs ou clients s\u2019y connectent pour manipuler les donn\u00e9es,\n        sans se soucier de la logique sous-jacente.\n      <\/p>\n    <\/section>\n\n    <section>\n      <h2>Couche m\u00e9tier : le \u00ab\u202fc\u0153ur\u202f\u00bb de l\u2019application<\/h2>\n      <p>\n        C\u2019est ici qu\u2019on retrouve la logique essentielle : r\u00e8gles de calcul, validations complexes,\n        encha\u00eenements d\u2019actions. On peut l\u2019organiser selon diff\u00e9rents patterns :\n      <\/p>\n      <ul>\n        <li><strong>Transaction Script :<\/strong> m\u00e9thodes proc\u00e9durales simples, chaque m\u00e9thode correspond \u00e0 un sc\u00e9nario.<\/li>\n        <li><strong>Table Module :<\/strong> chaque classe g\u00e8re une table de la BD pour les op\u00e9rations CRUD.<\/li>\n        <li><strong>Active Record :<\/strong> un objet = une ligne en base, on peut faire <code class=\"inline\">myObjet.Save()<\/code>, etc.<\/li>\n        <li><strong>DDD (Domain Driven Design)<\/strong> : un design centr\u00e9 sur le \u00ab\u202fdomaine\u202f\u00bb et le langage m\u00e9tier.\n            Parfois plus complexe \u00e0 mettre en place, mais tr\u00e8s adapt\u00e9 aux projets exigeants.<\/li>\n      <\/ul>\n      <p>\n        Le but est d\u2019isoler ces r\u00e8gles pour pouvoir tester et faire \u00e9voluer le code m\u00e9tier ind\u00e9pendamment du reste.\n      <\/p>\n    <\/section>\n\n    <!-- PARTIE 4 -->\n    <section>\n      <h3>Couche d\u2019acc\u00e8s aux donn\u00e9es (DAL)<\/h3>\n      <p>\n        Le <em>Data Access Layer<\/em> s\u2019occupe de toute la partie \u00ab\u202fpersistante\u202f\u00bb : base de donn\u00e9es relationnelle\n        (SQL Server, PostgreSQL), NoSQL, fichiers, etc. Dans le monde .NET, on utilise souvent\n        <strong>Entity Framework Core<\/strong> ou <strong>Dapper<\/strong> pour simplifier les requ\u00eates.\n        Des patterns tels que <strong>Repository<\/strong> et <strong>Unit of Work<\/strong> permettent de factoriser\n        la logique d\u2019acc\u00e8s.\n      <\/p>\n      <p>\n        <em>Exemple :<\/em> une interface <code class=\"inline\">IRepository&lt;T&gt;<\/code> pour les op\u00e9rations CRUD g\u00e9n\u00e9riques,\n        ou encore un <code class=\"inline\">RequestRepository<\/code> sp\u00e9cialis\u00e9 qui sait g\u00e9rer les entit\u00e9s de type \u00ab\u202fDemande\u202f\u00bb.\n      <\/p>\n    <\/section>\n\n    <section>\n      <h2>Objectifs et b\u00e9n\u00e9fices d\u2019une telle architecture<\/h2>\n      <p>\n        En s\u00e9parant la pr\u00e9sentation, le service, le m\u00e9tier et les donn\u00e9es, on obtient un code plus modulable.\n        Les changements dans la base n\u2019affectent pas la pr\u00e9sentation, et vice versa. Les \u00e9quipes peuvent s\u2019organiser\n        par couche, et on dispose d\u2019une meilleur extensibilit\u00e9. Les tests unitaires et fonctionnels deviennent plus simples.\n      <\/p>\n      <p>\n        <em>Conclusion :<\/em> on passe d\u2019un code monolithique, o\u00f9 tout est imbriqu\u00e9, \u00e0 un syst\u00e8me ordonn\u00e9,\n        o\u00f9 chaque brique a son r\u00f4le. Cela facilite la maintenance \u00e0 long terme.\n      <\/p>\n    <\/section>\n\n    <section>\n      <h2>Impl\u00e9mentation moderne avec .NET Core<\/h2>\n      <p>\n        Dans le cadre d\u2019ASP.NET Core, on peut r\u00e9partir le projet en plusieurs sous-projets\u00a0:\n      <\/p>\n      <ul>\n        <li><strong>MonAppli.Web<\/strong> : Couche de pr\u00e9sentation (Razor pages, Angular, etc.)<\/li>\n        <li><strong>MonAppli.Service<\/strong> : Web APIs, classes de service exposant la logique pour le front<\/li>\n        <li><strong>MonAppli.Business<\/strong> : Le c\u0153ur m\u00e9tier, r\u00e8gles de validation, calculs, etc.<\/li>\n        <li><strong>MonAppli.DataAccess<\/strong> : Acc\u00e8s \u00e0 la BD, Repositories, EF Core, migrations<\/li>\n        <li><strong>MonAppli.Common<\/strong> : Entit\u00e9s partag\u00e9es, utilitaires, constantes globales<\/li>\n      <\/ul>\n      <p>\n        Exemple concret : un syst\u00e8me de gestion de demandes (TMS) dans lequel le locataire soumet un formulaire.\n        Le front (Web) envoie la requ\u00eate \u00e0 la couche de service, qui utilise le business pour traiter les donn\u00e9es,\n        et enfin passe la main \u00e0 la DAL pour persister en base.\n      <\/p>\n    <\/section>\n\n    <!-- PARTIE 5 -->\n    <section>\n      <h2>Approche Active Record et DDD revisit\u00e9es<\/h2>\n      <p>\n        <strong>Active Record<\/strong> : on mappe chaque classe m\u00e9tier directement \u00e0 la table correspondante.\n        Entity Framework facilite l\u2019\u00e9criture de <code class=\"inline\">DbSet&lt;T&gt;<\/code> qui repr\u00e9sente les enregistrements.\n        On peut faire <code class=\"inline\">context.MyEntities.Add(obj)<\/code> et le framework se charge de la persistance.\n      <\/p>\n      <p>\n        <strong>DDD<\/strong> (Domain Driven Design) : on part de la vision du m\u00e9tier, on cr\u00e9e des <em>Aggregates<\/em>,\n        des <em>Value Objects<\/em>, et on ne se focalise pas sur la structure physique des tables.\n        C\u2019est id\u00e9al quand le domaine est complexe et amen\u00e9 \u00e0 \u00e9voluer.\n      <\/p>\n    <\/section>\n\n    <section>\n      <h2>Couche d\u2019acc\u00e8s aux donn\u00e9es \u2013 aper\u00e7u avanc\u00e9<\/h2>\n      <p>\n        Au-del\u00e0 des simples requ\u00eates CRUD, la DAL peut g\u00e9rer les transactions et la communication\n        avec plusieurs sources de donn\u00e9es (par ex. microservices externes, API de stockage cloud).\n        L\u2019utilisation de <code class=\"inline\">UnitOfWork<\/code> permet de regrouper des s\u00e9ries d\u2019op\u00e9rations\n        pour garantir leur coh\u00e9rence. Les <strong>migrations EF Core<\/strong> simplifient la gestion du sch\u00e9ma en base.\n      <\/p>\n    <\/section>\n\n    <section>\n      <h2>Conclusion et pistes d\u2019\u00e9volution<\/h2>\n      <p>\n        En migrant d\u2019un programme monolithique vers une architecture en couches, vous gagnez en robustesse,\n        en testabilit\u00e9 et en modularit\u00e9. Vous pouvez pousser plus loin la s\u00e9paration en adoptant\n        des microservices ou en exploitant des conteneurs Docker pour isoler chaque couche.\n      <\/p>\n      <p>\n        L\u2019essentiel est de clarifier les r\u00f4les\u00a0: la pr\u00e9sentation reste l\u00e9g\u00e8re, la logique m\u00e9tier est centralis\u00e9e,\n        et l\u2019acc\u00e8s aux donn\u00e9es est encapsul\u00e9. Avec .NET Core, vous disposez d\u2019un \u00e9cosyst\u00e8me moderne\n        (Razor, Blazor, EF Core, etc.) pour impl\u00e9menter ces principes et construire des applications\n        \u00e9volutives et p\u00e9rennes.\n      <\/p>\n    <\/section>\n\n  <\/div>\n<\/body>\n<\/html>\n\n","protected":false},"excerpt":{"rendered":"<p>Refactorisation d\u2019un monolithe vers une architecture en couches \u2013 Version Actualis\u00e9e Refactorisation d\u2019un monolithe vers une architecture en couches Exercice initial Pour introduire notre d\u00e9marche, voici une situation\u202f: vous disposez d\u2019un programme regroupant toutes les fonctionnalit\u00e9s dans un seul bloc de code, sans r\u00e9elle organisation. Les vues (affichage), la logique m\u00e9tier (calculs, r\u00e8gles sp\u00e9cifiques) et l\u2019acc\u00e8s aux donn\u00e9es (requ\u00eates SQL, connexion \u00e0 la base) sont entrem\u00eal\u00e9s. Votre mission : rep\u00e9rer dans ce \u00ab\u202fmonolithe\u202f\u00bb quelles sont les parties qui correspondent respectivement \u00e0 l\u2019interface (pr\u00e9sentation), au traitement m\u00e9tier et \u00e0 la persistance de donn\u00e9es. Prenez des notes, car la suite du cours<\/p>\n","protected":false},"author":1,"featured_media":242,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[9],"tags":[],"class_list":["post-419","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-developpement-avance"],"_links":{"self":[{"href":"https:\/\/wmg-studio.com\/index.php\/wp-json\/wp\/v2\/posts\/419","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wmg-studio.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/wmg-studio.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/wmg-studio.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/wmg-studio.com\/index.php\/wp-json\/wp\/v2\/comments?post=419"}],"version-history":[{"count":10,"href":"https:\/\/wmg-studio.com\/index.php\/wp-json\/wp\/v2\/posts\/419\/revisions"}],"predecessor-version":[{"id":429,"href":"https:\/\/wmg-studio.com\/index.php\/wp-json\/wp\/v2\/posts\/419\/revisions\/429"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/wmg-studio.com\/index.php\/wp-json\/wp\/v2\/media\/242"}],"wp:attachment":[{"href":"https:\/\/wmg-studio.com\/index.php\/wp-json\/wp\/v2\/media?parent=419"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/wmg-studio.com\/index.php\/wp-json\/wp\/v2\/categories?post=419"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/wmg-studio.com\/index.php\/wp-json\/wp\/v2\/tags?post=419"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}