[Pesquisar este blog]

segunda-feira, 24 de abril de 2017

Os Princípios SOLID::SRP (parte II)

Parte I | Parte II | Parte III | Parte IV | Parte V | Parte VI
Os princípios de projeto e programação propostos em 1995 por Robert C. Martin, tornaram-se conhecidos como SOLID e tem como objetivo orientar a construção de sistemas que no futuro se mostrem mais fáceis de ampliar e manter. Estes princípios constituem um guia para refatorar código e, também, auxiliar nas abordagens ágeis de construção de software.

O acrônimo SOLID é formado por:
  • Single Responsability Principle
  • Open-Closed Principle
  • Liskov`s Substitution Principle
  • Interface Segregation Principle
  • Dependency Inversion Principle
Neste post será abordado o SRP ou princípio da responsabilidade única.

SRP::Single Responsability Principle

Um módulo, classe ou componente de software deve ter uma e apenas uma responsabilidade.
O Single Responsability Principle ou Princípio da Responsabilidade Única ou apenas SRP afirma que cada classe, módulo ou componente de software deve possuir uma, e apenas uma, responsabilidade, o que se traduz como a existência de uma única razão que possa levar a sua mudança.

Isto significa que cada classe deve representar apenas um ator ou entidade de um sistema, devendo ser escrita, modificada e mantida para atender apenas um propósito específico e bem determinado. Um módulo, classe ou componente de software não deve ser um canivete suíço que, por mais que tenha muitas utilidades, nenhuma permite realizar profissionalmente qualquer tipo de serviço.

Na verdade, deveria ser difícil visualizar e entender diferentes responsabilidades em uma mesma classe, mas acaba sendo frequente observar classes que somam mais de uma responsabilidade, criando muitas motivações para sua alteração, o que não é produtivo.
Um sistema composto por classes que atendam ao SRP é, substancialmente, mais simples de se manter, pois somente uma razão específica levará a modificação de cada módulo, classe ou componente. Além disso, propicia flexibilidade para realização de mudanças no futuro sem criar impactos em outras entidades.

Este princípio se traduz diretamente em alta coesão!

No exemplo que segue observa-se uma interface Java denominada IFuncionario que estabelece três operações distintas: calcularSalario(), salvar() e gerarRelatorio(Writer). Também segue uma classe que ilustra a implementação desta interface.

public interface IFuncionario {
    public Salario calcularSalario();
    public void salvar();
    public void gerarRelatorio(Writer w);
}
public class Funcionario implements IFuncionario {

    public Salario calcularSalario() { ... }
    public void salvar() { ... }
    public void gerarRelatorio(Writer w) { ... }
}

Se por uma lado esta interface e sua implementação podem parecer adequadas, não é difícil perceber que a interface IFuncionario define três responsabilidades diferentes, o que é uma clara violação do SRP! A interface IFuncionario indica a necessidade de lógicas voltadas para: (1) cálculo do salário; (2) persistência do objeto; e (3) funcionalidade de autodescrição (produção de relatório). Tudo isso além da própria representação do Funcionario.

Nesta situação é necessário identificar e avaliar funcionalidades para: separar aquelas modificadas por razões diferentes; agrupar aquelas modificadas pelas mesmas razões. Estas ações (provavelmente) darão origem a classes denominadas como *Manager, *Controller, *Handler, *DAO, *Service.

Note que o SRP requer nomes precisos e, principalmente, classes bem focadas (coesas).

No caso, ao dividir as responsabilidades identificadas teremos classes separadas para: o cálculo do salário; a persistência dos objetos; e a geração de relatório.

Conclusões

Deve ser enfatizado que o trabalho decorrente da separação das classes será largamente compensado pelas facilidades em evoluir este design.
Outra consequência do SRP é que se torna um pouco mais simples localizar a duplicação de código, algo que é obviamente ruim, pois ao invés de realizar uma modificação ou correção num único local do código, torna-se necessário localizar todas as cópias para efetuar a alteração desejada.

Para Saber Mais

  • LARMAN, Craig. Utilizando UML e padrões: uma introdução à análise e ao projeto orientados à objetos e ao Processo Unificado. Porto Alegre: Bookman, 2007.
  • MARTIN, R. C.; et. al. Clean Code: a handbook of agile software craftsmanship. Boston: Pearson Education, 2009.
  • MARTIN, R. C. The Clean Coder. Upper Sadle River: Prentice-Hall, 2011.
  • MARTIN, R. C. Principles of OOD. Disponível emhttp://butunclebob.com/ArticleS.UncleBob.PrinciplesOfOod, recuperado em 17/02/2017.
  • MARTIN, R. C. Get a SOLID start. Disponível em http://objectmentor.com, recuperado em 17/02/2017.
  • PAGE-JONES, Meilir. Fundamentos do Desenho Orientado a Objetos. São Paulo: Makron Books, 2001.
  • SOMMERVILLE, I. Software Engineering. 9th. Ed. Boston: Addison-Wesley, 2011.