Princípios SOLID em Java: teoria e prática para desenvolvedores

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

Princípios SOLID em Java: da teoria ao código limpo



Todo desenvolvedor Java, mais cedo ou mais tarde, enfrenta o problema do código "sujo": classes que fazem tudo ao mesmo tempo, dependências rígidas e impossibilidade de extensão sem quebrar a lógica existente. É aqui que os princípios SOLID entram em ação — cinco regras fundamentais de design orientado a objetos, formuladas por Robert Martin (Uncle Bob). Neste artigo, vamos analisar cada princípio na prática com exemplos em Java, para que seu código se torne flexível, testável e fácil de manter.



1. Single Responsibility Principle (SRP) — Princípio da Responsabilidade Única



Essência: "Uma classe deve ter apenas um motivo para mudar". Em outras palavras, a classe deve ser responsável por uma tarefa claramente definida.



Violação do SRP

Considere a classe OrderService, que simultaneamente calcula o preço, salva no banco de dados e envia e-mail:



public class OrderService {    public void processOrder(Order order) {        // 1. Cálculo do valor        double total = order.getItems().stream()                .mapToDouble(Item::getPrice)                .sum();

// 2. Salvamento no BD Database.save(order);

// 3. Envio de notificação EmailService.send("Pedido realizado no valor de: " + total); }}


Problema: Alterar a lógica de envio de e-mails ou a forma de salvamento forçará a modificação de OrderService. Isso viola o SRP.



Refatoração segundo o SRP

Dividimos as responsabilidades em três classes separadas:



public class PriceCalculator {    public double calculateTotal(Order order) {        return order.getItems().stream()                .mapToDouble(Item::getPrice)                .sum();    }}

public class OrderRepository { public void save(Order order) { Database.save(order); }}

public class NotificationService { public void sendConfirmation(Order order) { EmailService.send("Pedido realizado no valor de: " + order.getTotal()); }}

// Código clientepublic class OrderProcessor { private PriceCalculator calculator; private OrderRepository repository; private NotificationService notifier;

public void processOrder(Order order) { double total = calculator.calculateTotal(order); order.setTotal(total); repository.save(order); notifier.sendConfirmation(order); }}


Resultado: Cada classe tem um único motivo para mudar. O código se torna modular e testável.



2. Open-Closed Principle (OCP) — Princípio Aberto/Fechado



Essência: "Entidades de software devem estar abertas para extensão, mas fechadas para modificação". Nova funcionalidade é adicionada através de extensão, e não alterando o código existente.



Violação do OCP

Imagine um sistema de descontos onde cada novo tipo de desconto exige alteração no método applyDiscount:



public class DiscountService {    public double applyDiscount(String type, double price) {        if (type.equals("SUMMER")) {            return price * 0.9;        } else if (type.equals("VIP")) {            return price * 0.8;        }        // Adicionar novo tipo → alterar a classe        return price;    }}


Solução através de polimorfismo

Usamos uma interface e diferentes implementações:



public interface Discount {    double apply(double price);}

public class SummerDiscount implements Discount { @Override public double apply(double price) { return price * 0.9; }}

public class VipDiscount implements Discount { @Override public double apply(double price) { return price * 0.8; }}

// Novo tipo — apenas uma nova classe

Blogs

Book Recommendations