🎯 Principes SOLID en PHP Symfony

1. Single Responsibility Principle (SRP)

❌ Une classe fait trop de choses
class Order
{
    public function calculateTotal(): float { /* ... */ }
    public function saveToDatabase(): void { /* ... */ }
    public function sendEmail(): void { /* ... */ }
    public function generatePDF(): void { /* ... */ }
}
✅ Chaque classe a une responsabilité unique
class OrderCalculator
{
    public function calculateTotal(array $items): float
    {
        return array_sum(array_column($items, 'price'));
    }
}

class OrderRepository
{
    public function save(Order $order): void { /* ... */ }
}

class EmailNotifier
{
    public function sendConfirmation(Order $order): void { /* ... */ }
}

2. Open/Closed Principle (OCP)

❌ Modification du code existant pour ajouter une fonctionnalité
class PaymentProcessor
{
    public function process(string $type, float $amount): bool
    {
        if ($type === 'credit_card') {
            // Process credit card
        } elseif ($type === 'paypal') {
            // Process PayPal
        }
        // Ajouter un nouveau type = modifier cette classe
    }
}
✅ Extension par polymorphisme
interface PaymentMethod
{
    public function process(float $amount): bool;
}

class CreditCardPayment implements PaymentMethod
{
    public function process(float $amount): bool { /* ... */ }
}

class PayPalPayment implements PaymentMethod
{
    public function process(float $amount): bool { /* ... */ }
}

class PaymentProcessor
{
    public function __construct(private PaymentMethod $method) {}
    
    public function pay(float $amount): bool
    {
        return $this->method->process($amount);
    }
}

3. Liskov Substitution Principle (LSP)

❌ Sous-classe qui viole le contrat de la classe parent
class Bird
{
    public function fly(): void { /* fly */ }
}

class Penguin extends Bird
{
    public function fly(): void
    {
        throw new Exception("Les pingouins ne volent pas!");
    }
}
✅ Hiérarchie respectueuse du comportement
abstract class Bird
{
    abstract public function eat(): void;
}

class Sparrow extends Bird
{
    public function eat(): void { /* eat */ }
    public function fly(): void { /* fly */ }
}

class Penguin extends Bird
{
    public function eat(): void { /* eat */ }
    public function swim(): void { /* swim */ }
}

4. Interface Segregation Principle (ISP)

❌ Interface trop large
interface Worker
{
    public function work(): void;
    public function eat(): void;
    public function sleep(): void;
}

class Robot implements Worker
{
    public function work(): void { /* work */ }
    public function eat(): void { /* Robot ne mange pas! */ }
    public function sleep(): void { /* Robot ne dort pas! */ }
}
✅ Interfaces spécifiques et cohésives
interface Readable
{
    public function read(): string;
}

interface Writable
{
    public function write(string $data): void;
}

class FileManager implements Readable, Writable
{
    public function read(): string { return "data"; }
    public function write(string $data): void { /* write */ }
}

class LogReader implements Readable
{
    public function read(): string { return "logs"; }
}

5. Dependency Inversion Principle (DIP)

❌ Dépendance directe sur une implémentation concrète
class UserService
{
    private FileLogger $logger;
    
    public function __construct()
    {
        $this->logger = new FileLogger(); // Couplage fort
    }
    
    public function createUser(string $name): void
    {
        $this->logger->log("User created");
    }
}
✅ Dépendance sur une abstraction
interface LoggerInterface
{
    public function log(string $message): void;
}

class FileLogger implements LoggerInterface
{
    public function log(string $message): void { /* ... */ }
}

class UserService
{
    public function __construct(private LoggerInterface $logger) {}
    
    public function createUser(string $name): void
    {
        $this->logger->log("User created: $name");
    }
}

# services.yaml
# App\LoggerInterface: '@App\FileLogger'