Modélisation du domaine
Au cœur de toute application orientée domaine se trouve le modèle qui représente la connaissance centrale et les règles métier du système. Bien modéliser le domaine signifie traduire les concepts du monde réel en structures logicielles expressives, cohérentes et consistantes.
Entités
Une entité est un objet défini principalement par son identité et non uniquement par ses attributs. Même si les attributs changent au fil du temps, l'identité d'une entité reste la même.
Caractéristiques principales :
- Possède une identité unique (généralement un
Id
). - Ce qui importe, c'est qui est l'entité, pas seulement ce qu'elle contient.
- Ses attributs peuvent changer au fil du temps.
Créer une entité avec Lino
Pour créer une nouvelle entité en utilisant Lino, exécutez :
lino entity new
L'assistant CLI vous demandera :
- Service – Le service dans lequel l'entité sera créée.
- Module – Le module dans lequel l'entité sera créée (uniquement dans les services modulaires).
- Nom de l'entité – Le nom utilisé dans le domaine et dans la table de la base de données.
Ensuite, vous définirez les champs qui composent l'entité en configurant chacun d'eux.
Types de champs disponibles
Type | Description | Plage / Observations |
---|---|---|
short | Entier 16 bits | -32 768 → 32 767 |
int | Entier 32 bits | -2 147 483 648 → 2 147 483 647 |
long | Entier 64 bits | -9 223 372 036 854 775 808 → 9 223 372 036 854 775 807 |
string | Texte | Jusqu'à environ 2 milliards de caractères |
bool | Valeur booléenne | true ou false |
Guid | Identifiant global unique | Unicité distribuée |
decimal | Nombre décimal haute précision | Idéal pour valeurs monétaires |
float | Nombre flottant (32 bits) | ≈ 6–9 chiffres de précision |
double | Nombre flottant (64 bits) | ≈ 15–17 chiffres de précision |
DateTime | Date et heure | Inclut le fuseau horaire |
DateOnly | Seulement la date (C# 10+) | – |
TimeOnly | Seulement l'heure (C# 10+) | – |
Entity | Référence à une autre entité | 1:1 ou 1:N |
Value Object | Objet valeur immuable | Ex.: Adresse, CPF |
Enum | Énumération | Ensemble fixe de valeurs |
List<Entity> | Liste d'entités | 1:N |
ManyToMany | Plusieurs-à-plusieurs | Nécessite une table de jointure |
Exemple
Création de l'entité Person
:
┌────┬────┬───────────────┬────────┬────────┬───────────┬────────────────┐ │ PK │ FK │ Property name │ Type │ Length │ Required │ Auto-increment │ ├────┼────┼───────────────┼────────┼────────┼───────────┼────────────────┤ │ x │ │ Id │ int │ │ x │ x │ ├────┼────┼───────────────┼────────┼────────┼───────────┼────────────────┤ │ │ │ Name │ string │ 100 │ x │ │ └────┴────┴───────────────┴────────┴────────┴───────────┴────────────────┘
Structure générée par Lino :
MyApp/ └── src/ └── Services/ └── MyService/ └── Domain/ ├── MyApp.MyService.Domain.csproj └── Aggregates/ └── People/ ├── Person.cs ├── Errors/ │ └── PersonErrors.cs ├── Repositories/ │ └── IPersonRepository.cs └── Resources/ └── Person/ ├── PersonResources.resx ├── PersonResources.en.resx └── PersonResources.pt-BR.resx
Après avoir défini vos entités, utilisez Lino lui-même pour gérer les Migrations et garder la base de données synchronisée. Ce processus sera détaillé dans la section Couche de Persistance.
Objets de Valeur
Un objet de valeur représente un concept du domaine défini uniquement par ses attributs – il ne possède pas d’identité propre. Deux objets de valeur sont considérés comme égaux si toutes leurs valeurs sont identiques.
Principales caractéristiques :
- Immuables après création.
- Ne possèdent pas de
Id
.
Créer un objet de valeur avec Lino
Exécutez :
lino value-object new
Le CLI demandera :
- Service – Service dans lequel l’objet sera créé.
- Module – Module dans lequel l’objet sera créé (uniquement dans les services modulaires).
- Emplacement – Racine du domaine ou agrégat spécifique.
- Nom de l’objet de valeur.
Puis définissez les champs qui composent l’objet.
Types de champs disponibles
Type | Description | Remarques |
---|---|---|
short | Entier 16 bits | -32 768 → 32 767 |
int | Entier 32 bits | -2 147 483 648 → 2 147 483 647 |
long | Entier 64 bits | -9 223 372 036 854 775 808 → 9 223 372 036 854 775 807 |
string | Texte | Jusqu’à ~2 milliards de caractères |
bool | Booléen | true /false |
decimal | Décimal précis | Valeurs monétaires |
float | Nombre à virgule flottante (32 bits) | ≈ 6–9 chiffres |
double | Nombre à virgule flottante (64 bits) | ≈ 15–17 chiffres |
DateTime | Date/heure | Inclut le fuseau horaire |
DateOnly | Seulement la date | C# 10+ |
TimeOnly | Seulement l’heure | C# 10+ |
Exemple
Objet de valeur Address
:
┌───────────────┬────────┬────────┬───────────┐ │ Property name │ Type │ Length │ Required │ ├───────────────┼────────┼────────┼───────────┤ │ Street │ string │ 100 │ x │ ├───────────────┼────────┼────────┼───────────┤ │ Number │ string │ 10 │ x │ ├───────────────┼────────┼────────┼───────────┤ │ Neighborhood │ string │ 50 │ │ ├───────────────┼────────┼────────┼───────────┤ │ City │ string │ 100 │ x │ ├───────────────┼────────┼────────┼───────────┤ │ State │ string │ 2 │ x │ ├───────────────┼────────┼────────┼───────────┤ │ PostalCode │ string │ 20 │ x │ ├───────────────┼────────┼────────┼───────────┤ │ Country │ string │ 100 │ x │ └───────────────┴────────┴────────┴───────────┘
Structure des fichiers générée (agrégat Person
) :
MyApp/ └── src/ └── Services/ └── MyService/ └── Domain/ ├── MyApp.MyService.Domain.csproj └── Aggregates/ └── People/ ├── Person.cs ├── ValueObjects/ │ └── Address.cs ├── Errors/ │ ├── AddressErrors.cs │ └── PersonErrors.cs ├── Repositories/ │ └── IPersonRepository.cs └── Resources/ ├── Address/ │ ├── AddressResources.resx │ ├── AddressResources.en.resx │ └── AddressResources.pt-BR.resx └── Person/ ├── PersonResources.resx ├── PersonResources.en.resx └── PersonResources.pt-BR.resx
Comme pour les entités, les Migrations peuvent être gérées par Lino pour maintenir la synchronisation du modèle de données.
Énumérations
Les énumérations en DDD peuvent aller au-delà des enum
traditionnels de C#. Elles peuvent être des objets riches
représentant des états fixes, contenant des validations, des méthodes auxiliaires et même des comportements.
Motivation :
- Les
enum
de C# sont limités à une valeur entière ou chaîne. - Modéliser une Enumeration comme une classe offre plus de flexibilité et d’expressivité.
Caractéristiques principales :
- Ce sont des classes héritant d’une base commune et encapsulant
Id
etNom
. - Elles permettent d’ajouter des validations, des méthodes auxiliaires et des comportements.
Créer une énumération avec Lino
Exécutez :
lino enum new
L’assistant vous demandera :
- Service.
- Module (si applicable).
- Emplacement – racine du domaine ou agrégat.
- Nom de l’énumération.
- Type –
enum
traditionnel ou Smart Enum (class
). - Stockage –
int
oustring
en base de données.
Exemple
Énumération PersonStatus
:
┌───────┬───────────┬──────────────┐ │ Value │ Name │ Display Name │ ├───────┼───────────┼──────────────┤ │ 1 │ Active │ Active │ ├───────┼───────────┼──────────────┤ │ 2 │ Inactive │ Inactive │ ├───────┼───────────┼──────────────┤ │ 3 │ Suspended │ Suspended │ ├───────┼───────────┼──────────────┤ │ 4 │ Deleted │ Deleted │ └───────┴───────────┴──────────────┘
Structure générée :
MyApp/ └── src/ └── Services/ └── MyService/ └── Domain/ ├── MyApp.MyService.Domain.csproj └── Aggregates/ └── People/ ├── Person.cs ├── Enums/ │ └── PersonStatus.cs ├── ValueObjects/ │ └── Address.cs ├── Errors/ │ ├── AddressErrors.cs │ └── PersonErrors.cs ├── Repositories/ │ └── IPersonRepository.cs └── Resources/ ├── Address/ │ ├── AddressResources.resx │ ├── AddressResources.en.resx │ └── AddressResources.pt-BR.resx ├── Person/ │ ├── PersonResources.resx │ ├── PersonResources.en.resx │ └── PersonResources.pt-BR.resx └── PersonStatus/ ├── PersonStatusResources.resx ├── PersonStatusResources.en.resx └── PersonStatusResources.pt-BR.resx
Stocker la valeur d’une énumération comme string
est valide et peut améliorer la lisibilité, mais tend à être moins efficace en termes de performances et de stockage.
C’est pourquoi nous recommandons de stocker la valeur comme int
, et pour maintenir l’intégrité référentielle et faciliter la maintenance, de créer une entité (table) auxiliaire dont la clé primaire correspond à la valeur de l’énumération.
Après avoir défini les énumérations, utilisez Lino pour générer et appliquer les Migrations, garantissant que la base de données reflète le modèle de domaine. Voir les détails dans la section Couche de Persistance.