TypeScript Academy · Aula

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.

Aula 3 de 38 etapas

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 ProductId

Agregado 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.

Grátis para começar

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

  1. Tipos de marca/opacos para evitar confusões entre unidades
  2. IDs marcados e padrões de modelagem de domínio
  3. Modelagem de domínio — agregados, invariantes e serviços
← Voltar para TypeScript Academy