Aula 08
Como o Golang Escolhe que Versão da Dependência Usar (Versões Semânticas e Seleção Mínima)
Summary
Resumo da Aula de Golang: Gerenciamento de Versões de Módulos
Bem-vindo à aula sobre como o Go lida com diferentes versões de um mesmo módulo, abordando dependências indiretas.
Introdução
- O foco da aula é o gerenciamento de versões semânticas e a escolha de versões de módulos pelo Go.
- Um exemplo prático é apresentado com um consumidor que depende de múltiplos módulos (A, B, C), todos os quais dependem do módulo X, mas com versões diferentes.
Versões Semânticas (SemVer)
Formato de Versão
- As versões são numeradas como
vX.Y.Z
, onde:- X: Versão maior (major)
- Y: Versão menor (minor)
- Z: Versão de patch (patch)
Significado dos Números
- Versão Maior: Incrementa em mudanças que quebram a compatibilidade.
- Versão Menor: Incrementa ao adicionar novas funcionalidades de forma compatível.
- Patch: Incrementa ao corrigir bugs sem alterar funcionalidades.
Importância da Compatibilidade
- Mudanças na versão maior quebram a compatibilidade, enquanto mudanças na versão menor ou de patch não quebram.
Escolha de Versões no Go
Mínima Seleção de Versão (Minimum Version Selection - MVS)
- O Go escolhe a versão mais recente que atende as dependências dos módulos consumidores (mantendo compatibilidade).
- No exemplo, o Go escolheria a versão 1.8.0 do módulo X, mesmo que os módulos A e B não usem suas funcionalidades adicionais.
Condição Necessária
- As dependências devem seguir corretamente o padrão SemVer para que a seleção funcione como esperado.
Demonstração Prática
- O comando
go list -m all
pode ser usado para verificar qual versão está sendo utilizada na construção do consumidor. - Ao modificar as dependências (excluindo módulos), a versão utilizada mudará conforme a necessidade de cada módulo.
Conclusão
- O gerenciamento de versões é essencial para garantir que as dependências funcionem corretamente sem quebras.
- O Go faz isso eficientemente através da seleção da versão mínima disponível para cada módulo.
Até a próxima aula!
Video Transcript
Bem-vindo a mais uma aula de Golang. Nessa aula eu vou falar de como o Gol lida com versões diferentes do mesmo módulo.
Este módulo vindo como, por exemplo, dependências indiretas através de um módulo que você requere explicitamente.
Eu vou começar explicando versões semânticas e depois disso a gente vai ver como é que o Gol escolhe qual versão do mesmo módulo usar na build final.
Então vamos lá pessoal. Eu tenho esquecido este diagrama. No topo de diagrama tem uma caixa com o texto consumidor.
Este vai ser o programa consumidor de vários módulos. Por exemplo, este consumidor depende do módulo a e depende do módulo b e depende do módulo c.
E cada módulo que a dependência do consumidor depende do módulo chamado x.
Note que o módulo a depende do módulo x, o módulo b também depende do módulo x e o módulo c também depende do módulo x.
Essas três dependências dependem por si próprias do mesmo módulo x.
Mas a versão é diferente. O módulo a requere módulo x na versão 1.6.2.
Então, no módulo b requer módulo x na versão 1.7.4.
O módulo c, finalmente, requer a versão do módulo x 1.8.0, que é mais atual neste caso, nesta lista de versões.
Então, neste caso, quando o gol compilar o programa consumidor, que depende de módulo a, b e c, que por si próprios depende do módulo x,
qual versão do módulo x o gol vai escolher? Será que a mais baixa é 1.6.2, ou é a do meio 1.7.4, ou é a mais atual desta lista, 1.8.0?
Então, vamos ver. Primeiro eu gostaria de falar de versões semânticas.
Então, vamos aqui.
No inglês, semétric vergonim, a sigla também é chamada de semver.
O que é que é isso? Então, um padrão de numeração de versões de software.
Neste padrão, a versão é numerada da seguinte maneira.
Você digita v, seguido de o número x, ponto número y, ponto número z.
Certo?
Por exemplo, v1.0.0, v1.2.0, v1.2.3.
Agora, o que é que cada número x e v2.0.0 significa?
Vou te explicar aqui. Então, o primeiro que é o x, é o número à esquerda, tem três números.
A esquerda, depois do v, é a versão maior, major.
E o número do meio, entre os pontos, é a versão menor, no inglês minor.
E, finalmente, o último número à direita, no final, é o remendo, no inglês patch.
Então, o que é que é isso?
Então, cada número desses tem um significado se você obedecer o padrão semver.
Toda vez que você fazer uma mudança no software e você lançar uma nova versão,
qual que é o número que você vai incrementar?
Bem, depende das mudanças que você fez.
Então, deixa eu te explicar maior.
O número maior vai ser incrementado e todos os números à direita serão zerados.
Quando você tiver a mudança no seu código, que vai quebrar os programas que dependem do seu programa.
No inglês, é chamado Breaking Change.
Uma mudança que, se você atualizar da upgrade para essa nova versão,
o seu programa que depende desse software não vai mais funcionar, vai quebrar.
Então, se isso acontecer, você teria que incrementar o número à esquerda.
Nesse caso, por exemplo, 1, 2, 3, iria se tornar 2 e você zera o do meio e o da direita.
Agora, vamos para menor, que é o número do meio.
Menor seria quando você adiciona funções adicionais ao seu código, seu programa.
Então, você iria incrementar o número do meio e iria zerar o número à direita.
Isso significa funções adicionais que não quebram o software como ele está.
É apenas algo a mais que você adiciona.
As coisas que já tinham continuam, na mesma maneira.
Vou te dar um exemplo aqui.
Por exemplo, se o 1, 2, 3 aqui da linha 13,
se eu adicionasse algo a mais, mais as outras funções antigas ainda funcionasse da mesma maneira,
eu aumentaria o número do meio, que é o 2 para 3 e zeraria o número à direita.
Então, nesse caso, 1, 2, 3, iria se tornar 1, 3, 0.
Está certo?
Agora, vamos falar de patch ou remando.
Você incrementa o número à direita, se você consertar algum bug naquela versão menor.
Então, patch, que é o número à direita, no final da numeração, é para o conserto de bugs.
Isso significa que não houve nenhuma mudança radical no código e também não houve nenhuma adição de função.
O que já existia, tinha algum problema, algum bug que foi consertado e agora ele funciona em comportamento correto.
Nesse caso, você só incrementaria o número mais à direita da numeração.
Por exemplo, no 1, 2, 3, se o programa, a próxima versão só tivesse um conserto de bugs, você aumentaria do 3 à direita para 4.
Então, versão 1.2.3 se tornaria 1.2.4.
Está bom?
Eu quero que você note que quando muda a menor ou quando muda o patch, não há uma quebra do programa.
Não há a breaking change, como é a mudança da maior.
Isso é importante, porque, por exemplo, entre a versão 1.2.0 e 1.2.3, eu poderia usar ambas.
No meu programa e não haveria nenhuma quebra.
Poderia também usar a versão 1.0.0 em um programa.
E você poderia atualizar para 1.2.0 e não iria quebrar nada, porque a 1.2.0 seria uma incrementação da versão menor, que seriam funções adicionais.
Então, como eu estava usando a versão 1.0.0, eu estava usando as funções antigas que já existiam.
Quando eu dar o upgrade para 1.2.0, novas funções serão adicionadas, mas como meu programa não usa essas funções adicionais, não irá ocorrer nenhuma quebra no meu programa.
Então, é importante essa que eu acabei de falar, porque é isso que o Go vai usar para determinar qual versão usar.
Se lembra desse lance de funções adicionais e do seu programa, não usar essas funções adicionais.
De volta aqui ao desenho.
Vamos analisar na maneira Samver.
O módulo X usa Samver.
A primeira versão é 1.6.2.
A versão maior é 1, o número maior é 1, o número menor é 6 e o remando é 2.
O que significa o que?
Houve alguns bugs do .0, então, o .2 à direita significa que houve dois lançamentos em que os bugs foram concertados.
Agora, essa próxima módulo B usa a versão 1.7.4.
O que significa?
Significa que houve uma adição de certas funções da versão 6 menor para 1.7.4.
Mas note que se o módulo A usa as funções da 1.6 e o módulo B requer em 1.7, que tem coisas adicionais,
o módulo A ainda vai funcionar se estivesse usando o .7, porque as funções adicionais que vieram no 1.7 não são usadas pelo módulo A.
Agora, o módulo C usa a versão mais nova nessa lista de versões aqui, nesse caso, 1.8.0.
Então, mais uma versão menor, que é o número do meio, que adicionou mais coisas.
Agora, o módulo B, que tem a versão 1.7, com certeza não vai usar as novidades da versão 1.8, que foram adicionadas.
Então, por isso, A ainda funciona se eu tivesse usando o .8 no módulo B.
Da mesma maneira, o .8 no módulo A também funcionaria.
Então, isso eu já te dei a dica de qual o gol que vai escolher, né?
E vai escolher a 1.8, porque tem coisas adicionais que o B nem o A vai usar, mas ainda funciona no A e no B,
porque as coisas antigas ainda permanecem da mesma maneira, porque não houve uma quebra de mudança com a versão maior.
Note que a versão maior dos três modos ainda é a versão 1.
Vamos aqui continuar a falar da escolha do gol.
Então, acabamos de falar de versões semânticas, semantic versioning, semver.
Agora, vamos falar da maneira que o gol escolhe e eu acabei de dar a resposta, né?
Então, no inglês, minimum version selection, MBS, é o que o gol usa, traduzindo essa versão de versão mínima.
Mas esse mini não significa que ele vai escolher a versão mais antiga, então não confunda com isso.
Isso significa que ele vai escolher a versão mínima, cujas funcionalidades estão disponíveis para cada módulo.
Nosso caso era 1.8 lá, que tinha funções adicionais que só o módulo C precisaria, então o módulo B e nem o A não precisam,
mas o C precisa então a mínima, nesse caso, seria 1.8.
Mas, claro, para isso funcionar direito, tem que ter a pré-condição aqui, que na linha 3 tem o que eu escrevi,
que o módulo, as dependências, tem que obedecer o padrão sem ver corretamente na numeração das versões.
Isso significa que ele tem que obedecer essas regras aqui que a gente acabou de falar da maior só com T breaking change,
da menor ter funções adicionais e do remendo ter concerto de bugs.
Se não obedecer, aí vai dar problema.
Nesse caso, o módulo teria que consertar o padrão de versões para que o gol possa funcionar corretamente.
Tá bom?
Então, de acordo com essa seleção de versão mínima, no nosso exemplo, a resposta seria o módulo X de versão 1.8.0,
que seria usado para fazer a build do consumidor.
Para confirmar isso, eu fiz um exemplo para vocês verem aqui.
Eu tenho aqui no lado esquerdo, eu queria um pacote consumidor.
Eu tenho um gol.mod, que define as dependências do módulo A, módulo B, módulo C.
Eu queria esses módulos aqui localmente, por isso que tem que ter esse replays,
que realmente não está hospedado aqui nesse domínio.
Então, ele depende de módulo A, B e C.
Eu queria o módulo A aqui no lado esquerdo, que tem um pacote que o gol.mod dele é.
Nesse caso, eu usei como dependência compartilhada entre todos os módulos, o gorilamax,
github.com, barra gorila, barra mox.
Nesse caso, versão 1.6.2 requerida pelo módulo A.
Para módulo B, requer em versão 1.7.4.
Para módulo C, requer em 1.8.0.
Certo?
Certo?
Agora vamos aqui demonstrar qual versão ele vai usar na build final.
Como é que eu posso saber? Ah, qual é que o gol vai usar?
Será que é 1.8, como a gente espera, né?
Ou é 1.7.4 ou é 1.6.2? Como é que eu confirmo isso?
Bem, a gente pode usar o comando golista.
Isso aqui no meu terminal.
Dentro da parte do projeto consumidor, eu posso falar gol, espaçoList, espaçoTraxUm, espaçoO.
Isso vai listar as dependências módulos.
TraxUm significa listar os módulos em vez de pacotes.
E all é todos.
Então ele mostra quais são as dependências módulos em que o programa consumidor depende, módulo consumidor depende.
Nesses casos, a gente está interessado no gorila mox.
Github.com.grilla.mox e ele diz que vai usar a versão 1.8.0 e isso confirma o que a gente esperava.
Tá certo?
Se você quiser fazer um exercício, você pode remover o módulo C.
E você vai ver que ele vai usar a versão do módulo B que é 1.7.4.
Que confirmaria, se você tivesse o módulo A e o módulo B, nesse caso a versão mínima,
seria 1.7.4, que seria mínima para funcionar em todos os módulos.
Nesses casos 1.7 teria algo adicional a 1.6, que o módulo A não precisaria, mas o módulo B precisa ter.
Então funcionaria no A, porque ele ainda estava usando as funções antigas, que ainda tem na versão 1.7.
E para o módulo B ele usa talvez as funções mais novas, então precisaria 1.7.4.
E assim por diante você pode dar a módulo A e ver o que acontece, ou dar a módulo B
e confirmar com o gol, list, traço M, all.
Tá bom pessoal?
Então espero que vocês tenham gostado dessa aula e até mais.
Tchau!
Nenhum comentário ainda (loading...)
Nenhum comentário ainda (loading...)
Gostou da aula? 😆👍
Apoie nosso trabalho com uma doação: