“`html
Versões semânticas (SemVer) explicado
Semântica de versão não é “número bonito”: é um contrato. Neste post eu organizo o raciocínio do SemVer,
mostro como decidir entre major, minor e patch, e explico
como tratar pré-lançamentos e compatibilidade real.
1) O que é SemVer e por que ele existe
O SemVer (Semantic Versioning) define um formato padronizado para a versão do software,
normalmente usado por bibliotecas e APIs. A ideia central é que a mudança de versão comunique, com
previsibilidade, o impacto para quem usa.
major. Se você adiciona sem quebrar, você sobe minor. Se você corrige sem mudar comportamento,
sobe patch.
O SemVer reduz atrito entre equipes porque elimina adivinhação: o consumidor consegue entender a
compatibilidade potencial antes de atualizar.
2) Como interpretar “MAJOR.MINOR.PATCH” com critérios objetivos
A versão segue o padrão: MAJOR.MINOR.PATCH (com opcionais para pré-lançamento e build).
A parte mais importante é decidir quais tipos de mudanças justificam cada incremento.
-
PATCH (
z):
correções de bugs, ajustes internos e melhorias que não alteram a API/contrato
nem o comportamento observável de forma incompatível. -
MINOR (
y):
adição de funcionalidades compatíveis para consumidores existentes.
Tipicamente: novos recursos opcionais, novos endpoints com comportamento não-breaking, sobrecargas,
novos campos com semântica compatível (ex.: retornos adicionais). -
MAJOR (
x):
mudanças incompatíveis com versões anteriores. Se um consumidor precisa ajustar código
para voltar a funcionar, é MAJOR.
Um detalhe que eu sempre reforço: “compatível” significa compatível na prática.
Se o consumidor quebra por causa de uma mudança na forma esperada, a versão não pode ser minor ou
patch — é major.
3) Compatibilidade real: o que quebra alguém (mesmo sem mudar endpoints)
Em APIs e SDKs, “não quebrou” é relativo ao contrato que o consumidor usa. Às vezes você altera algo
que parece interno, mas muda comportamento observável.
Exemplos clássicos de mudanças incompatíveis (MAJOR):
- Remoção de endpoint, parâmetro obrigatório, campo ou evento usado por consumidores.
-
Mudança de semântica: antes “X”, agora “Y” com o mesmo formato.
Mesmo mantendo o tipo/shape, muda a interpretação. -
Alteração de tipos de retorno/contratos que invalida parsing do consumidor
(ex.: antes retornavastring, agora retornaobject). - Regras de validação que deixam entradas antes aceitas como inválidas.
- Mudança de ordenação, idempotência, timeouts e garantias que alteram o comportamento dependente.
existente em poucas frases, provavelmente é caso de MAJOR.
Para evitar surpresas, eu costumo validar mudanças com testes de contrato e cenários de consumidor:
simulo o uso real (cliente, serialização, erros, estados) e vejo se a atualização “passa” sem ajustes.
4) Pré-lançamentos, build metadata e como escolher a próxima versão
Além de MAJOR.MINOR.PATCH, o SemVer permite identificadores opcionais:
-
Pré-lançamento:
MAJOR.MINOR.PATCH-PRERELEASE
(ex.:1.4.0-beta.2). Indica instabilidade e pode quebrar compatibilidade.
Consumidores normalmente tratam isso como “não estável”. -
Build metadata:
MAJOR.MINOR.PATCH+BUILD
(ex.:1.4.0+20260429). É informativo; não deve afetar compatibilidade.
Na prática, existe um ciclo típico:
- Se a mudança é compatível: incrementa MINOR e, se aplicável, prepara beta.
- Se é correção compatível: incrementa PATCH (e sobe pré se estiver em ciclo de teste).
-
Se é quebra: incrementa MAJOR e volta o MINOR/PATCH para valores base,
seguindo seu padrão de release.
Ele só descreve o que deveria quebrar/ não quebrar conforme a sua decisão.
Exemplo técnico: decidir o incremento de versão
Use um “checklist” simples antes do release. Abaixo vai um pseudocódigo que eu uso como
guia mental para escolher o tipo de mudança.
function nextVersion(current, change) {
// current: { major, minor, patch }
// change: { breaksContract, addsCompatibleFeatures, fixesBugs, prerelease, buildMeta }
if (change.breaksContract) {
return `${current.major + 1}.0.0${change.prerelease ? '-beta.1' : ''}${change.buildMeta ? '+' + change.buildMeta : ''}`;
}
if (change.addsCompatibleFeatures) {
return `${current.major}.${current.minor + 1}.0${change.prerelease ? '-beta.1' : ''}${change.buildMeta ? '+' + change.buildMeta : ''}`;
}
if (change.fixesBugs) {
return `${current.major}.${current.minor}.${current.patch + 1}${change.prerelease ? '-rc.1' : ''}${change.buildMeta ? '+' + change.buildMeta : ''}`;
}
// Nenhuma mudança relevante no contrato/comportamento
return `${current.major}.${current.minor}.${current.patch}${change.buildMeta ? '+' + change.buildMeta : ''}`;
}
O que torna isso útil não é o “código”: é a disciplina.
Repare no primeiro caso (breaksContract) — ele domina todos os outros.
Quer continuar melhorando seu processo?
Se você gostou do raciocínio por trás de SemVer, vale a pena ler mais posts técnicos aqui no
yurideveloper.com.br sobre versionamento, contratos de API e releases com previsibilidade.
“`
Sou Apaixonado pela programação e estou trilhando o caminho de ter cada diz mais conhecimento e trazer toda minha experiência vinda do Design para a programação resultando em layouts incríveis e idéias inovadoras! Conecte-se Comigo!