Pular para o conteúdo

Linguagem Ubíqua

Cunhada por Eric Evans, a Linguagem Ubíqua (Ubiquitous Language) é a espinha dorsal do Design Estratégico. A ideia é eliminar a “tradução” entre a linguagem do negócio e a linguagem técnica — tradução que sempre perde informação e introduz bugs conceituais.

Não existe uma linguagem ubíqua global do sistema. Ela é contextual: cada Bounded Context tem a sua. O termo “Cliente” no contexto de Vendas pode significar algo diferente de “Cliente” no contexto de Faturamento. Forçar um único significado gera um modelo confuso e ambíguo.

  • Ambiguidade de termos: sem acordo, “pedido”, “ordem” e “solicitação” viram sinônimos flutuantes.
  • Perda na tradução: o analista descreve uma regra, o dev a implementa com outro nome, e o código deixa de “falar” o negócio.
  • Documentação que mente: modelos que não usam a linguagem do especialista envelhecem mal.
  1. O código é a documentação viva. Se o especialista fala “aprovar apólice”, deve existir apolice.aprovar(), não apolice.setStatus(2).
  2. Refine a linguagem continuamente. Descobriu um termo melhor com o especialista? Refatore o modelo — inclusive nomes de classes.
  3. Um termo, um significado — por contexto. Homônimos entre contextos são normais; homônimos dentro do mesmo contexto são bug.
  4. Testes falam a linguagem. Cenários BDD/Gherkin são um ótimo espelho da linguagem ubíqua.

Em subdomínios genéricos (envio de e-mail, autenticação) ou CRUDs triviais, investir pesado na linguagem ubíqua tem baixo retorno. O esforço se justifica no Core Domain, onde está a vantagem competitiva.

Modelo que fala a linguagem do negócio de seguros. Note os nomes derivados diretamente do vocabulário do especialista.

package com.seguradora.apolice.domain;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.UUID;
public class Apolice {
private final ApoliceId id;
private final Segurado segurado;
private final BigDecimal premio;
private LocalDate vigenciaInicio;
private LocalDate vigenciaFim;
private StatusApolice status;
public Apolice(Segurado segurado, BigDecimal premio, LocalDate vigenciaInicio, LocalDate vigenciaFim) {
if (premio == null || premio.signum() <= 0) {
throw new IllegalArgumentException("Premio deve ser positivo");
}
if (vigenciaFim.isBefore(vigenciaInicio)) {
throw new IllegalArgumentException("Vigencia final anterior ao inicio");
}
this.id = new ApoliceId(UUID.randomUUID());
this.segurado = segurado;
this.premio = premio;
this.vigenciaInicio = vigenciaInicio;
this.vigenciaFim = vigenciaFim;
this.status = StatusApolice.PROPOSTA;
}
public void aprovar() {
if (status != StatusApolice.PROPOSTA) {
throw new IllegalStateException("Apenas propostas podem ser aprovadas");
}
this.status = StatusApolice.VIGENTE;
}
public void cancelar() {
if (status != StatusApolice.VIGENTE) {
throw new IllegalStateException("Apenas apolices vigentes podem ser canceladas");
}
this.status = StatusApolice.CANCELADA;
}
public boolean estaVigenteEm(LocalDate data) {
return status == StatusApolice.VIGENTE
&& !data.isBefore(vigenciaInicio)
&& !data.isAfter(vigenciaFim);
}
public ApoliceId id() {
return id;
}
public StatusApolice status() {
return status;
}
}
package com.seguradora.apolice.domain;
public enum StatusApolice {
PROPOSTA,
VIGENTE,
CANCELADA
}
  • Traduzir na fronteira: manter um glossário paralelo em vez de nomear o código com os termos reais.
  • Linguagem global forçada: um único “Cliente” para todo o sistema, gerando um modelo genérico e anêmico.
  • Termos técnicos vazando: dto, manager, helper como se fossem conceitos de negócio.
  • Congelar a linguagem: não refatorar nomes quando o entendimento do domínio evolui.

1. A Linguagem Ubíqua é global ou contextual?

Resposta

Contextual. Cada Bounded Context tem a sua. O mesmo termo pode significar coisas diferentes em contextos distintos, e isso é esperado — não um defeito.

2. Onde a Linguagem Ubíqua deve aparecer?

Resposta

Literalmente no código: nomes de classes, métodos, Domain Events e testes. O código é documentação viva do vocabulário do negócio.

3. Por que apolice.setStatus(2) viola a Linguagem Ubíqua?

Resposta

Porque não expressa a intenção do negócio. O especialista fala “aprovar”, “cancelar” — logo devem existir métodos aprovar()/cancelar() que carregam a regra, e não um setter genérico com códigos mágicos.

4. Quando NÃO vale a pena investir pesado na Linguagem Ubíqua?

Resposta

Em subdomínios genéricos (e-mail, auth) e CRUDs triviais. O retorno é maior no Core Domain, onde reside a complexidade e a vantagem competitiva.