Refatoração de código legado em C#: Como transformar um projeto obsoleto em um produto .NET moderno
Todo desenvolvedor .NET mais cedo ou mais tarde se depara com código legado — classes monolíticas de 3000 linhas, lógica espaguete em arquivos .aspx.cs e strings mágicas espalhadas por todo o projeto. A refatoração desse código não é apenas "pentear" a sintaxe, mas uma tarefa estratégica: melhorar a arquitetura sem quebrar a lógica de negócios. Neste artigo, vamos analisar abordagens práticas para refatoração de código C# que ajudarão você a modernizar projetos herdados de forma segura e eficiente.
1. Preparação: Por que a refatoração de código legado exige uma abordagem especial
O principal erro dos iniciantes é começar imediatamente a reescrever o código. Em projetos legados C# .NET, frequentemente existem dependências ocultas: classes estáticas, estados globais, acoplamentos rígidos com o banco de dados via ADO.NET. Qualquer alteração pode causar uma cascata de erros.
Principais sinais de código legado em C#:
- Ausência de testes unitários — o código não é coberto por testes unitários, tornando a refatoração arriscada.
- God Objects (Objetos Divindade) — classes que fazem tudo: desde trabalhar com o banco de dados até renderizar a interface do usuário.
- Dependências rígidas — criação direta de instâncias via
new SqlConnection()dentro dos métodos. - Strings e números mágicos — configurações embutidas no código, em vez de em
app.configouappsettings.json. - Uso de APIs obsoletas — por exemplo,
WebClientem vez deHttpClientouArrayListem vez deList<T>.
Antes de iniciar a refatoração, certifique-se de: congelar os requisitos com o cliente, configurar o sistema de controle de versão (Git) e criar uma "rede de segurança" na forma de testes de integração.
2. Refatoração segura: Estratégia "Movendo a Parede"
A técnica clássica para C# é o Strangler Fig Pattern (Padrão Figo Estrangulador). Em vez de reescrever tudo de uma vez, você substitui gradualmente os componentes antigos por novos, até que o código antigo deixe de ser usado.
2.1. Extração de interfaces e injeção de dependências
O antipadrão mais comum em C# legado são os métodos auxiliares estáticos. Vejamos um exemplo:
// Código obsoletopublic class OrderService{ public void ProcessOrder(int orderId) { var conn = new SqlConnection("Server=myServer;Database=myDB;..."); var cmd = new SqlCommand("SELECT * FROM Orders WHERE Id = " + orderId, conn); // ... toneladas de lógica }}Passo 1: Extraímos uma interface para acesso a dados.
public interface IOrderRepository{ Order GetById(int orderId);}
public class OrderRepository : IOrderRepository{ private readonly string _connectionString;
public OrderRepository(string connectionString) { _connectionString = connectionString; }
public Order GetById(int orderId) { using var conn = new SqlConnection(_connectionString); // ... consulta segura }}Passo 2: Injetamos a dependência através do construtor. Agora você pode substituir o repositório nos testes, e o próprio OrderService deixou de depender de uma implementação específica do banco de dados.
public class OrderService{ private readonly IOrderRepository _orderRepository;
public OrderService(IOrderRepository orderRepository) { _orderRepository = orderRepository; }
public void ProcessOrder(int orderId) { var order = _orderRepository.GetById(orderId); // ... lógica de negócios }}2.2. Substituição de tipos obsoletos por modernos
No .NET Framework, eram frequentemente usados ArrayList, Hashtable e
Blogs
Book Recommendations
Leia também
Como fazer profiling de código Python: guia prático
Microsserviços em TypeScript: por onde começar em 2024
Erros ao aprender C#: o que os iniciantes fazem (e como evitá-los)
Barra de status no iOS: 5 erros fatais com cor do texto (Swift)
Salários de desenvolvedores C++ na Rússia: panorama do mercado 2024