Refatoração de código legado em C#: guia passo a passo

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course
```html

Introdução: Por que refatorar código legado em C# é uma necessidade



Todo desenvolvedor .NET mais cedo ou mais tarde enfrenta código legado. Não é necessariamente um projeto de 20 anos no .NET Framework 1.1 — muitas vezes, "legado" se torna o código escrito há um ano com pressa, sem testes e violando os princípios SOLID. Trabalhar com esse código se torna um pesadelo: qualquer alteração quebra a funcionalidade em lugares inesperados, e entender a lógica só é possível através de debug.



Refatoração não é reescrever do zero. É melhorar a estrutura interna do código sem alterar seu comportamento externo. Neste artigo, vamos abordar técnicas práticas de refatoração de código legado em C# que podem ser aplicadas imediatamente, minimizando riscos.



1. Preparação: A regra de ouro da refatoração



Antes de alterar o código, certifique-se de que você tem uma "rede de segurança" — um conjunto de testes automatizados. Sem eles, a refatoração se torna um palpite.



Criação de testes de caracterização (characterization tests)

Se não houver testes, escreva testes de caracterização (também conhecidos como golden master ou snapshot tests). A ideia é simples: execute o método com diferentes entradas, registre o resultado e, em seguida, verifique se após a refatoração o resultado não mudou.



// Exemplo de teste de caracterização para um método legado[Test]public void CalculateTotal_ShouldReturnSameResult_AfterRefactoring(){    // Arrange    var order = new Order { Items = new List<Item> { new Item { Price = 100, Quantity = 2 } } };    var expected = 200; // Resultado previamente conhecido

// Act var result = LegacyOrderCalculator.CalculateTotal(order);

// Assert Assert.AreEqual(expected, result);}


Dica: Use bibliotecas como Verify ou ApprovalTests para testes de snapshot automatizados.



2. Técnica nº1: Extrair método (Extract Method)



A técnica mais simples e eficaz. Quando você vê um método de 200 linhas com comentários como "// aqui cálculo de desconto" — é um candidato ideal.



Exemplo: Método grande



public decimal ProcessOrder(Order order){    decimal total = 0;    foreach (var item in order.Items)    {        total += item.Price * item.Quantity;    }

// Cálculo de desconto if (order.Customer.IsPremium) { total *= 0.9m; // 10% de desconto } else if (order.TotalAmount > 1000) { total *= 0.95m; // 5% de desconto }

// Aplicação de imposto total *= 1.2m; // 20% de imposto

return total;}


Após a refatoração



public decimal ProcessOrder(Order order){    decimal subtotal = CalculateSubtotal(order.Items);    decimal afterDiscount = ApplyDiscount(subtotal, order.Customer);    return ApplyTax(afterDiscount);}

private decimal CalculateSubtotal(IEnumerable<Item> items){ return items.Sum(item => item.Price * item.Quantity);}

private decimal ApplyDiscount(decimal total, Customer customer){ if (customer.IsPremium) return total * 0.9m; if (total > 1000) return total * 0.95m; return total;}

private decimal ApplyTax(decimal amount){ return amount * 1.2m;}


Vantagens:

  • Cada método tem uma única responsabilidade
  • O código se torna legível e testável
  • A lógica de desconto pode ser reutilizada em outros lugares


3. Técnica nº2: Substituir lógica condicional por polimorfismo



Código legado frequentemente contém longas cadeias de if-else ou switch. Isso viola o princípio aberto/fechado (OCP).



Exemplo: Switch por tipo de documento



public decimal CalculateShippingCost(Order order){    switch (order.ShippingType)    {        case "Standard":            return 5;        case "Express":            return 15;        case "Overnight
```                

Blogs

Book Recommendations