@vibby0
Fabrique
d’Allumettes
Industrielle
Ligériennes
Représenter le réel :
User Story
En tant que receptionnaire,
Je receptionne un tronc
Afin d’en préparer le débitagenamespace spec;
use PhpSpec\ObjectBehavior;
class ReceptionisteSpec extends ObjectBehavior
{
function it_receptionne_tronc()
{
$tronc = new Tronc('542kg');
$this->receptionnerTronc($tronc)->shouldReturn($etiquette);
}
}Encore trop old-school
namespace App\Scierie\Application\UseCase\ReceptionerUnTronc;
use App\Scierie\Domain\Depository\TroncDepository;
class ReceptionerUnTroncHandler
{
function __construct(
private readonly TroncDepository $troncDepository;
) {}
function __invoke(ReceptionerUnTroncInput $input)
{
$tronc = new Tronc(
masse: $input->masse,
essence: $input->essence
);
$this->troncDepository->store($tronc);
return new Etiquette($tronc);
}
}Qu’est ce qu’on fait ?
Qu’est ce qu’on donne ?
namespace App\Scierie\Application\
UseCase\ReceptionerUnTronc;
use Symfony\Component\Validator\Constraints;
use App\Scierie\Application\Asserts;
class ReceptionerUnTroncInput
{
function __construct(
#[Constraints\NotBlank]
#[Asserts\IsMasse]
public string $masse,
#[Constraints\NotBlank]
#[Asserts\IsEssence]
public string $essence,
) {}
}C’est quoi ce truc ?
namespace App\Scierie\Domain\Entity;
use App\Scierie\Application\Asserts;
use Ramsey\Uuid\Uuid;
#[Asserts\MasseMinimumParEssence]
class Tronc
{
public readonly Uuid $id;
function __construct(
private Masse $masse,
private Essence $essence,
) {
$this->id = Uuid::uuid4();
}
function refendre(
EpaisseurDeCoupe $epaisseur
): Planche {
[…]
}
}Une propriété à forte valeur
namespace App\Scierie\Domain\ValueObject;
use Symfony\Component\Validator\Constraints;
class Masse
{
function __construct(
#[Constraints\Positive]
public readonly int $value,
public readonly UniteMasse $unite,
) {
}
}
Enum UniteMasse
{
case Kilogramme;
case Tonne;
case Livre;
}Se connecter au monde
namespace App\Scierie\Domain\Depository;
interface TroncDepository
{
function store(Tronc $tronc): void;
function update(Tronc $tronc): void;
function marquerCommeSecs(\DateTime $date);
}
interface TroncRepository
{
function findById(Uuid $id): Tronc;
function findByMasseMinimum(
Tronc $tronc,
Masse $masse,
): \ArrayObject;
}
- src
- Scierie
- Application
- UseCase
- ReceptionnerTronc
- RefendreTronc
- Asserts
- Domain
- Entity
- ValueObject
- Depository
- Repository
- Franglais d’ubiquitous langage
- La doc ? Quelle doc ?
- Je fais pas du MVC ! (ou si ?)
- Tests fonctionnels
- Holistique et Étendue
- Sous-domaines
- Objectiver le métier
- Site web backend
- API pour frontend
- Appli mobile
- Ligne de commande
- Objet connecté
Côté gauche
namespace App\Scierie\Infrastructure\Controller;
class NewTroncController extends AbstractController
{
public function __invoke(
Request $request,
ReceptionerUnTroncHandler $handler,
) {
$input = new ReceptionerUnTroncInput(
masse: $request->get('masse'),
essence: $request->get('essence'),
);
$etiquette = $handler($input);
return $this->render(
'view.html.twig',
['etiquette' => $etiquette]
);
}
}
Côté droit
namespace App\Scierie\Domain\Depository;
interface TroncDepo implements TroncDepository
{
function __construct(
private EntityManager $em,
private ElasticSearchIndexer $es,
){}
function store(Tronc $tronc)
{
$this->em->persist($tronc);
$this->em->flush();
$this->es->index($tronc);
}
}
namespace App\Scierie\Infrastructure\Doctrine\Type;
use Doctrine\DBAL\Types\ArrayType;
use App\Scierie\Domain\ValueObject\Masse;
class voMasseType extends ArrayType
{
function convertToPHPValue($value): mixed
{
return new Masse($value['value'], $value['unite']);
}
function convertToDatabaseValue($value): array
{
return [
'value' => $value->value,
'unite' => $value->unite,
];
}
}
<?xml version="1.0" encoding="utf-8"?>
<doctrine-mapping xmlns="…">
<entity name="App\Scierie\Domain\Entity\Tronc">
<field name="id" type="string" length="32" />
<field name="masse" type="vo_masse" length="16" />
<field name="essence" type="enum_essence" length="16" />
</entity>
</doctrine-mapping>
Api-Platform
App\Scierie\Domain\Entity\Tronc:
attributes:
order:
dateArrivee: ASC
collectionOperations:
get:
method: GET
security: is_granted('ROLE_USER')
output: App\Forfait\Application\Output\Etiquette
post:
method: POST
path: /reception-tronc
security: is_granted('ROLE_RECEPTIONISTE')
input: App\Scierie\Application\UseCase\ReceptionerUnTroncInput
output: App\Forfait\Application\Output\Etiquette
messenger: input
itemOperations:
get:
method: GET
security: is_granted('ROLE_USER')
output: App\Forfait\Application\Output\Etiquette
@vibby0