Patterns de développement

Documentation complète des patterns utilisés dans le projet pour garantir la cohérence et la maintenabilité du code.

Pattern Action

Le pattern Action encapsule une opération métier atomique et réutilisable. Chaque Action représente une intention métier claire (créer, modifier, supprimer, etc.).

Principes

  • Atomicité : Une Action = une opération métier
  • Réutilisabilité : Utilisable depuis n'importe où (Controller, Livewire, Commande, etc.)
  • Testabilité : Facile à tester en isolation
  • Transaction : Utilise les transactions DB pour garantir la cohérence

Convention de nommage

Format : \{Verb\}\{Entity\}Action

// Exemples
CreateFeedbackAction
UpdateFeedbackStatusAction
DeleteFeedbackAction
PublishProductAction

Structure de base

namespace App\Specifics\{ModuleName}\Actions;

use App\Models\User;
use Illuminate\Support\Facades\DB;

class CreateFeedbackAction
{
    public function execute(User $user, array $data): Feedback
    {
        return DB::transaction(function () use ($user, $data) {
            $feedback = Feedback::create([
                'user_id' => $user->id,
                'status' => FeedbackStatus::OPEN,
                ...$data,
            ]);
            
            event(new FeedbackCreated($feedback));
            
            return $feedback;
        });
    }
}

Bonnes pratiques

  • ✅ Utiliser DB::transaction() pour les opérations critiques
  • ✅ Typage strict des paramètres et du retour
  • ✅ Déclencher des Events après les actions importantes
  • ✅ Gérer les erreurs explicitement avec des exceptions
  • ❌ Éviter les Actions trop complexes (utiliser un Service)

Pattern Query

Le pattern Query encapsule la logique de récupération de données complexe. Chaque Query représente une requête spécifique avec filtres, tri, pagination, etc.

Principes

  • Spécificité : Une Query = une requête spécifique
  • Réutilisabilité : Utilisable depuis n'importe où
  • Performance : Optimisée avec eager loading
  • Flexibilité : Paramètres optionnels pour filtres

Convention de nommage

Format : Get\{Entity\}\{Context\}Query

// Exemples
GetFeedbackListQuery
GetFeedbackDetailQuery
GetPublishedPostsQuery
GetUserInvoicesQuery

Structure de base

namespace App\Specifics\{ModuleName}\Queries;

use Illuminate\Contracts\Pagination\LengthAwarePaginator;

class GetFeedbackListQuery
{
    public function execute(
        ?FeedbackType $type = null,
        ?FeedbackStatus $status = null,
        ?User $user = null,
        string $sortBy = 'created_at',
        string $sortDirection = 'desc',
        int $perPage = 15
    ): LengthAwarePaginator {
        $query = Feedback::with(['user'])
            ->withCount(['votes', 'comments']);
        
        if ($type) {
            $query->where('type', $type);
        }
        
        return $query->orderBy($sortBy, $sortDirection)
            ->paginate($perPage);
    }
}

Bonnes pratiques

  • ✅ Utiliser with() pour l'eager loading
  • ✅ Utiliser withCount() pour les statistiques
  • ✅ Paramètres optionnels avec valeurs par défaut
  • ✅ Pagination pour les listes
  • ❌ Éviter les requêtes N+1

Pattern Service

Le pattern Service orchestre plusieurs Actions et/ou Queries pour réaliser une opération métier complexe. Un Service coordonne la logique entre plusieurs composants.

Principes

  • Orchestration : Coordonne plusieurs Actions/Queries
  • Logique métier complexe : Gère les cas complexes
  • Réutilisabilité : Encapsule la logique réutilisable
  • Dependency Injection : Injecte les Actions/Queries nécessaires

Convention de nommage

Format : \{Entity\}Service ou \{Purpose\}Service

// Exemples
FeedbackService
ProductService
BlockManager
ContactSyncService

Structure de base

namespace App\Specifics\{ModuleName}\Services;

class FeedbackService
{
    public function __construct(
        private CreateFeedbackAction $createAction,
        private GetFeedbackListQuery $listQuery,
    ) {}
    
    public function createFeedback(User $user, array $data): Feedback
    {
        return $this->createAction->execute($user, $data);
    }
    
    public function listFeedbacks(array $filters = []): LengthAwarePaginator
    {
        return $this->listQuery->execute(...$filters);
    }
}

Quand utiliser un Service

  • ✅ Orchestrer plusieurs Actions/Queries
  • ✅ Logique métier complexe
  • ✅ Synchronisation de données
  • ❌ Opérations atomiques simples (utiliser une Action)
  • ❌ Requêtes simples (utiliser une Query)

Pattern DTO (Data Transfer Object)

Le pattern DTO encapsule des données complexes pour les transférer entre les couches de l'application. Un DTO garantit la structure et la validation des données.

Principes

  • Immutabilité : Propriétés readonly pour garantir l'immutabilité
  • Typage strict : Types explicites pour toutes les propriétés
  • Validation : Structure garantie
  • Sérialisation : Méthode toArray() pour la conversion

Convention de nommage

Format : \{Action\}\{Entity\}Data

// Exemples
CreateRoomData
UpdateProductData
RoomTokenData

Structure de base

namespace App\Specifics\{ModuleName}\DTO;

class CreateRoomData
{
    public function __construct(
        public readonly string $name,
        public readonly ?string $description = null,
        public readonly array $metadata = [],
    ) {}
    
    public function toArray(): array
    {
        return [
            'name' => $this->name,
            'description' => $this->description,
            'metadata' => $this->metadata,
        ];
    }
    
    public static function fromArray(array $data): self
    {
        return new self(
            name: $data['name'],
            description: $data['description'] ?? null,
            metadata: $data['metadata'] ?? [],
        );
    }
}

Quand utiliser un DTO

  • ✅ Transférer des données complexes entre couches
  • ✅ Garantir la structure des données
  • ✅ Validation centralisée
  • ❌ Données simples (utiliser un tableau associatif)
  • ❌ Logique métier (utiliser une Action/Service)

Ressources supplémentaires

Pour plus de détails sur chaque pattern, consultez la documentation complète dans docs/patterns/.

Prendre rendez-vous