> ## Documentation Index
> Fetch the complete documentation index at: https://docs.arkatech.fr/llms.txt
> Use this file to discover all available pages before exploring further.

# 06/02 - Clean code

## 1. Le Nommage : Soyez Expressifs

Le nom d’une variable ou d’une fonction doit dire **pourquoi** elle existe, **ce qu’elle fait** et **comment** on l’utilise.

❌ **Mauvais (Peu clair)**

```php theme={null}
// On ne sait pas ce que sont 'p', 'l' ou 'v'
$p = 150;
$l = array_reduce($items, fn($a, $i) => $a + $i->price, 0);

if ($l > $p) {
    $v = $l * 0.1;
    $t = $l - $v;
    echo $t;
}
```

✅ **Bon (Explicite)**

```php theme={null}
const MINIMUM_ORDER_FOR_DISCOUNT = 150;
const DISCOUNT_RATE_PERCENTAGE = 0.1; // 10%

$orderTotal = array_reduce($cartItems, fn($total, $item) => $total + $item->price, 0);

if ($orderTotal > MINIMUM_ORDER_FOR_DISCOUNT) {
    $discountAmount = $orderTotal * DISCOUNT_RATE_PERCENTAGE;
    $finalPriceWithDiscount = $orderTotal - $discountAmount;
    
    echo $finalPriceWithDiscount;
}
```

## 2. Les Fonctions : Faites une seule chose (SRP)

Une fonction (ou un service) doit avoir une seule responsabilité. Si tu as besoin du mot “et” pour décrire ce que fait ta fonction, c’est qu’elle doit être découpée.

❌ **Mauvais (Symfony - Service “fourre-tout”)**

```php theme={null}
// Un service qui fait trop de choses
public function handleUserSignup(array $data): User
{
    // 1. Logique de validation métier
    if (strlen($data['password']) < 8) {
        throw new \Exception("Trop court");
    }

    // 2. Persistance (Base de données)
    $user = new User($data);
    $this->entityManager->persist($user);
    $this->entityManager->flush();

    // 3. Logique de communication (Email)
    $email = (new Email())
        ->to($user->getEmail())
        ->subject('Bienvenue !')
        ->text("Bienvenue " . $user->getFirstName());
    $this->mailer->send($email);

    // 4. Logique de marketing (Tracker)
    $this->analytics->track('user_created', ['id' => $user->getId()]);

    return $user;
}
```

✅ **Bon (Responsabilités séparées)**

**Le Service Principal (Responsabilité : Créer)**

Il ne sait pas qu’un mail doit être envoyé, il dit juste : “J’ai fini mon travail”.

```php theme={null}
public function createUser(UserDto $data): User
{
    $user = $this->userRepository->save($data);

    // On émet un événement. C'est tout.
    $this->eventDispatcher->dispatch(new UserCreatedEvent($user));

    return $user;
}
```

**Le Listener d’Email (Responsabilité : Communiquer)**

Ce code vit dans un autre fichier. Il ne s’occupe que de la mise en forme et de l’envoi.

```php theme={null}
#[AsEventListener(event: UserCreatedEvent::class)]
public function onUserCreated(UserCreatedEvent $event): void
{
    $user = $event->getUser();
    $welcomeMessage = $this->templateService->buildWelcome($user->getName());
    $this->emailService->send($user->getEmail(), "Bienvenue", $welcomeMessage);
}
```

**Le Listener Analytics (Responsabilité : Analyser)**

Si demain on veut arrêter de tracker les utilisateurs, on supprime juste ce bloc, sans toucher au code de création d’utilisateur.

```php theme={null}
#[AsEventListener(event: UserCreatedEvent::class)]
public function logUserAnalytics(UserCreatedEvent $event): void
{
    $this->analytics->track('new_registration', ['userId' => $event->getUser()->getId()]);
}
```

## 3. Le Principe de “Don’t Repeat Yourself” (DRY)

Évite de copier-coller. Si tu vois la même logique deux fois, centralise-la.

❌ **Mauvais (Twig/PHP - Duplication)**

```html theme={null}
<div style="padding: 10px; border: 1px solid black;">Profil Utilisateur</div>

<div style="padding: 10px; border: 1px solid black;">Profil Admin</div>
```

✅ **Bon (Composant/Inclusion réutilisable)**

```html theme={null}
<div class="card-styles">{{ content }}</div>

{% include '_card.html.twig' with {'content': 'Profil Utilisateur'} %}
```

## 4. Les Commentaires : Le code doit s’expliquer seul

N’utilise les commentaires que pour expliquer le **“Pourquoi”** (décisions complexes), jamais le **“Quoi”**. Si le code est complexe, renomme tes variables.

❌ **Mauvais**

```php theme={null}
// Vérifie si l'utilisateur est actif et a plus de 18 ans
if ($u->getStatus() === 'active' && $u->getAge() > 18) { ... }
```

✅ **Bon**

```php theme={null}
$isEligibleAdult = $user->isActive() && $user->isAdult();
if ($isEligibleAdult) { ... }
```

## 5. Les Principes SOLID (Le “S” et le “O”)

| **Principe**              | **Définition simple**                                                 |
| :------------------------ | :-------------------------------------------------------------------- |
| **S**ingle Responsibility | Un fichier = Une mission.                                             |
| **O**pen/Closed           | Ton code doit être ouvert à l’extension mais fermé à la modification. |

### S : Single Responsibility Principle (SRP)

“Une classe ou une fonction ne devrait avoir qu’une seule raison de changer.”

Si ton fichier s’occupe à la fois de calculer un prix, de formater une date et d’envoyer une notification, il a **trop de raisons** de changer.

❌ **Le mauvais élève (La classe “Dieu”)**

```php theme={null}
class Invoice {
    public function calculateTotal(array $items) { /* ... */ }
    public function generateHTML() { /* ... */ } // ❌ Affichage
    public function saveToDatabase() { /* ... */ } // ❌ Persistance
}
```

✅ **Le bon élève (Découpage)**

* **InvoiceCalculator** : Ne connaît que les chiffres.
* **InvoiceRenderer** : Ne connaît que le HTML/PDF (Twig).
* **InvoiceRepository** : Ne connaît que la base de données (Doctrine).

### O : Open/Closed Principle (OCP)

“Ouvert à l’extension, fermé à la modification.”

Tu devrais pouvoir ajouter une nouvelle fonctionnalité **sans modifier le code existant**.

❌ **Mauvais : Le switch infini**

```php theme={null}
// Si on veut ajouter "Espagne", on DOIT modifier cette fonction
function getShippingCost(string $country): int {
    if ($country === 'France') return 5;
    if ($country === 'Belgium') return 7;
    if ($country === 'USA') return 15;
    // ... Début de l'enfer
}
```

✅ **Bon : L’approche par polymorphisme**

```php theme={null}
// 1. On définit une règle générale
interface ShippingStrategy {
    public function calculate(): int;
}

// 2. On crée des extensions pour chaque cas
class FranceShipping implements ShippingStrategy {
    public function calculate(): int { return 5; }
}

class USAShipping implements ShippingStrategy {
    public function calculate(): int { return 15; }
}

// 3. Le code principal est "fermé" : il ne change jamais.
function displayCost(ShippingStrategy $strategy) {
    echo $strategy->calculate();
}
```

## 6. Structure et Clean Architecture (Symfony)

En Symfony, respectez la hiérarchie pour ne pas transformer les contrôleurs en usines à gaz.

**Règle d’or :**

* **Controller** : Reçoit la `Request`, valide les données (`Form` ou `MapRequestPayload`), renvoie la `Response`. Pas de logique métier.
* **Service** : Contient toute la logique métier.
* **Repository/Entity** : Gère l’accès aux données via Doctrine.

**Exemple de structure propre :**

```
src/
└── User/
    ├── Controller/       # Contrôleurs Web/API
    ├── Dto/              # Objets de transfert de données
    ├── Entity/           # Entités Doctrine
    ├── EventListener/    # Gestion des événements
    ├── Repository/       # Requêtes SQL (QueryBuilder)
    └── Service/          # Logique métier pure
```

## Résumé pour l’équipe

* **Lisibilité > Brièveté** : On s’en fiche que le code soit court, on veut qu’il soit clair.
* **Petit, c’est mieux** : Des méthodes de moins de 20 lignes, des classes spécialisées.
* **Supprime le code mort** : Si une fonction n’est plus utilisée, on l’efface (Git s'en souvient).
