fbpx
Quando fazer upgrade da minha aplicação .NET?
Publicado em: quarta-feira, 8 de maio de 2024
Categorias: .NET | .NET de A a Z
Tags: .NET Core

Muitas vezes aparece a dúvida sobre quando fazer o upgrade de uma versão do .NET.

Será que vale a pena pular de LTS em LTS ou vale a pena pegar as STS’s no meio do caminho?

Empresas burocráticas, devem mudar suas políticas ou não?

Hoje vamos tratar desse assunto, com os meus argumentos, mostrando as recomendações que faço mais ou menos desde 2017~2018.

Disclaimers

  1. Você é totalmente livre, para não concordar, para não seguir essa recomendação.
  2. Meu objetivo não é te convencer, nem te recomendar nada.
  3. Meu 1° objetivo é mostrar o que recomendo e por que recomendo.
  4. Meu 2° objetivo é parar de responder essa pergunta tendo de escrever em um chat, boa parte das vezes com uma grande limitação de caracteres.

Contexto

O primeiro ponto que preciso citar aqui é minha experiência com .NET. Desde a versão 1, lá em 2002, levei alguns meses ter a permissão para trabalhar com .NET, lá na Petrobras, em 2003.

Desde então NUNCA abandonei o .NET.

Estive presente e usei absolutamente todas as versões do .NET sem pular nenhuma, isso desde 2003 até hoje.

Já conduzi ao menos 2 centenas de migrações de projetos pessoais, e muitas migrações em projetos de clientes, acredito que mais de 500 projetos, em ao menos umas 50 solutions.

SemVer

Para ficar claro como podemos ver SemVer aqui no .NET, vamos pegar a versão mais recente do .NET instalada no meu desktop hoje, no dia em que escrevo esse post:

Então a versão mais recente é a versão 8.0.300-preview.24203.14 que se apresenta como na tabela abaixo:

MAJORMINORPATCHBUILD
80300preview.24203.14

O que esperar quando uma versão muda?

MAJOR

Sempre que temos uma MAJOR nova, temos mais impacto, temos breaking changes, mudanças que demandam algum tipo de reescrita de código.

MINOR

Sempre que temos uma MINOR nova, temos um impacto menor, sem breaking changes, em geral, estamos falando da adição de features.

PATCH

Sempre que temos um PATCH novo, temos uma correção. De qualquer natureza. Seja um bug, uma correção de segurança, algo que resolve qualquer tipo de problema sem adicionar recursos novos.

BUILD

O build é um um número não relacionado aos demais, ele caminha isolado. É usado internamente para determinar qual build gerou uma determinada versão.

Se quisermos identificar qual versão dos fontes foram usados, voltar à pipeline de CI/CD, e encontrar essa task com o ID do build. Olhando os logs encontraremos exatamente qual versão do repositório de fontes foi usada para gerar aqueles artefatos.

A Microsoft usa essa abordagem há muitos anos.

O ciclo de vida do .NET

No passado, na época do .NET Framework a Microsoft possuia um ciclo de releases que parecia mais moderado aos olhos desatentos.

VersãoCLRRelease Date
1.01.0Jan/2002
1.11.1Abr/2003
2.02.0Out/2005
3.02.0Nov/2006
3.52.0Nov/2007
4.04.0Ago/2010
4.54.0Ago/2008
4.5.14.0Out/2013
4.5.24.0Mai/2014
4.64.0Jul/2015
4.6.14.0Nov/2015
4.6.24.0Ago/2016
4.74.0Abr/2017
4.7.14.0Out/2017
4.7.24.0Abr/2018
4.84.0Abr/2019
4.8.14.0Ago/2022

Note que embora o ciclo de releases seja elevado, o ciclo de novas CLR’s é muito baixo, se mantendo o mesmo desde 2010.

Em agosto completamos 14 anos com a mesma CLR no .NET Framework.

E qual o impacto disso? Baixa evolução.

Toda mudança que não gere mudança na CLR é incremental, novas bibliotecas, novas recursos, mas sob uma mesma baseline. Sobre um mesmo core.

O .NET Framework é um ambiente de execução de runtime que gerencia os aplicativos destinados ao .NET Framework. Ele consiste no Common Language Runtime, que fornece gerenciamento de memória e outros serviços do sistema, além de em uma biblioteca de classes extensa, o que permite que programadores usem o código robusto e confiável para todas as áreas principais do desenvolvimento de aplicativos.

Introdução ao .NET Framework

Em linhas gerais, as grandes mudança ocorrem quando você mudava de versão da CLR, as demais mudanças eram incrementais e retrocompatíveis. Ou seja, o nível de impacto era muito baixo, embora sempre fosse necessário instalar uma nova versão do .NET.

Essas versões intermediárias traziam novos recursos, com zero ou quase zero impacto para os aquilo que já funcionava.

Outro aspecto importante, principalmente na era do Windows Server e do IIS, era a compatibilidade. Na mesma CLR tínhamos baixíssimos conflitos, mas manter 2 CLR’s simultaneamente no mesmo servidor sempre trouxe necessidade de cuidados especiais, principalmente na precedência da instalação do .NET e cuidados relativos à chamadas ao aspnet_regiis.exe para configurar o IIS com a versão desejada.

Outro cuidado necessário nessa época pré-containers, é a necessidade de isolar Application Pools do IIS por versão do .NET.

Hoje nada disso é necessário com .NET Core, principalmente com o Kestrel embarcado no .NET.

Com o uso massivo de containers, não temos mais conflitos entre versões do .NET, já que todo o grafo de dependências é resolvido dentro do container, com componentes que já vieram embarcados na imagem, isso faz com que possamos ter 10 versões diferentes sem que nenhuma afete as demais.

Mas antes dos containers, sempre foi tenso!

A era do .NET Core e nova visão da Microsoft

Embora a lista de releases possa ser intensa, como demonstrado na tabela do tópico anterior, e talvez tão intensa quanto hoje, a gente nunca sentia tanto impacto como sentimos hoje.

As mudanças de major nas releases do .NET Core fizeram com que tivéssemos mais retrabalho do que tínhamos no passado, com .NET Framework.

Isso porque, na prática, no passado só era preocupante e só demandava mais esforço para compatibilizar código, quando mudávamos de versão da CLR.

VersãoRelease Date
.NET Core 1.0Jun/2016
.NET Core 1.1 Nov/2016
.NET Core 2.0Ago/2017
.NET Core 2.1Mai/2018
.NET Core 2.2Dez/2018
.NET Core 3.0Set/2019
.NET Core 3.1Dez/2019
.NET 5Nov/2020
.NET 6Nov/2021
.NET 7Nov/2022
.NET 8Nov/2023
.NET 9Nov/2024 (projected)
.NET 10Nov/2025 (projected)

Então, a preocupação sobre mudanças quando uma major é lançada, não muda, entretanto a frequência com que major versions são lançadas mudou.

Afinal, quando migrar?

Eu aqui estou considerando:

  • Pequenos projetos
  • Projetos grandes
  • Empresas cuja burocracia é grande, como bancos e instituições financeiras em geral.
  • SMB’s (pequenos e médios negócios)
  • Free Lancers e profissionais liberais
  • Empresas que cultuam o pensamento: Se está funcionando não mexa.

Minha recomendação é não pular nenhuma release.

Isso quer dizer, necessariamente, realizar migrações de tudo 1 vez por ano.

Migrar projetos deve ser uma tarefa anual, acontecendo em uma janela muito específica:

  • De: 3 meses depois do lançamento de uma nova release
  • Até: 3 meses antes do lançamento de uma nova release

Como podemos, desde 2018, ter como base novembro para o lançamento de novas releases do .NET, podemos considerar que todo projeto deve ser migrado entre março e agosto (6 meses).

JANFEVMARABRMAIJUNJULAGOSETOUTNOVDEZ
XXXXXXRelease

Durante esse período, há abundância de conteúdo que auxilie nessa migração. Nessa janela, a migração é menos hostil, ao contrário, é fácil, é dócil, e tende a ser uma jornada muito tranquila.

De um lado você está migrando apenas da versão anterior para a nova, sem grandes saltos. Isso facilita a migração e torna mais suave.

Outra característica desse tipo de migração, é que o tempo de execução é muito pequeno. Projetos pequenos conseguem ser migrados em minutos, enquanto projetos grandes em horas ou dias.

Em contrapartida, ao se aproximar da nova release, uma enxurrada de posts e lançamentos começam a atrapalhar a jornada.

Mas se não conseguiu realizar dentro de uma janela, pule para a próxima.

Custos e Questões

Sim, está claro que temos um custo aumentado com essa decisão, entretanto manter aplicações em versões legadas, dificulta todo o ciclo de vida da aplicação e potencializa a chance da aplicação ser considerada legado, bem cedo.

Isso quer dizer que parte da longevidade de uma aplicação diz respeito às suas tecnologias e à idade delas.

Quanto mais atual, menor o ímpeto em se reconstruir tudo do zero.

Ademais, estamos cuidando para que argumentos como:

  • “Na versão atual não há como resolver isso sem xpto, mas não podemos usar”
  • “Já criaram uma solução para isso, mas não podemos usar”

Os argumentos que demandariam refatoração, somente nos momentos críticos onde não se é mais possível realizar uma tarefa por conta da versão antiga, deixam de existir.

Um dos principais motivadores para quererem jogar uma aplicação no lixo e reescrever do zero, são resolvidos.

Então, embora pouco tangível, é minha abordagem e minha recomendação clara e límpida.

Outra característica importante é que o esforço de migração é substancialmente reduzido na medida que é feito nessa janela. Isso porque temos abundância de conteúdo e diluímos a complexidade na medida que não acumulamos migrações.

Conclusão

Fazer esse tipo de migração anualmente tem muito potencial para reduzir os custos no médio prazo. Além de tornar o produto ou projeto um ativo e diferencial na hora de ofertar vagas, já que poderá falar sobre estar nas últimas versões de uma tecnologia.

A redução do escopo de migração é substancial, principalmente pela abundância de soluções e recomendações.

Temos como benefício a diluição dos riscos, pois com menor escopo, temos menor superfície de migração.

Assim, para quem seguir essa recomendação, comente aqui, eu quero ver suas impressões ao longo do tempo.

E quando houver necessidade de rollback? [2024-05/22]

Um dos pontos que gostaria de ter abordado na época, mas me esqueci, era o problema da incapacidade de migração de um ou outro projeto.

Um benefício indireto da abordagem proposta nesse post, é saber que a migração de um determinado projeto é problemática, bem antes de precisar dela.

Imagine o cenário onde 4 anos depois, na hora de realizar uma implementação acordada com um cliente, uma implementação importante, você descobre que já não é possível migrar esse projeto?

Da forma proposta aqui, podemos descobrir mais cedo e ganhar mais tempo para :

  • migrar as funcionalidades para outra aplicação
  • planejar uma substituição de um componente
  • realizar qualquer demanda que desbloqueie a migração desse projeto

A grande diferença é que você consegue proativamente saber que aquele projeto deve ser marcado como legado e já sabe que não pode ser migrado.

Em contrapartida, aquele projeto que não pode ser migrado é uma exceção em um parque com 10, 20, 50 projetos diferentes.

Tratar exceção como exceção é uma forma responsável, e sabemos que toda empresa terá seus patinhos-feios. Mas em vez de ser a regra, é a exceção, e tudo bem com isso.

[default]

2 Comentários

  1. Fabio Braga

    Um ponto importante na atualização continua planejada é quanto a segurança. Os pacotes recebem correções ao serem notificados/identificado. Mas há mais, bugs, performance e suporte podem explodir ainda mais as preocupações quanto a atualização.
    Vale lembrar que o mercado acaba exigindo mais e mais, profissionais se qualificam com as mais modernas possíveis, e problemas do passado em implementações passam a ser um estorvo na vida do codificador que busca uma linha de trabalho conhecida, eficaz e rotineira.
    Atualizações constantes garante menor impacto as de mais longo prazo, também terão menor custo e risco.
    É importante ter um calendário estratégico onde garanta a maturidade da atualização e possibilidade de testes de garantia.

    Responder
  2. Gilmar Santana

    Achei muito interessante a tabela com a janela anual de atualização. Vou levar isso em consideração para meu time.

    Responder

Enviar um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *

Esse site utiliza o Akismet para reduzir spam. Aprenda como seus dados de comentários são processados.

[special-full-page]

Lives

Fique de olho nas lives

Fique de olho nas lives no meu canal do Youtube, no Canal .NET e nos Grupos do Facebook e Instagram.

Aceleradores

Existem diversas formas de viabilizar o suporte ao teu projeto. Seja com os treinamentos, consultoria, mentorias em grupo.