Introdução: Por que SOLID é a base do código C# de qualidade
Desenvolver em C# no ecossistema .NET exige não apenas conhecimento de sintaxe, mas também a capacidade de projetar aplicações flexíveis, sustentáveis e testáveis. SOLID é a sigla para cinco princípios fundamentais de design orientado a objetos, formulados por Robert Martin. Eles ajudam os desenvolvedores a evitar dependências "rígidas", duplicação de código e problemas de escalabilidade.
Neste artigo, vamos analisar cada um dos cinco princípios SOLID aplicados ao C#: da teoria a exemplos reais de código. Você aprenderá como a refatoração com SOLID torna seu código mais limpo e a manutenção dos projetos mais simples.
1. Single Responsibility Principle (SRP) — Princípio da Responsabilidade Única
Teoria
Uma classe deve ter apenas um motivo para mudar. Em outras palavras, cada classe é responsável por exatamente uma funcionalidade ou lógica de negócio. Se uma classe faz demais, ela se torna difícil de testar, modificar e reutilizar.
Prática: violação do SRP
public class OrderProcessor{ public void ProcessOrder(Order order) { // 1. Validação do pedido if (order.Total <= 0) throw new Exception("Invalid order"); // 2. Salvamento no banco de dados using var db = new AppDbContext(); db.Orders.Add(order); db.SaveChanges(); // 3. Envio de notificação por email SmtpClient client = new SmtpClient(); client.Send("admin@shop.com", order.CustomerEmail, "Order confirmed", "Thank you!"); }}Aqui, OrderProcessor viola o SRP: ele é responsável pela validação, operações com banco de dados e envio de email. Alterar a lógica de envio de notificações exigiria modificar esta mesma classe.
Refatoração com SRP
public class OrderValidator{ public bool Validate(Order order) => order.Total > 0;}
public class OrderRepository{ public void Save(Order order) { using var db = new AppDbContext(); db.Orders.Add(order); db.SaveChanges(); }}
public class EmailService{ public void SendConfirmation(string email) { SmtpClient client = new SmtpClient(); client.Send("admin@shop.com", email, "Order confirmed", "Thank you!"); }}
public class OrderProcessor{ private readonly OrderValidator _validator; private readonly OrderRepository _repository; private readonly EmailService _emailService;
public OrderProcessor(OrderValidator validator, OrderRepository repository, EmailService emailService) { _validator = validator; _repository = repository; _emailService = emailService; }
public void ProcessOrder(Order order) { if (!_validator.Validate(order)) throw new Exception("Invalid order"); _repository.Save(order); _emailService.SendConfirmation(order.CustomerEmail); }}Agora cada classe tem uma única área de responsabilidade. Isso simplifica os testes e a modificação.
2. Open/Closed Principle (OCP) — Princípio Aberto/Fechado
Teoria
Entidades de software (classes, módulos, funções) devem estar abertas para extensão, mas fechadas para modificação. Ou seja, você deve ser capaz de adicionar novas funcionalidades sem alterar o código existente.
Prática: violação do OCP
public class ShapeDrawer{ public void DrawShape(object shape) { if (shape is Circle circle) Console.WriteLine($"Drawing circle with radius {circle.Radius}"); else if (shape is Rectangle rect) Console.WriteLine($"Drawing rectangle {rect.Width}x{rect.Height}"); // Ao adicionar um novo tipo de forma — é necessário modificar este método! }}Refatoração com OCP através de abstração
public abstract c
```