Comment afficher joliment du JSON en PHP : guide complet pour débutants

Formateur Python en ligne pour débutants

Apprenez Python facilement sans surcharge théorique. Résolvez des tâches pratiques avec vérification automatique et écrivez du code directement dans le navigateur.

Start Course

Introduction : Pourquoi votre application n'est pas sa base de données

\n\n

Imaginez que vous construisez une maison. Fondations, murs, toit — tout est bien pensé. Mais un an plus tard, vous décidez de changer le câblage électrique. Et là, vous découvrez que les fils sont noyés dans le béton et les prises soudées aux armatures. Pour remplacer un interrupteur, vous devez démolir la moitié de la maison.

\n\n

C'est à peu près à quoi ressemble une application Java classique, où la logique métier est étroitement liée au framework, à la base de données ou au contrôleur REST. Vous voulez passer de PostgreSQL à MongoDB ? Réécrire les contrôleurs de Spring MVC à JAX-RS ? Bienvenue dans l'enfer du refactoring.

\n\n

La solution est l'architecture hexagonale (également appelée "Ports and Adapters", ou "Clean Architecture" dans l'interprétation d'Alistair Cockburn). Ce n'est pas une baguette magique, mais c'est un moyen de rendre votre application flexible, testable et indépendante du monde extérieur.

\n\n

Aujourd'hui, nous allons décortiquer l'architecture hexagonale en Java avec des exemples de code concrets, sans bla-bla ni raisonnement abstrait. C'est parti.

\n\n

Qu'est-ce que l'architecture hexagonale (Ports and Adapters) ?

\n\n

L'essence est simple : votre application est un noyau qui contient la logique métier. Autour du noyau se trouve un "hexagone" (en réalité un nombre arbitraire de côtés), à travers lequel le monde extérieur communique avec le noyau.

\n\n

Chaque côté a son propre port (interface). Et un adaptateur est l'implémentation du port pour une technologie spécifique. Par exemple :

\n
    \n
  • Port "UserRepository" — adaptateur "JpaUserRepository" ou "MongoUserRepository"
  • \n
  • Port "SendNotification" — adaptateur "EmailSender" ou "SmsSender"
  • \n
\n\n

La règle principale : le noyau ne connaît rien des bibliothèques externes, des bases de données ou des frameworks web. Il ne connaît que ses ports (interfaces). Cela offre plusieurs avantages :

\n
    \n
  • Indépendance vis-à-vis de l'infrastructure — changez la base de données ou le framework sans toucher à la logique.
  • \n
  • Testabilité — la logique métier peut être testée sans démarrer le contexte Spring ou la base de données.
  • \n
  • Lisibilité — le code du noyau raconte l'histoire du domaine, pas les détails techniques.
  • \n
\n\n

Structure du projet : Comment organiser le code

\n\n

Il n'existe pas de structure de packages unique et correcte, mais je propose une option éprouvée basée sur les principes du DDD (Domain-Driven Design) et de l'architecture hexagonale :

\n\n
com.example.app\n├── domain\n│   ├── model          // Entités, Objets Valeur\n│   ├── port           // Interfaces de port (entrants/sortants)\n│   └── service        // Services métier (cas d'utilisation)\n├── adapter\n│   ├── inbound\n│   │   ├── rest       // Contrôleurs REST (adaptateurs entrants)\n│   │   └── messaging  // Écouteurs Kafka/RabbitMQ\n│   └── outbound\n│       ├── persistence // Référentiels JPA, JDBC, MongoDB\n│       └── client      // Clients HTTP, API externes\n└── config             // Configuration Spring (si vous l'utilisez)\n
\n\n

Remarque : domain n'importe rien depuis adapter. C'est crucial. Si vous voyez @Entity ou @RestController dans le domaine, l'architecture est cassée.

\n\n

Exemple : Système de gestion des commandes

\n\n

Concevons un système simple : un utilisateur peut créer une commande, et le système vérifie la disponibilité des produits dans l'entrepôt et envoie une notification.

\n\n

Étape 1. Modèle du domaine (domain/model)

\n\n
// Order.java\npublic class Order {\n    private final OrderId id;\n    private final List<OrderItem> items;\n    private OrderStatus status;\n\n    public Order(List<OrderItem> items) {\n        this.id = new OrderId(UUID.randomUUID().toString());\n        this.items = Collections.unmodifiableList(items);\n        this.status = OrderStatus.PENDING;\n    }\n\n    public void confirm() {\n        if (status != OrderStatus.PENDING) {\n            throw new IllegalStateException("Only PENDING orders can be confirmed");\n        }\n        this.status = Ord                

Blogs

Book Recommendations