02 - Linguagem Ubíqua (Ubiquitous Language)
video: https://youtu.be/... no frontmatter da nota.Linguagem Ubíqua (Ubiquitous Language)
A linguagem ubíqua é o vocabulário compartilhado, preciso e obrigatório entre especialistas do
negócio, desenvolvedores, testadores e todos os envolvidos no produto. Ela define que um termo como
"reserva", "liquidação" ou "inadimplência" tem um significado único e acordado dentro de um
contexto, e que esse mesmo vocabulário aparece nas conversas, nos requisitos, no código, nos testes
e nos logs. O objetivo é eliminar a tradução permanente entre o jeito de falar do negócio e o jeito
de falar da tecnologia, porque cada tradução perde significado e abre espaço para defeitos. Em
produção, boa parte dos bugs sérios nasce de ambiguidade de termos e não de lógica mal escrita. Um
sistema onde o código fala a língua do negócio é auditável pelo próprio especialista, acelera o
onboarding e reduz o custo de cada mudança.
O problema que resolve
Em projetos sem vocabulário comum, cada camada fala um dialeto diferente. O analista escreve
"lançamento", o desenvolvedor cria uma classe chamada TransactionRecord, o QA chama de "movimento"
e o suporte abre ticket com o termo que o cliente usou. Quando um incidente acontece, o time gasta
horas apenas descobrindo se todos estão falando da mesma coisa. Esse custo de tradução aparece em
outros três pontos: na escrita de requisitos, que descrevem o comportamento com palavras que o
código não reconhece; na revisão de código, onde um nome ruim exige reunião para confirmar o
significado; e na manutenção por novos integrantes, que precisam construir mentalmente um dicionário
que ninguém documentou. A linguagem ubíqua ataca a raiz: um único dicionário, usado por todos e
refletido no próprio software.
Onde a linguagem vale e como ela se forma
A linguagem ubíqua só é consistente dentro de um bounded context, e tentar um dicionário único para
a empresa inteira costuma fracassar. "Apólice" significa algo diferente no seguro de vida e no
seguro de automóvel, e forçar um único significado produz um modelo vago. A formação do vocabulário
acontece nas conversas de levantamento e nas sessões de modelagem com especialistas, e deve ser
registrada em um glossário vivo no repositório do projeto. O critério de admissão de um termo é
objetivo: ele precisa ser usado naturalmente pelos especialistas, sem exigir tradução, e precisa ser
preciso o bastante para não gerar duas interpretações. Termos que não passam nesse critério ficam de
fora ou são refinados até passarem.
O código refletindo a linguagem
O teste prático da linguagem ubíqua é abrir o código e conseguir ler nomes de classes, métodos e
estados como frases do negócio. Se o especialista diz "reservar um assento" e o código tem
Assento.reservar(), a conversa e a implementação estão coladas. O exemplo a seguir compara dois
estilos para a mesma operação de pedido em TypeScript, um com vocabulário genérico de técnico e outro
com o vocabulário acordado do domínio.
// Estilo genérico: o leitor precisa traduzir o que "processar" significa
class PedidoProcessor {
exec(p: PedidoDTO, repo: Repo): Res {
if (p.itens.length === 0) throw new Error("inválido");
p.status = "PRC";
repo.save(p);
}
}
// Estilo ubíquo: nomes vêm do vocabulário acordado com o negócio
class Pedido {
// um pedido sem itens não é um pedido, é um carrinho abandonado
static novoPara(cliente: ClienteId, itens: ItemDePedido[]): Pedido {
if (itens.length === 0) throw new PedidoSemItens();
return new Pedido(PedidoId.novo(), cliente, itens, StatusDoPedido.AGUARDANDO_PAGAMENTO);
}
// o negócio diz "confirmar pedido", então o método se chama confirmar
confirmar(pagamento: PagamentoAprovado): void {
if (this.status !== StatusDoPedido.AGUARDANDO_PAGAMENTO) {
throw new PedidoNaoPodeSerConfirmado(this.id, this.status);
}
this.status = StatusDoPedido.CONFIRMADO;
this.registrarEvento(new PedidoConfirmado(this.id, pagamento.id));
}
}
A diferença não é estética. Na versão ubíqua, um incidente às 3 da manhã é diagnosticável lendo o
log, porque a mensagem PedidoNaoPodeSerConfirmado significa algo para o time de negócio também. Na
versão genérica, o erro "inválido" obriga a abrir código para descobrir qual regra falhou.
Renomeação como refatoração de verdade
Quando o negócio muda o nome de um conceito, o código deve mudar junto, e essa troca é refatoração
no mesmo sentido de extrair método ou remover duplicação. Manter o termo antigo "para não quebrar
nada" cria dois dicionários em paralelo, e em poucos meses ninguém sabe qual é o oficial. IDEs
modernas tornam a renomeação segura em linguagens estaticamente tipadas, então o custo da atualização
é baixo perto do custo do vocabulário dividido. Casos reais mostram o ganho: um time que trocou
"contrato" por "assinatura" após mudança regulatória atualizou classes, filas, tópicos e dashboards
em uma sprint, e a documentação parou de divergir do sistema. Nomes que atravessam fronteiras
externas, como campos de APIs públicas, exigem um plano de transição com deprecação, mas o modelo
interno deve seguir o negócio sem hesitar.
Glossário como documentação viva
O glossário é o artefato mínimo e mais barato para sustentar a linguagem: uma tabela de termo,
significado, exemplos e o que o termo não é. Ele vive junto do código, no repositório, e é atualizado
no mesmo pull request que introduz o conceito novo, exatamente como se atualiza um teste. Testes de
aceitação escritos em Gherkin reforçam o mesmo efeito, porque descrevem regras com o vocabulário
acordado e falham quando o código se descola da linguagem. A diferença para uma documentação comum é
a cobrança: glossário desatualizado é defeito, não detalhe. Times maduros revisam termos novos em
reunião curta, e a pergunta padrão é se o especialista do negócio reconheceria a frase escrita no
código.
Introduzindo a linguagem em um time que já existe
Em sistemas legados, o vocabulário do código raramente coincide com o vocabulário atual do negócio, e
forçar uma grande renomeação de uma vez é arriscado. O caminho incremental começa pelo glossário do
contexto mais ativo, seguido pela adoção dos termos em conversas, tickets e mensagens de commit.
Depois vêm os testes novos, que já nascem com a linguagem correta, e então os métodos tocados por
cada mudança de funcionalidade. Eventos publicados para outras equipes merecem cuidado redobrado,
porque renomear um payload quebra consumidores, então a troca segue com deprecação anunciada. Em
alguns meses o núcleo ativo do domínio fala a língua do negócio, e o vocabulário antigo sobrevive
apenas nas bordas congeladas.
Sinais de linguagem quebrada
| Sintoma observado | Causa provável | Mitigação |
|---|---|---|
| Reuniões em que negócio e time técnico repetem coisas diferentes do mesmo termo | Vocabulário sem significado único por contexto | Construir glossário por bounded context e validar com especialistas |
| Nomes como Gerenciador, Handler e Dados no núcleo do domínio | Código escrito só pelo vocabulário técnico | Renomear com base no que o negócio chama a operação |
| Especialista não consegue ler um teste de aceitação | Testes escritos no dialeto da tecnologia | Reescrever cenários em Gherkin com termos do negócio |
| Requisito novo muda o código, mas não a documentação, ou o inverso | Duas fontes de verdade sem sincronização | Glossário e testes no mesmo pull request da mudança |
| Novos integrantes demoram semanas para entender termos básicos | Conhecimento oral que nunca virou registro | Onboarding começando pelo glossário e pelos testes |
Erros comuns e boas práticas
- Escolher termos que soam técnicos em vez dos que o especialista usa. Se o mercado chama de
"sinistro", chamar de "evento de ocorrência" cria tradução desnecessária. - Manter termos ambíguos para agradar todos os interlocutores. Vagueza no vocabulário vira
vagueza no modelo e depois nos dados. - Ignorar que a linguagem vale por contexto e tentar dicionário corporativo único. Termos
compartilhados entre contextos precisam de mapeamento explícito, não de unificação. - Deixar o glossário em documento fora do repositório. Documentação longe do código envelhece
sem que ninguém perceba. - Tratar renomeação como custo puro. O termo desatualizado no código é dívida que cobra juros em
cada conversa, em cada incidente e em cada integração. - Registrar o termo sem exemplo de uso. Um termo sem exemplo admite duas leituras, e a ambiguidade
volta exatamente onde o glossário deveria eliminá-la.