Introdução: Por que o código legado precisa de refatoração?
\n\nTodo desenvolvedor que trabalha com a plataforma .NET, mais cedo ou mais tarde, encontra código legado. São programas escritos em versões antigas do C# (por exemplo, .NET Framework 4.x), que usam padrões obsoletos como DataTable no ASP.NET Web Forms ou classes monolíticas com milhares de linhas. Esse código é uma fonte de dívida técnica: é difícil de manter, contém bugs ocultos e atrasa a implementação de novos recursos.
Refatoração é o processo de alterar a estrutura interna do código sem alterar seu comportamento externo. Neste artigo, vamos detalhar um plano passo a passo para refatorar código legado em C#, desde o diagnóstico até a implementação de práticas modernas. Você aprenderá como melhorar com segurança um projeto antigo usando ferramentas .NET e técnicas comprovadas.
\n\n1. Diagnóstico e preparação: por onde começar?
\n\nAntes de alterar o código, é necessário entender seu estado atual. Sem análise, você corre o risco de quebrar a funcionalidade.
\n\n1.1. Avaliação da dívida técnica
\nUse analisadores de código integrados ao Visual Studio ou disponíveis via NuGet:
\n- \n
- Roslyn analyzers — encontram erros potenciais e construções obsoletas. \n
- SonarQube (ou SonarCloud) — avalia qualidade do código, duplicação, complexidade. \n
- NDepend — visualiza dependências entre classes e módulos. \n
1.2. Escrever testes como rede de proteção
\nRefatoração sem testes é jogar roleta-russa. Para código legado, muitas vezes não há testes de unidade. Comece escrevendo testes de caracterização (characterization tests), que fixam o comportamento atual:
\n\n// Exemplo de teste para um método antigo\n[Test]\npublic void CalculateDiscount_ShouldReturn10Percent_WhenOrderTotalIsGreaterThan100()\n{\n // Arrange\n var legacyClass = new OrderProcessor();\n var order = new Order { Total = 150 };\n \n // Act\n var result = legacyClass.CalculateDiscount(order);\n \n // Assert\n Assert.AreEqual(15, result); // 10% de 150\n}\n\nCrie testes para os caminhos críticos. Isso permitirá refatorar com segurança, sabendo que o comportamento não mudará.
\n\n1.3. Escolha da estratégia: "Estratégia do jardim"
\nNão tente refatorar o projeto inteiro de uma vez. Escolha um módulo ou classe que cause mais problemas (alta complexidade, bugs frequentes). Trabalhe de forma iterativa: passos pequenos, commits frequentes.
\n\n2. Técnicas principais de refatoração de código legado em C#
\n\nVamos considerar os principais métodos que ajudarão a transformar "código espaguete" em uma arquitetura limpa.
\n\n2.1. Eliminação de God-objects (classes grandes)
\nFrequentemente, o código legado contém classes que fazem tudo: trabalham com banco de dados, validam dados, enviam e-mail. Use o princípio da Responsabilidade Única (SRP).
\n\nAntes da refatoração:
\npublic class UserService\n{\n public void RegisterUser(string name, string email)\n {\n // Validação\n if (string.IsNullOrEmpty(name)) throw new Exception();\n \n // Trabalho com BD\n using (var conn = new SqlConnection("..."))\n {\n conn.Execute("INSERT INTO Users ...");\n }\n \n // Envio de e-mail\n SmtpClient client = new SmtpClient();\n client.Send(new MailMessage(...));\n }\n}\n\nApós a refatoração:
\npublic class UserService\n{\n private readonly IUserRepository _userRepository;\n private readonly IEmailService _emailService;\n private readonly IValidator<UserRegistration> _validator;\n\n public UserService(IUserRepository repo, IEmailService email, IValidator<UserRegistration> validator)\n {\n _userRepository = repo;\n _emailService = email;\n _validator = validator;\n }\n\n public void RegisterUse