Movatterモバイル変換


[0]ホーム

URL:


Skip to content
DEV Community
Log in Create account

DEV Community

     

Desenvolvimento Orientado a SOLID

No desenvolvimento de software, a manutenção, extensão e a flexibilidade do código são importantes para o sucesso a longo prazo de um projeto. Os princípios SOLID foram formulados para orientar os desenvolvedores na criação de código que seja mais fácil de entender, modificar e estender. Neste artigo, vamos falar de cada um dos cinco princípios SOLID e como usar com exemplos práticos em Java.

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

O Princípio da Responsabilidade Única (SRP) estabelece que uma classe deve ter apenas uma razão para mudar, ou seja, deve ter uma única responsabilidade dentro do sistema.

// Antes de aplicar o SRPclass ProductService {    public void saveProduct(Product product) {        // Lógica para salvar o produto no banco de dados    }    public void sendEmail(Product product) {        // Lógica para enviar um email sobre o produto    }}
Enter fullscreen modeExit fullscreen mode
// Após aplicar o SRPclass ProductService {    public void saveProduct(Product product) {        // Lógica para salvar o produto no banco de dados    }}class EmailService {    public void sendEmail(Product product) {        // Lógica para enviar um email sobre o produto    }}
Enter fullscreen modeExit fullscreen mode

No exemplo, separamos a responsabilidade de salvar um produto no banco de dados da responsabilidade de enviar e-mails sobre o produto. Isso facilita futuras mudanças, pois alterações no envio de e-mails não afetam mais a lógica de salvamento de produtos.

2. Open/Closed Principle (Princípio do Aberto/Fechado)

O Princípio do Aberto/Fechado (OCP) sugere que as entidades de software (classes, módulos, funções, etc.) devem estar abertas para extensão, mas fechadas para modificação. Isso é alcançado através do uso de abstrações e herança.

// Exemplo inicial violando o OCPclass AreaCalculator {    public double calculateArea(Rectangle[] rectangles) {        double area = 0;        for (Rectangle rectangle : rectangles) {            area += rectangle.width * rectangle.height;        }        return area;    }}
Enter fullscreen modeExit fullscreen mode
// Exemplo após aplicar o OCPinterface Forma {    double calculateArea();}class Rectangle implements Forma {    private double width;    private double height;    public Rectangle(double width, double height) {        this.width = width;        this.height = height;    }    @Override    public double calculateArea() {        return width * height;    }}class AreaCalculator {    public double calculateArea(Forma [] formas) {        double area = 0;        for (Forma formas: formas) {            area += forma.calculateArea();        }        return area;    }}
Enter fullscreen modeExit fullscreen mode

Nesse segundo exemplo, inicialmente a classeAreaCalculator estava diretamente dependente da classeRectangle. Isso significa que se você quisesse adicionar outro tipo de forma, como um círculo ou um triângulo, você precisaria modificar a classeAreaCalculator, violando assim o OCP. Com a criação da interfaceForma, a classeAreaCalculator é capaz de receber novas formas geométricas sem modificar o código existente.

3. Liskov Substitution Principle (Princípio da Substituição de Liskov)

O Princípio da Substituição de Liskov (LSP) afirma que objetos de uma superclasse devem ser substituíveis por objetos de suas subclasses sem afetar a integridade do sistema. Em outras palavras, o comportamento das subclasses deve ser consistente com o comportamento das superclasses.

// Classe baseclass Bird {    public void fly() {        // Método padrão que imprime "Flying"        System.out.println("Flying");    }}// Classe derivada que viola o LSPclass Duck extends Bird {    @Override    public void fly() {        // Sobrescrita que imprime "Ducks cannot fly"        System.out.println("Ducks cannot fly");    }}
Enter fullscreen modeExit fullscreen mode

Problema: A classeDuck, está sobrescrevendo o método fly() para imprimir "Ducks cannot fly", assim alteramos o comportamento padrão definido na classe baseBird, que é de que todos os pássaros voam ("Flying"). Isso viola o LSP porque qualquer código que espera um objetoBird ou suas subclasses para voar não funcionará corretamente com um Duck, que a gente já sabe que não voa.

// Classe derivada que respeita o LSPinterface Bird {    void fly();}class Eagle implements Bird {    @Override    public void fly() {        System.out.println("Flying like an Eagle");    }}class Duck implements Bird {    @Override    public void fly() {        throw new UnsupportedOperationException("Ducks cannot fly");    }}
Enter fullscreen modeExit fullscreen mode

Com essa abordagem,Eagle eDuck podem ser permutáveis onde umBird é esperado, sem quebrar as expectativas definidas pela interface Bird. A exceção lançada porDuck comunica explicitamente que patos não voam, sem modificar o comportamento da superclasse de uma maneira que possa causar problemas inesperados no código.

4. Interface Segregation Principle (Princípio da Segregação de Interfaces)

O Princípio da Segregação de Interfaces (ISP) sugere que as interfaces de uma classe devem ser específicas para os clientes que as utilizam. Isso evita interfaces "gordas" que obrigam implementações de métodos não utilizados pelos clientes.

// Exemplo antes de aplicar o ISPinterface Worker {    void work();    void eat();    void sleep();}class Programmer implements Worker {    @Override    public void work() {        // Lógica específica para programar    }    @Override    public void eat() {        // Lógica para comer    }    @Override    public void sleep() {        // Lógica para dormir    }}
Enter fullscreen modeExit fullscreen mode
// Exemplo após aplicar o ISPinterface Worker {    void work();}interface Eater {    void eat();}interface Sleeper {    void sleep();}class Programmer implements Worker, Eater, Sleeper {    @Override    public void work() {        // Lógica específica para programar    }    @Override    public void eat() {        // Lógica para comer    }    @Override    public void sleep() {        // Lógica para dormir    }}
Enter fullscreen modeExit fullscreen mode

No exemplo, dividimos a interfaceWorker em interfaces menores (Work,Eat,Sleep) para garantir que as classes que as implementam tenham apenas os métodos necessários para elas. Isso evita que as classes tenham que implementar métodos que não são relevantes para elas, melhorando a clareza e coesão do código.

5. Dependency Inversion Principle (Princípio da Inversão de Dependências)

O Princípio da Inversão de Dependências (DIP) sugere que módulos de alto nível (como classes de negócio ou de aplicação, que implementam as principais regras de negócio) não devem depender de módulos de baixo nível (classes de infraestrutura, como acesso a dados e serviços externos, que oferecem suporte às operações de alto nível). Ambos devem depender de abstrações.

// Exemplo antes de aplicar o DIPclass BackendDeveloper {    public void writeJava() {        // Lógica para escrever em Java    }}class Project {    private BackendDeveloper developer;    public Project() {        this.developer = new BackendDeveloper();    }    public void implement() {        developer.writeJava();    }}
Enter fullscreen modeExit fullscreen mode
// Exemplo após aplicar o DIPinterface Developer {    void develop();}class BackendDeveloper implements Developer {    @Override    public void develop() {        // Lógica para escrever em Java    }}class Project {    private Developer developer;    public Project(Developer developer) {        this.developer = developer;    }    public void implement() {        developer.develop();    }}
Enter fullscreen modeExit fullscreen mode

A classeProject depende agora de uma abstração (Developer) em vez de uma implementação concreta (BackendDeveloper). Isso permite que diferentes tipos de desenvolvedores (por exemplo,FrontendDeveloper,MobileDeveloper) possam ser facilmente injetados na classeProject sem modificar seu código.

Conclusão

Adotar os princípios SOLID não apenas eleva a qualidade do seu código, mas também fortalece suas habilidades técnicas, aumenta sua eficiência no trabalho e impulsiona sua trajetória profissional como desenvolvedor de software.

Top comments(0)

Subscribe
pic
Create template

Templates let you quickly answer FAQs or store snippets for re-use.

Dismiss

Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment'spermalink.

For further actions, you may consider blocking this person and/orreporting abuse

Women + Tech = 🦋

Inscreva-se na comunidade e fique por dentro de nossos eventos, cursos, mentorias e projetos open source.

More fromWoMakersCode

DEV Community

We're a place where coders share, stay up-to-date and grow their careers.

Log in Create account

[8]ページ先頭

©2009-2025 Movatter.jp