Application
Après avoir exploré le Domain — le cœur métier ❤️ — nous allons maintenant nous intéresser à la couche Application.
Si le Domain définit ce qui est vrai dans le métier, la couche Application définit ce que le système fait concrètement 🎯.
Elle orchestre les cas d’usage, coordonne les entités du Domain et fait le lien entre le cœur métier et le monde extérieur, sans jamais dépendre de la technique.
4.1. Qu’est-ce que la couche Application ?
La couche Application est responsable de la logique applicative.
Elle sert principalement à :
- Orchestrer les Use Cases
- Définir des interfaces (ports) vers l’extérieur
- Appliquer des règles liées au contexte applicatif
- Coordonner plusieurs objets du Domain
⚠️ Point clé :
La couche Application dépend du Domain, mais ne dépend jamais de l’Infrastructure ni de la Presentation.
4.2. Rôle de la couche Application dans l’architecture
On peut résumer son rôle ainsi :
Presentation ──► Application ──► Domain
▲
│
Infrastructure
👉 Elle est le point de passage obligé entre l’extérieur et le Domain.
4.3. Les composants principaux
La couche Application est généralement composée de deux types d’éléments :
4.3.1. Les Use Cases (Application Services)
Les Use Cases représentent les scénarios métiers que l’application doit gérer.
Ils répondent à des questions très concrètes :
- Comment créer un utilisateur ?
- Comment passer une commande ?
- Comment valider un paiement ?
👉 Un Use Case raconte une histoire métier précise, du début à la fin.
4.3.2. Les Interfaces (Ports)
La couche Application définit des interfaces pour tout ce qui sort de son périmètre :
IUserRepositoryIOrderRepositoryIPaymentGateway
Ces interfaces sont appelées ports.
- Elles sont définies côté Application
- Elles sont implémentées côté Infrastructure
Ainsi, l’Application dépend uniquement d’abstractions, jamais de détails techniques.
4.4. Exemple simple : créer un utilisateur
Voici un Use Case minimaliste illustrant ce principe.
// Port défini dans la couche Application
public interface IUserRepository
{
User? GetByEmail(EmailAddress email);
void Add(User user);
}
// Use Case
public class CreateUserUseCase
{
private readonly IUserRepository _userRepository;
public CreateUserUseCase(IUserRepository userRepository)
{
_userRepository = userRepository;
}
public void Execute(string email)
{
var emailAddress = new EmailAddress(email);
if (_userRepository.GetByEmail(emailAddress) != null)
throw new InvalidOperationException("Un utilisateur avec cet email existe déjà.");
var user = new User(Guid.NewGuid(), emailAddress);
_userRepository.Add(user);
}
}
Ce qui est important ici
- Le Use Case oriente le scénario
- Les règles métier vivent dans le Domain (
User,EmailAddress) - La persistance est abstraite via
IUserRepository - L’Infrastructure interviendra plus tard pour l’implémentation
4.5. Exemple : coordination de plusieurs entités
La couche Application est aussi responsable de la coordination.
public class PlaceOrderUseCase
{
private readonly IOrderRepository _orderRepository;
private readonly IUserRepository _userRepository;
public PlaceOrderUseCase(IOrderRepository orderRepository, IUserRepository userRepository)
{
_orderRepository = orderRepository;
_userRepository = userRepository;
}
public void Execute(Guid userId, List<OrderItem> items)
{
var user = _userRepository.GetById(userId)
?? throw new InvalidOperationException("Utilisateur introuvable.");
var order = new Order(items, hasDiscount: false);
var orderService = new OrderService();
var total = orderService.CalculateTotal(order);
// Règles applicatives spécifiques (ex : promotions, seuils, notifications…)
_orderRepository.Add(order);
}
}
👉 Ici, le Use Case :
- coordonne plusieurs entités
- appelle un service de domaine
- applique éventuellement des règles propres à l’application
4.6. Bonnes pratiques pour la couche Application
Quelques règles simples pour garder une couche Application saine 🌱 :
- Un Use Case = une intention métier claire
- Pas de logique technique
- Toute dépendance externe passe par une interface
- Des classes simples, faciles à lire et à tester
👉 Si un Use Case devient trop complexe, c’est souvent le signe qu’une règle métier devrait vivre dans le Domain.