GRASP – como atribuir responsabilidades com eficiência, uma introdução
A programação orientada a objetos é, de longe, o paradigma mais utilizado em programação. Com várias décadas de existência, (apesar de muita gente não saber, a OO surgiu com as linguagens SIMULA I (1962-65) e Simula 67 (1967)) evoluiu bastante, porém, é muito comum encontrar projetos com problemas de arquitetura dos mais diversos tipos, entre eles, problemas de coesão, acoplamento desnecessários, generalizações inconsistentes e outras.
O intenção deste artigo é introduzir o conceito de GRASP (General Responsibility Assignment Software Patterns), que, conforme o nome já diz, tem o objetivo de tornar a distribuição de responsabilidade entre as classes uma tarefa mais criteriosa e eficiente, melhorando de forma significativa a qualidade de seu projeto e reduzindo os problemas de arquitetura mais comuns.
A maioria dos programadores aprendeu que em POO devemos mapear objetos reais para objetos em seu modelo de classes. Isto muitas vezes é seguido a risca, mas nem sempre é a melhor maneira de modelar suas classes, pois muitos detalhes cruciais só são visíveis ao se considerar o contexto geral, ou seja, a forma como esses objetos vão interagir e como eles vão colaborar uns com os outros. Os padrões GRASP surgiram exatamente para auxiliar nesta questão.
O GRASP descreve ao todo nove padrões ou princípios, a saber:
- Especialista de informação (Expert)
- Criador (Creator)
- Alta coesão (High coesion)
- Baixo acoplamento (Low coupling)
- Controlador (Controller)
- Polimorfismo (Polymorphism)
- Invenção pura (Pure Fabrication)
- Indireção (Indirection)
- Variação protegida (Protected Variations)
Cada um destes padrões trata de um problema específico, e sugere uma solução de arquitetura para superá-lo. A solução pode utilizar alguns dos consagrados padrões GoF (que poderá ser assunto aqui no AgileZ), portanto é recomendável que o programador ou analista conheça bem soluções como Observer pattern, Proxy, Iterator, Adapter, Strategy, Singleton entre outros.
Antes de começar a descrever cada um dos nove padrões, convém conceituar o que é responsabilidade. Uma responsabilidade pode ser descrita como uma obrigação, seja obrigação de fazer ou conhecer alguma coisa.
Fazer algo:
- a si mesmo
- começar ações em outros objetos
- controlar ações em outros objetos
Conhecer algo:
- informações encapsuladas
- objetos relacionados
- informações que pode calcular
Exemplo: uma classe Memo pode ter obrigação de gerar linhas (faz algo a si mesma), ou pode utilizar uma classe Linha para isso (inicia uma ação em outro objeto) e controlar essas ações mantendo um contador de linhas (informações encapsuladas). Para isso, o Memo deve conhecer a classe Linha (objetos relacionados).
Não devemos, entretanto, confundir métodos/operações com responsabilidades. Um ou vários métodos devem ser utilizados para implementar uma determinada responsabilidade.
I. O padrão Expert (Especialista de informação)
O primeiro padrão que deve ser considerado para resolver o problema de atribuição de responsabilidade é o Expert, que diz que o primeiro candidato a receber a responsabilidade é aquele que possui a informação necessária para executar a tarefa.
O exemplo mais comum é o da venda. Nosso sistema precisa calcular o total de uma venda. Qual classe deve ser responsável por fazer este cálculo?
Sabemos que, para calcular o total de uma venda, precisamos somar os totais de cada item, além do desconto e juros, se houver. Olhando o diagrama, fica fácil observar que a classe Venda é a classe que mantém a lista de itens (dona da informação), portanto ela é a primeira candidata a calcular o total.
Utilizando o padrão Expert, atribuímos à classe Venda a responsabilidade por calcular o total da venda. Como será feito o cálculo internamente? A classe Venda deve iterar pelos itens, somando os valores de cada um e depois subtrair os descontos e somar os acréscimos. Mas, e o valor do item, quem deve calcula-lo? Aplicando novamente o padrão Expert, podemos observar que é o Item quem possui a informação necessária para essa tarefa (quantidade), e o produto é quem possui o preço, logo, as responsabilidades, seguindo o padrão Expert, ficariam assim:
É lógico que este foi um exemplo bem simples, e provavelmente nenhum analista precisaria conhecer o GRASP para chegar ao modelo proposto, mas, ao tratar de relacionamentos e projetos mais complexos, fica bem mais difícil manter um modelo consistente, altamente escalável e flexível, sem conhecer bem esses padrões.
Vamos continuar com os demais padrões GRASP em nossos próximos artigos. Fiquem a vontade para dar sugestões e críticas.
Os princípios GRASP são a base que nos possibilita a criação de uma arquitetura robusta e expansível para os projetos. Texto de fácil entendimento para este conteúdo. Muito bom. Parabéns.
Muito legal a sua explicação, mais vc apenas falou de um tópico o Expert e os outros 8?Criador,Alta coesão,
Baixo acoplamento,
Controlador,
Polimorfismo,
Invenção pura,
Indireção,
Variação protegida.
Valeu Abraços!!
@Ed
Ed, sei que to devendo um monte de padrões, e vou resolver isso em breve.
Abraço.