Pattern Repository et Unit of Work - Exemple concret : Plateforme e-commerce
Étude de cas : découvrez l’utilisation conjointe des deux patterns pour gérer commandes, stocks, et paiements dans une plateforme e-commerce.
Sommaire
Cet article fait partie d'une série de plusieurs articles sur les patterns Repository et Unit of Work :
- Introduction générale et utilité des patterns dans les projets d'entreprise
- Détail du Pattern Repository
- Détail du Pattern Unit of Work
- Compatibilité et limitations avec les microservices
- Exemple concret : Utilisation conjointe dans une plateforme e-commerce
- Conclusion et retour d'expérience
Prenons l’exemple d’une application de gestion de commandes dans une plateforme e-commerce. Voici comment les patterns Repository et Unit of Work peuvent être utilisés ensemble :
Scénario : Création d’une commande
- Une commande contient des informations sur le client, les articles commandés, et le montant total.
- L’opération doit :
- Créer une nouvelle commande.
- Mettre à jour l’inventaire pour les articles concernés.
- Enregistrer la transaction de paiement.
Code d’implémentation
public class OrderService
{
private readonly IUnitOfWork _unitOfWork;
public OrderService(IUnitOfWork unitOfWork)
{
// Injection de l'UnitOfWork pour coordonner les transactions
_unitOfWork = unitOfWork;
}
public async Task<bool> CreateOrderAsync(Order order, IEnumerable<OrderItem> orderItems)
{
try
{
// Étape 1 : Ajouter la commande
await _unitOfWork.Repository<Order>().AddAsync(order);
// Étape 2 : Mettre à jour l'inventaire pour chaque article commandé
foreach (var item in orderItems)
{
var product = await _unitOfWork.Repository<Product>().GetByIdAsync(item.ProductId);
if (product == null || product.Stock < item.Quantity)
{
throw new InvalidOperationException("Stock insuffisant.");
}
product.Stock -= item.Quantity; // Réduction du stock
_unitOfWork.Repository<Product>().Update(product);
}
// Étape 3 : Enregistrer la transaction de paiement
var payment = new Payment
{
OrderId = order.Id,
Amount = orderItems.Sum(i => i.Price * i.Quantity),
PaymentDate = DateTime.UtcNow
};
await _unitOfWork.Repository<Payment>().AddAsync(payment);
// Étape 4 : Sauvegarder toutes les modifications dans une transaction unique
await _unitOfWork.SaveChangesAsync();
return true; // Retourne vrai si tout s'est bien passé
}
catch (Exception)
{
// Gestion des erreurs : la transaction sera annulée en cas d'exception
throw;
}
}
}
Explications
- Isolation de la logique : Chaque repository gère une entité spécifique (Order, Product, Payment).
- Transaction unique : Toutes les opérations sont regroupées via l’Unit of Work, garantissant la cohérence des données.
- Facilité de maintenance : La logique d’application reste claire et bien structurée.
A suivre : Conclusion et retour d'expérience