Modélisation métier — agrégats, invariants et services
Modélisez des agrégats comme Cart avec des identifiants brandés et imposez les invariants grâce aux fabriques et aux services.
Modélisation métier — agrégats, invariants et services est une leçon TypeScript Academy gratuite sur CoddyKit. Ceci est la leçon 3 sur 3. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage TypeScript Academy, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours TypeScript Academy comprend 3 leçons au total.
Introduction
Objectif : modéliser un agrégat Cart à l’aide d’identifiants marqués et garantir que des règles comme quantité > 0 sont respectées dans les fabriques et les services.
- Les identifiants marqués distinguent les frontières entre entités
- Les fabriques renvoient des unions de résultats
- Les fonctions de service évitent les transitions invalides
Entités et marques
Les identifiants marqués rendent CartId et ProductId incompatibles, même s’ils sont tous deux des chaînes. Cela évite les confusions.
type Brand<Tag extends string, T> = T & { readonly __brand: Tag }
type CartId = Brand<"CartId", string>
type ProductId = Brand<"ProductId", string>
type Result<T> = { ok: true; value: T } | { ok: false; error: string }
const cartId = (s: string): CartId => s as CartId
const productId = (s: string): ProductId => s as ProductIdAgrégat et invariant
Les fabriques valident les règles : la quantité doit être > 0. Seuls des objets Line valides peuvent être créés.
type Money = number & { readonly __brand: "Money" }
const money = (n: number): Money => n as Money
interface Line { productId: ProductId; qty: number; price: Money }
interface Cart { id: CartId; lines: Line[]; total: Money }
function makeLine(productId: ProductId, qty: number, price: Money): Result<Line> {
if (!Number.isInteger(qty) || qty <= 0) return { ok: false, error: "qty must be > 0" }
return { ok: true, value: { productId, qty, price } }
}
function makeCart(id: CartId): Cart { return { id, lines: [], total: money(0) } }Service : ajouter un élément
Les fonctions de service effectuent des transitions sûres et recalculent les totaux. Si les totaux sont invalides, la fonction renvoie une erreur au lieu de corrompre l’état.
function addItem(cart: Cart, line: Line): Result<Cart> {
const lines = [...cart.lines, line]
const totalNum = lines.reduce((s, x) => s + (x.qty * (x.price as number)), 0)
if (!Number.isFinite(totalNum) || totalNum < 0) return { ok: false, error: "invalid total" }
return { ok: true, value: { ...cart, lines, total: (totalNum as unknown) as Money } }
}
// Usage
const c0 = makeCart(cartId("c1"))
const l = makeLine(productId("p1"), 2, money(10))
const c1 = l.ok ? addItem(c0, l.value) : { ok: false, error: "bad line" }Conversion aux frontières
Aux frontières du système (par ex. les APIs), convertissez les données en objets de transfert et validez-les lors de leur analyse inverse. Les fabriques garantissent l’exactitude des données.
type CartDTO = { id: string; lines: { productId: string; qty: number; price: number }[]; total: number }
function serialize(c: Cart): CartDTO {
return {
id: c.id as unknown as string,
lines: c.lines.map(x => ({ productId: x.productId as unknown as string, qty: x.qty, price: x.price as unknown as number })),
total: c.total as unknown as number
}
}
function parse(dto: CartDTO): Result<Cart> {
const id = cartId(dto.id)
const lines: Line[] = []
for (const raw of dto.lines) {
const l = makeLine(productId(raw.productId), raw.qty, money(raw.price))
if (!l.ok) return { ok: false, error: l.error }
lines.push(l.value)
}
const totalNum = lines.reduce((s, x) => s + (x.qty * (x.price as number)), 0)
return { ok: true, value: { id, lines, total: money(totalNum) } }
}Conseils
Bonnes pratiques :
- Centralisez la validation dans les fabriques.
- Gardez les fonctions de service pures et déterministes.
- Effectuez les conversions de marques uniquement aux frontières du système.
Vérification de l’invariant
Vérification rapide : comment imposer une règle invariante telle que quantité > 0 ?
Récapitulatif
Récapitulatif : les identifiants marqués, associés aux fabriques et aux services, imposent les invariants. Les états invalides ne peuvent pas être créés, car tous les points d’entrée valident les données.
Questions Fréquemment Posées
La leçon « Modélisation métier — agrégats, invariants et services » est-elle gratuite ?
Oui — le texte complet de « Modélisation métier — agrégats, invariants et services » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours TypeScript Academy, passe à CoddyKit PRO. Le cours TypeScript Academy comprend 3 leçons au total.
Qu'est-ce que j'apprendrai dans « Modélisation métier — agrégats, invariants et services » ?
Modélisez des agrégats comme Cart avec des identifiants brandés et imposez les invariants grâce aux fabriques et aux services. Tu pratiques TypeScript Academy avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.
Dois-je avoir de l'expérience pour commencer TypeScript Academy ?
Aucune expérience préalable n'est requise. TypeScript Academy sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 3 sur 3.
Combien de temps prend la leçon « Modélisation métier — agrégats, invariants et services » ?
La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.
Peux-tu écrire et exécuter du code dans cette leçon TypeScript Academy ?
Oui. Chaque leçon TypeScript Academy inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.
Toutes les leçons de ce cours
- Types opaques et brands pour éviter les confusions d’unités
- Identifiants marqués et motifs de modélisation métier
- Modélisation métier — agrégats, invariants et services