Modelagem de domínio — agregados, invariantes e serviços
Modele agregados como Cart com IDs marcados e imponha invariantes por meio de fábricas e serviços.
Modelagem de domínio — agregados, invariantes e serviços é uma aula grátis de TypeScript Academy no CoddyKit. Esta é a aula 3 de 3. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de TypeScript Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de TypeScript Academy inclui 3 aulas no total.
Introdução
Objetivo: modelar um agregado Cart usando IDs marcados e garantir que regras como quantidade > 0 sejam impostas nas fábricas e nos serviços.
- IDs marcados distinguem os limites das entidades
- As fábricas retornam uniões de resultado
- As funções de serviço evitam transições inválidas
Entidades e marcas
IDs marcados tornam CartId e ProductId incompatíveis, embora ambos sejam cadeias de caracteres. Isso evita confusões.
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 ProductIdAgregado e invariante
As fábricas validam as regras: a quantidade deve ser > 0. Somente objetos Line válidos podem ser criados.
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) } }Serviço: adicionar item
As funções de serviço realizam transições seguras e recalculam os totais. Se os totais forem inválidos, a função retorna um erro em vez de corromper o estado.
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" }Mapeamento nas fronteiras
Nas fronteiras (por exemplo, em APIs), converta os dados em objetos de transferência e valide-os ao analisá-los novamente. As fábricas garantem que os dados estejam corretos.
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) } }
}Dicas
Boas práticas:
- Centralize a validação nas fábricas.
- Mantenha as funções de serviço puras e determinísticas.
- Faça conversões de marca somente nas fronteiras do sistema.
Verificação do invariante
Verificação rápida: como impor um invariante como quantidade > 0?
Recapitulação
Recapitulação: IDs marcados combinados com fábricas e serviços impõem invariantes. Estados inválidos não podem ser criados porque todos os pontos de entrada validam os dados.
Aprenda TypeScript com um tutor de IA — grátis
Escreva e execute código real no seu navegador, obtenha ajuda instantânea de um tutor de IA 24/7 e continue de onde parou na web ou no app.
- Cursos
- 101
- Aulas
- 352
Perguntas Frequentes
A aula “Modelagem de domínio — agregados, invariantes e serviços” é grátis?
Sim — o texto completo de “Modelagem de domínio — agregados, invariantes e serviços” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de TypeScript Academy, atualize para CoddyKit PRO. O curso de TypeScript Academy inclui 3 aulas no total.
O que vou aprender em “Modelagem de domínio — agregados, invariantes e serviços”?
Modele agregados como Cart com IDs marcados e imponha invariantes por meio de fábricas e serviços. Você pratica TypeScript Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.
Preciso ter experiência prévia para começar TypeScript Academy?
Nenhuma experiência prévia é necessária. TypeScript Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 3 de 3.
Quanto tempo leva a aula “Modelagem de domínio — agregados, invariantes e serviços”?
A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.
Posso escrever e executar código nesta aula de TypeScript Academy?
Sim. Cada aula de TypeScript Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.
Todas as aulas deste curso
- Tipos de marca/opacos para evitar confusões entre unidades
- IDs marcados e padrões de modelagem de domínio
- Modelagem de domínio — agregados, invariantes e serviços