#Action vs Service dans Laravel
Service pour les capacités réutilisables. Action pour les opérations métier précises.
Quand un Controller commence à contenir trop de logique métier, il est temps de l'extraire.
Deux approches sont particulièrement courantes dans Laravel :
- Service
- Action
Mais lequel choisir ?
#Le Service
Un Service regroupe généralement plusieurs opérations liées au même domaine.
1class PaymentService2{3 public function charge(Order $order)4 {5 // ...6 }78 public function refund(Order $order)9 {10 // ...11 }1213 public function verify(Order $order)14 {15 // ...16 }17}1class PaymentService2{3 public function charge(Order $order)4 {5 // ...6 }78 public function refund(Order $order)9 {10 // ...11 }1213 public function verify(Order $order)14 {15 // ...16 }17}
Ici, on regroupe plusieurs capacités liées au paiement :
1PaymentService2├── charge()3├── refund()4└── verify()1PaymentService2├── charge()3├── refund()4└── verify()
C'est particulièrement utile lorsque ces fonctionnalités doivent être réutilisées à plusieurs endroits.
#L'Action
Une Action représente une opération métier précise.
1class CreateOrderAction2{3 public function execute(array $data): Order4 {5 // ...6 }7}1class CreateOrderAction2{3 public function execute(array $data): Order4 {5 // ...6 }7}
Au lieu d'avoir un énorme OrderService :
1OrderService2├── create()3├── update()4├── cancel()5├── refund()6└── ...1OrderService2├── create()3├── update()4├── cancel()5├── refund()6└── ...
On peut séparer les opérations :
1CreateOrderAction2UpdateOrderAction3CancelOrderAction4RefundOrderAction1CreateOrderAction2UpdateOrderAction3CancelOrderAction4RefundOrderAction
Chaque classe a ainsi une responsabilité clairement définie.
#La différence
La question à se poser est simple :
Est-ce une capacité ou une opération ?
#Capacité → Service
1PaymentService2EmailService3FileStorageService1PaymentService2EmailService3FileStorageService
#Opération métier → Action
1CreateOrderAction2ApproveInvoiceAction3CancelSubscriptionAction1CreateOrderAction2ApproveInvoiceAction3CancelSubscriptionAction
#Pourquoi pas utiliser les deux ?
Les deux patterns peuvent parfaitement fonctionner ensemble.
Par exemple :
1OrderController2 ↓3CreateOrderAction4 ↓5 ┌───────────────┐6 ↓ ↓7PaymentService InventoryService1OrderController2 ↓3CreateOrderAction4 ↓5 ┌───────────────┐6 ↓ ↓7PaymentService InventoryService
L'Action orchestre le cas d'utilisation.
Les Services fournissent les capacités nécessaires.
#En résumé
| Service | Action |
|---|---|
| Regroupe des capacités | Représente une opération |
| Plusieurs méthodes | Généralement une méthode |
PaymentService |
CreateOrderAction |
| Orienté capacité / domaine | Orienté cas d'utilisation |
Il n'y a donc pas de pattern universellement meilleur.
Service pour les capacités réutilisables. Action pour les opérations métier précises.
Et dans une application complexe, les deux peuvent parfaitement cohabiter.