Do que se trata o artigo: Apresentar os conceitos principais do conjunto de princípios de boas práticas de programação chamados de SOLID Principles, relacionando-os a padrões de projeto existentes.
Em que situação o tema é útil: O tema é útil para analista de sistemas e programadores que buscam melhorar a qualidade do software
baseado na metodologia orientada a objetos. A apresentação dos padrões SOLID pode contribuir para uma melhor aprendizagem dos padrões de projeto conhecidos.
Resumo DevMan: Os padrões SOLID são considerados uma boa prática de programação orientada a objetos que visam diminuir o acoplamento entre classes e separar responsabilidades como forma de melhorar o código da aplicação desenvolvida. Neste sentido, este artigo apresentará os padrões que compõem o SOLID.
Em um sistema desenvolvido através do paradigma orientado a objetos, existem diversos padrões e metodologias que devem ser adotadas para que o software produzido seja de fácil manutenção e possibilite sua extensão.
Através dos diversos padrões de software apresentados pelos mais diferentes autores, percebe-se que tratam de soluções de problemas recorrentes no desenvolvimento de sistemas.
Apesar dos padrões serem de fato uma melhoria nos sistemas, muitos analistas e programadores ainda apresentam dificuldades na sua aprendizagem, principalmente em uma primeira abordagem aos padrões de projeto existentes.
Como forma de facilitar este aprendizado, juntamente com a motivação de criar um código melhor, pode-se estudar cinco princípios básicos de design orientados a objetos, chamados de “SOLID”.
Abordados inicialmente por Robert Martin, em um artigo chamado Principles Of Ood, o autor elabora cinco técnicas de programação orientada a objetos onde cada técnica é uma das letras da palavra SOLID. Esses cinco princípios são:
- Single Responsibility Principle: princípio da responsabilidade única;
- Open Closed Principle: princípio do aberto/fechado;
- Liskov Substitution Principle: princípio da substituição de Liskov;
- Interface Segregation Principle: princípio da segregação de Interfaces;
- Dependency Inversion Principle: princípio da inversão de dependência.
Single Responsibility Principle
O princípio da responsabilidade única é focado na discussão entre as classes de um sistema e nas suas responsabilidades. Uma responsabilidade é uma tarefa ou ação que a classe deve realizar, e para que o sistema possa estar de acordo com esse princípio, cada classe deve possuir apenas uma única responsabilidade.
Este é um dos princípios mais fáceis de entender, apresentado através da Listagem 1.
Listagem 1 – Classe que não está de acordo o padrão da responsabilidade única
public class ClienteController { public void save(ClienteVO c) { if (this.validate(c)) { ClienteDAO.getInstance().save(c); this.sendEmail(); } } private boolean validate(ClienteVO c) { if (c.nome.equals("")) return true; } private void sendEmail() { MimeMessage msg = new MimeMessage(session); msg.setFrom(new InternetAddress("email@email.com")); ... Transport.send(msg); } }
Nesse código, tem-se uma fictícia classe ClienteController, onde são criadas algumas funcionalidades relativas a persistência de dados, validação e envio de email.
Apesar do código compilar, a classe ClienteController está desempenhando diversos papéis (responsabilidades) que não são inerentes à ela. Por exemplo, a classe está validando uma informação, persistindo o objeto e enviando email.
Neste contexto, deve-se separar cada funcionalidade em classes, mesmo que a princípio seja gerado acoplamento entre elas. Ou seja, a validação deve ser formada por uma classe cuja única responsabilidade seja validar um campo. Existem diversos tipos de validação, como validar se um campo é nulo ou se um email está escrito corretamente. Seguindo o princípio, cada tipo de validação deve ser uma classe, já que cada validador é uma responsabilidade única. Para exemplificar melhor este processo, observe a Listagem 2.
Listagem 2 – Classe com duas responsabilidades
public class Retangulo extends Figura{ public void area() { } public void desenhar() { } }
No contexto de uma classe que representa um retângulo, a responsabilidade deste retângulo é conter ações inerentes a ele, sendo que a responsabilidade de desenhar (draw) não é relativa à classe retângulo, mesmo porque uma responsabilidade de desenho é muito específica em relação ao ambiente em si.
A quebra desta responsabilidade pode significar diversos problemas de implementação. No exemplo anterior, se houvesse a necessidade de desenhar um retângulo em ambientes diferentes, possivelmente as classes teriam que ser refeitas, ou então o uso de condições seria utilizado para distinguir o ambiente em si.
Outro motivo muito comum de criar uma classe que possui muitas responsabilidades é a forma como o projeto de software é realizado, prezando pela criação de poucas classes no sistema como uma tentativa de diminuir a manutenção no mesmo.
...