Home > Blog > Desenvolvimento Web
Desenvolvimento Web
JavaScript
Programação

Domain Services no Node.js: regras de domínio

Atualizado em: 14 de outubro de 2026

Estação de trabalho usada no desenvolvimento de aplicações Node.js

Domain Services no Node.js representam regras de negócio que não pertencem naturalmente a uma única entidade ou Value Object. Eles trabalham com conceitos do domínio sem coordenar detalhes técnicos como HTTP, filas ou conexão com banco.

O padrão é útil quando uma decisão envolve vários objetos, políticas ou cálculos. Porém, usar um serviço para toda regra cria um modelo anêmico. Primeiro tente colocar o comportamento na entidade; extraia um Domain Service apenas quando a responsabilidade realmente atravessar objetos.

Domain Service ou Application Service?

Um Domain Service executa regra do negócio. Um Application Service coordena o caso de uso, carrega dados, abre transação, chama o domínio e persiste resultados.

export function calcularLimiteDeCompra({ cliente, carrinho, politica }) {
  const risco = politica.classificar(cliente);
  return risco === 'alto'
    ? Math.min(carrinho.total(), cliente.limiteDisponivel)
    : carrinho.total();
}

A função não conhece repository, Express ou PostgreSQL.

Exemplo de Application Service

export function criarFinalizarCompra({ clientes, pedidos, politica, unitOfWork }) {
  return async function finalizar({ clienteId, pedidoId }) {
    return unitOfWork.run(async trx => {
      const cliente = await clientes.obter(clienteId, trx);
      const pedido = await pedidos.obter(pedidoId, trx);
      const limite = calcularLimiteDeCompra({ cliente, carrinho: pedido, politica });
      pedido.finalizarComLimite(limite);
      await pedidos.salvar(pedido, trx);
      return pedido;
    });
  };
}

A aplicação coordena; o domínio decide.

Quando criar um Domain Service?

  • a regra envolve duas ou mais entidades independentes;
  • o conceito possui nome reconhecido pelo negócio;
  • colocar a regra em uma entidade causaria dependência artificial;
  • a operação é sem estado ou recebe dependências de domínio explícitas;
  • o resultado representa uma decisão ou cálculo do negócio.

Políticas

Políticas são serviços de domínio que encapsulam uma decisão variável.

export class PoliticaDeDesconto {
  calcular({ cliente, pedido }) {
    if (cliente.vip && pedido.total.centavos >= 10000) {
      return 0.15;
    }
    if (pedido.itens.length >= 5) return 0.05;
    return 0;
  }
}

O pedido pode receber a porcentagem e aplicar a regra de arredondamento internamente.

Strategy

Diferentes políticas podem implementar o mesmo contrato.

export function selecionarFrete({ modalidade, normal, expresso }) {
  if (modalidade === 'expresso') return expresso;
  return normal;
}

A composição ocorre fora do domínio, normalmente no composition root.

Pureza

Serviços puros são fáceis de testar: recebem valores e retornam resultado sem I/O. Quando a regra depende de cotação externa, use uma porta.

export function criarConversorDeMoeda(cotacoes) {
  return {
    async converter(valor, destino) {
      const taxa = await cotacoes.obter(valor.moeda, destino);
      return valor.converter(taxa, destino);
    }
  };
}

cotacoes é uma abstração de domínio; o adapter HTTP fica na infraestrutura.

Nomes orientados ao negócio

Evite classes como UtilsService, CommonService e DataService. Prefira PoliticaDeCredito, CalculadoraDeFrete e AlocadorDeEstoque.

Estado

Domain Services normalmente não mantêm estado mutável entre requisições. Dados necessários devem ser argumentos ou dependências imutáveis. Isso reduz problemas de concorrência no Node.js.

Erros do domínio

export class CreditoInsuficienteError extends Error {
  constructor() {
    super('Crédito insuficiente para a operação');
    this.code = 'CREDITO_INSUFICIENTE';
  }
}

Adapters traduzem o erro para HTTP, mensagem de fila ou saída de CLI.

Eventos

Uma decisão de domínio pode resultar em eventos, mas prefira que o aggregate registre o fato após aplicar a alteração. O serviço pode retornar uma decisão estruturada.

const decisão = politica.analisar({ cliente, pedido });
pedido.aplicarDecisao(decisão);

Testes unitários

const politica = new PoliticaDeDesconto();
const desconto = politica.calcular({
  cliente: { vip: true },
  pedido: { total: { centavos: 15000 }, itens: [1] }
});
assert.equal(desconto, 0.15);

Teste limites, combinações, arredondamento e erros.

Injeção de dependência

Receba políticas e portas pelo construtor ou fábrica. Consulte Dependency Injection no Node.js.

Domain Service e aggregate

O serviço não deve contornar a raiz para alterar entidades internas. Ele calcula ou decide; a raiz mantém invariantes. Leia Aggregates no Node.js.

Domain Service e Value Object

Se a operação depende apenas dos valores de um conceito, talvez pertença ao próprio Value Object. Uma soma monetária, por exemplo, deve estar em Dinheiro, não em MoneyService.

Erros comuns

  • mover todo comportamento para services;
  • misturar SQL e regra de domínio;
  • usar nomes genéricos;
  • manter estado global;
  • retornar DTO de HTTP;
  • depender diretamente de SDK externo;
  • duplicar regra já protegida pela entidade;
  • criar uma interface sem variação real.

Checklist

  • a operação tem nome no negócio;
  • não pertence claramente a uma entidade;
  • não conhece transporte ou persistência;
  • recebe dependências por portas;
  • preserva aggregates;
  • é testável isoladamente;
  • não vira depósito de funções.

Conclusão

Domain Services no Node.js são úteis para regras que atravessam objetos do domínio sem pertencer a uma entidade específica. Eles devem permanecer pequenos, expressivos e independentes da infraestrutura.

Use entidades e Value Objects como primeira opção. Quando a regra realmente representar uma política ou cálculo externo ao objeto, modele um serviço com nome do negócio e dependências explícitas.

Leia também Domain-Driven Design no Node.js, Entidades e Value Objects no Node.js e a referência de DDD.

10 melhores cursos de programação em 2026

Descubra os melhores cursos de programação. Aprenda a escolher o curso ideal para iniciar ou avançar na carreira de desenvolvedor

POSTS RELACIONADOS

Ver todos

Seta para a direita