Initial commit
This commit is contained in:
191
skills/make-invalide/README.md
Normal file
191
skills/make-invalide/README.md
Normal file
@@ -0,0 +1,191 @@
|
||||
# Framework Make Invalide
|
||||
|
||||
Génère une classe Invalide pour exceptions métier d'une entité.
|
||||
|
||||
## Vue d'ensemble
|
||||
Cette skill crée une classe Invalide qui encapsule les exceptions métier spécifiques à une entité selon les principes Elegant Objects.
|
||||
|
||||
## Caractéristiques
|
||||
|
||||
### Classe Invalide générée
|
||||
- Classe `final`
|
||||
- Constructeur privé
|
||||
- Factory statique `new()`
|
||||
- Encapsule l'entité
|
||||
- Base pour méthodes factory d'exceptions
|
||||
|
||||
## Utilisation
|
||||
|
||||
```bash
|
||||
Use skill framework:make:invalide
|
||||
```
|
||||
|
||||
Vous serez invité à fournir le nom de l'entité.
|
||||
|
||||
## Exemple d'utilisation
|
||||
|
||||
```bash
|
||||
EntityName: Product
|
||||
```
|
||||
|
||||
Génère :
|
||||
```php
|
||||
// src/Invalide/ProductInvalide.php
|
||||
final class ProductInvalide
|
||||
{
|
||||
private function __construct(
|
||||
private Product $product,
|
||||
) {}
|
||||
|
||||
public static function new(Product $product): self
|
||||
{
|
||||
return new self(product: $product);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Structure créée
|
||||
|
||||
```
|
||||
src/
|
||||
└── Invalide/
|
||||
└── {EntityName}Invalide.php
|
||||
```
|
||||
|
||||
## Prérequis
|
||||
- L'entité doit exister dans `src/Entity/{EntityName}.php`
|
||||
|
||||
## Usage recommandé
|
||||
|
||||
### Dans l'entité
|
||||
```php
|
||||
final class Product implements InvalideInterface
|
||||
{
|
||||
public function invalide(): ProductInvalide
|
||||
{
|
||||
return ProductInvalide::new(product: $this);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Enrichissement avec exceptions métier
|
||||
|
||||
```php
|
||||
final class ProductInvalide
|
||||
{
|
||||
private function __construct(
|
||||
private Product $product,
|
||||
) {}
|
||||
|
||||
public static function new(Product $product): self
|
||||
{
|
||||
return new self(product: $product);
|
||||
}
|
||||
|
||||
// Exceptions de validation
|
||||
public static function carNomVide(): \InvalidArgumentException
|
||||
{
|
||||
return new \InvalidArgumentException(
|
||||
'Le nom du produit ne peut pas être vide'
|
||||
);
|
||||
}
|
||||
|
||||
public static function carPrixNegatif(): \InvalidArgumentException
|
||||
{
|
||||
return new \InvalidArgumentException(
|
||||
'Le prix ne peut pas être négatif'
|
||||
);
|
||||
}
|
||||
|
||||
// Exceptions métier
|
||||
public static function carStockInsuffisant(
|
||||
int $demande,
|
||||
int $disponible
|
||||
): \DomainException {
|
||||
return new \DomainException(
|
||||
sprintf(
|
||||
'Stock insuffisant: %d demandé, %d disponible',
|
||||
$demande,
|
||||
$disponible
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public static function carProduitInactif(string $id): \DomainException
|
||||
{
|
||||
return new \DomainException(
|
||||
sprintf('Le produit %s est inactif', $id)
|
||||
);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Utilisation dans le code
|
||||
|
||||
```php
|
||||
// Validation dans factory
|
||||
public static function create(
|
||||
Uuid $id,
|
||||
string $name,
|
||||
float $price
|
||||
): self {
|
||||
if ('' === $name) {
|
||||
throw ProductInvalide::carNomVide();
|
||||
}
|
||||
if ($price < 0) {
|
||||
throw ProductInvalide::carPrixNegatif();
|
||||
}
|
||||
return new self(id: $id, name: $name, price: $price);
|
||||
}
|
||||
|
||||
// Validation métier
|
||||
public function decreaseStock(int $quantity): void
|
||||
{
|
||||
if (!$this->isActive) {
|
||||
throw ProductInvalide::carProduitInactif($this->id->toRfc4122());
|
||||
}
|
||||
if ($this->stock < $quantity) {
|
||||
throw ProductInvalide::carStockInsuffisant(
|
||||
demande: $quantity,
|
||||
disponible: $this->stock
|
||||
);
|
||||
}
|
||||
$this->stock -= $quantity;
|
||||
}
|
||||
```
|
||||
|
||||
## Conventions de nommage
|
||||
|
||||
### Méthodes factory
|
||||
- Préfixe : `car` (français)
|
||||
- Format : `carRaisonDeLErreur`
|
||||
- Exemples :
|
||||
- `carNomVide()`
|
||||
- `carEmailInvalide()`
|
||||
- `carStockInsuffisant()`
|
||||
- `carProduitInactif()`
|
||||
|
||||
### Messages d'exception
|
||||
- Pas de point final
|
||||
- Inclure le contexte maximum
|
||||
- Une seule phrase sans points internes
|
||||
- Exemples :
|
||||
- ✅ `'Le nom du produit ne peut pas être vide'`
|
||||
- ✅ `'Stock insuffisant: 5 demandé, 2 disponible'`
|
||||
- ❌ `'Erreur.'`
|
||||
- ❌ `'Le nom est vide. Veuillez le renseigner.'`
|
||||
|
||||
## Types d'exceptions recommandés
|
||||
|
||||
- `\InvalidArgumentException` - Validation d'arguments
|
||||
- `\DomainException` - Règles métier
|
||||
- `\LogicException` - État incohérent
|
||||
- `\RuntimeException` - Erreur runtime
|
||||
|
||||
## Principes Elegant Objects appliqués
|
||||
- Classe finale
|
||||
- Constructeur privé
|
||||
- Factory statiques
|
||||
- Fail fast
|
||||
- Messages d'erreur avec contexte
|
||||
- Exceptions spécifiques au domaine
|
||||
185
skills/make-invalide/SKILL.md
Normal file
185
skills/make-invalide/SKILL.md
Normal file
@@ -0,0 +1,185 @@
|
||||
---
|
||||
name: framework:make:invalide
|
||||
description: Génère classe Invalide (exceptions métier)
|
||||
license: MIT
|
||||
version: 1.0.0
|
||||
---
|
||||
|
||||
# Framework Make Invalide Skill
|
||||
|
||||
## Description
|
||||
Génère une classe Invalide pour gérer les exceptions métier d'une entité.
|
||||
|
||||
La classe Invalide encapsule l'entité et fournit des factory methods pour créer des exceptions spécifiques au contexte métier.
|
||||
|
||||
## Usage
|
||||
```
|
||||
Use skill framework:make:invalide
|
||||
|
||||
Vous serez invité à fournir :
|
||||
- Le nom de l'entité (ex: Product, User, Order)
|
||||
```
|
||||
|
||||
## Templates
|
||||
- `Invalide/UtilisateurInvalide.php` - Template de classe Invalide
|
||||
|
||||
## Variables requises
|
||||
- **{EntityName}** - Nom de l'entité en PascalCase (ex: Utilisateur, Product)
|
||||
- **{entityName}** - Nom de l'entité en camelCase (ex: utilisateur, product)
|
||||
- **{namespace}** - Namespace du projet (défaut: App)
|
||||
|
||||
## Dépendances
|
||||
- Requiert que l'entité existe dans `src/Entity/{EntityName}.php`
|
||||
|
||||
## Outputs
|
||||
- `src/Invalide/{EntityName}Invalide.php`
|
||||
|
||||
## Workflow
|
||||
|
||||
1. Demander le nom de l'entité (EntityName)
|
||||
2. Vérifier que l'entité existe dans `src/Entity/{EntityName}.php`
|
||||
- Si non : arrêter et demander de créer l'entité d'abord
|
||||
3. Générer la classe Invalide depuis le template :
|
||||
- Remplacer `{EntityName}` par le nom fourni
|
||||
- Remplacer `{entityName}` par la version camelCase
|
||||
4. Afficher le fichier créé
|
||||
|
||||
## Patterns appliqués
|
||||
|
||||
### Classe Invalide
|
||||
- Classe `final`
|
||||
- Constructeur privé
|
||||
- Factory statique `new()` pour instanciation
|
||||
- Propriété privée de type entité
|
||||
- Méthodes factory statiques pour exceptions spécifiques
|
||||
|
||||
## Exemple
|
||||
|
||||
```bash
|
||||
Use skill framework:make:invalide
|
||||
|
||||
# Saisies utilisateur :
|
||||
EntityName: Product
|
||||
|
||||
# Résultat :
|
||||
✓ src/Invalide/ProductInvalide.php
|
||||
```
|
||||
|
||||
Fichier généré :
|
||||
```php
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Invalide;
|
||||
|
||||
use App\Entity\Product;
|
||||
|
||||
final class ProductInvalide
|
||||
{
|
||||
private function __construct(
|
||||
private Product $product,
|
||||
) {
|
||||
}
|
||||
|
||||
public static function new(
|
||||
Product $product,
|
||||
): self {
|
||||
return new self(
|
||||
product: $product,
|
||||
);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Usage dans l'entité
|
||||
|
||||
L'entité doit implémenter la méthode `invalide()` :
|
||||
|
||||
```php
|
||||
public function invalide(): ProductInvalide
|
||||
{
|
||||
return ProductInvalide::new(
|
||||
product: $this,
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## Enrichissement avec exceptions métier
|
||||
|
||||
Ajouter des méthodes factory pour les cas d'erreur spécifiques :
|
||||
|
||||
```php
|
||||
final class ProductInvalide
|
||||
{
|
||||
private function __construct(
|
||||
private Product $product,
|
||||
) {}
|
||||
|
||||
public static function new(Product $product): self
|
||||
{
|
||||
return new self(product: $product);
|
||||
}
|
||||
|
||||
public static function carPrixNegatif(): \InvalidArgumentException
|
||||
{
|
||||
return new \InvalidArgumentException(
|
||||
'Le prix du produit ne peut pas être négatif'
|
||||
);
|
||||
}
|
||||
|
||||
public static function carStockInsuffisant(int $demande, int $disponible): \DomainException
|
||||
{
|
||||
return new \DomainException(
|
||||
sprintf(
|
||||
'Stock insuffisant: %d demandé, %d disponible',
|
||||
$demande,
|
||||
$disponible
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public static function carNomVide(): \InvalidArgumentException
|
||||
{
|
||||
return new \InvalidArgumentException(
|
||||
'Le nom du produit ne peut pas être vide'
|
||||
);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Usage des exceptions
|
||||
|
||||
```php
|
||||
final class Product
|
||||
{
|
||||
public static function create(Uuid $id, string $name, float $price): self
|
||||
{
|
||||
if ('' === $name) {
|
||||
throw ProductInvalide::carNomVide();
|
||||
}
|
||||
if ($price < 0) {
|
||||
throw ProductInvalide::carPrixNegatif();
|
||||
}
|
||||
return new self(id: $id, name: $name, price: $price);
|
||||
}
|
||||
|
||||
public function decreaseStock(int $quantity): void
|
||||
{
|
||||
if ($this->stock < $quantity) {
|
||||
throw ProductInvalide::carStockInsuffisant(
|
||||
demande: $quantity,
|
||||
disponible: $this->stock
|
||||
);
|
||||
}
|
||||
// ...
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Notes
|
||||
- Les méthodes factory d'exceptions doivent commencer par `car` (convention)
|
||||
- Les messages d'exception ne doivent pas finir par un point
|
||||
- Les messages doivent inclure le maximum de contexte
|
||||
- Privilégier les exceptions standard PHP (\InvalidArgumentException, \DomainException)
|
||||
- Respecte le principe "fail fast"
|
||||
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Invalide;
|
||||
|
||||
use App\Entity\Utilisateur;
|
||||
|
||||
final class UtilisateurInvalide
|
||||
{
|
||||
private function __construct(
|
||||
private Utilisateur $utilisateur,
|
||||
) {
|
||||
}
|
||||
|
||||
public static function new(
|
||||
Utilisateur $utilisateur,
|
||||
): self {
|
||||
return new self(
|
||||
utilisateur: $utilisateur,
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user