GRASP

O acrônimo GRASP - General Responsibility Assignment Software Patterns apresentado no livro Applying UML and Patterns: An Introduction to Object-Oriented Analysis and Design and Iterative Development (3rd Edition) do autor Craig Larman explana os princípios fundamentais para atribuição de responsabilidades aos elementos de programação da subetapa de Projeto em modelos UML e CRC Cards, composto por 9 princípios (5 básicos - Capítulo 17 e 4 avançados - Capítulo 25).

Básicos

  • Criador - Creator: atribuição da responsabilidade (fazer) de criação ao elemento de programação.

    Problema: Quem deve ser responsável por criar uma nova instância de algum elemento?

    Solução: Atribua a B a responsabilidade de criar uma instância de A, se:

B contém ou agrega A.

B registra ou guarda instância de A.

B faz uso de A.

B tem dados de inicialização de A.

  • Especialista na Informação - Information Expert (Expert): atribuição da responsabilidade (saber e fazer) ao elemento de programação com a informação.

    Problema: Qual é o princípio fundamental para atribuir responsabilidades aos elementos?

    Solução: Atribua uma responsabilidade para o elemento que tem a informação necessária para cumpri-la.

  • Baixo Acoplamento - Low Coupling: atribuição da responsabilidade de avaliar as dependências entre os elementos de programação.

    Problema: Como auxiliar na redução das dependências, impactos das mudanças e maximização do reuso?

    Solução: Atribua responsabilidades, de modo que o acoplamento (desnecessário) mantenha baixo. Use este princípio para avaliar alternativas.

  • Controlador - Controller: atribuição da responsabilidade de manipular os eventos no sistema e delegar aos elementos de programação, também conhecido por Coordenadora.

    Problema: Qual o primeiro elemento além da camada de apresentação (visão) recebe e coordena (controla) uma operação no sistema?

    Solução: Atribua a responsabilidade para um elemento representando uma das seguintes escolhas:

Representa o sistema geral, um elemento raiz, um dispositivo que o software está em execução ou um subsistema maior (estas são todas variações de um Controlador de Fachada - Facade Controller or Front Controller).

Representa um cenário de caso de uso em que a operação do sistema ocorre (um Controlador de Caso de Uso ou de Sessão - Use Case Controller or Session Controller). Identificações comuns são: <name>Handler, <name>Coordinator ou <name>Session.

  • Alta Coesão - High Cohesion: atribuição da responsabilidade de minimizar as funcionalidades não relacionadas aos elementos de programação.

    Problema: Como manter os elementos focados, compreensíveis, gerenciáveis e por consequência, com baixo acoplamento?

    Solução: Atribua responsabilidades de modo que a coesão mantenha alta. Use este princípio para avaliar alternativas.

    Coesão mede o grau de conectividade entre cada um dos elementos de programação. Quanto maior a coesão do software, mais bem definida e relacionada são as responsabilidades de cada elemento de programação individual da aplicação. Cada elemento de programação tem um conjunto muito específico de ações que executa.

Avançados

  • Polimorfismo - Polymorphism: atribuição da responsabilidade de manipular variações similares no sistema.

    Problema: Como manipular alternativas baseadas em tipo? Como criar componentes de software plugável?

    Solução: Quando alternativas ou comportamentos relacionados variam por tipo, atribua a responsabilidade para o comportamento usando operações polimórficas para os tipos pela qual o comportamento varie.

    Paramétrico: cria um espaço reservado - placeholder para o tipo. Exemplo de recurso: Genéricos - Generics.

    Ad hoc: cria um espaço reservado - placeholder para o tipo, porém com restrição de tipo em tempo de compilação - compile time. Exemplos de recursos: Overload (Estático) / Override (Dinâmico) - Dynamic Dispatch, Late Binding ou Virtual Method Call/Invocation.

    Subtipo: cria um espaço reservado - placeholder para o tipo, porém com restrição de tipo em tempo de execução - runtime. Exemplos de recursos: Herança (Estático) / Composição e Delegação (Dinâmico).

  • Fabricação/Invenção Pura - Pure Fabrication: atribuição da responsabilidade de decomposição representacional e comportamental do domínio.

    Problema: Qual elemento de programação deveria ter a responsabilidade pela funcionalidade, quando não quer violar os princípios de Alta Coesão e Baixo Acoplamento, ou outras metas, mas a solução oferecida pelo princípio de Especialista na Informação não é apropriado?

    Solução: Atribua o conjunto altamente coesivo de responsabilidades para um elemento de programação artificial ou conveniente que não represente um problema no conceito de domínio, alguma coisa feita para suportar a alta coesão, o baixo acoplamento e o reuso.

  • Indireção - Indirection: atribuição da responsabilidade de mediar componentes do sistema.

    Problema: Onde atribuir uma responsabilidade, para evitar acoplamento direto entre duas (ou mais) coisas? Como desacoplar elementos de programação para que o baixo acoplamento é suportado e o potencial reuso mantenha alto?

    Solução: Atribua a responsabilidade para um elemento de programação intermediário para mediar entre outros componentes e serviços de forma que eles não são acoplados diretamente.

  • Variações Protegidas - Protected Variations: atribuição da responsabilidade de proteger os pontos de variação e evolução do sistema. Outros nomes: Encapsulamento - Encapsulation, Ocultamento de Informação - Information Hiding ou Princípio do Aberto-Fechado - Open-Closed Principle.

    Problema: Como projetar elementos de programação, subsistemas e sistemas para que as variações ou instabilidades nesses elementos não tenham impactos indesejáveis sobre outros elementos?

    Solução: Identifique pontos de variação e instabilidade previsível, atribua responsabilidades para criar uma interface estável ao redor.

Core Protected Variations Mechanisms: recursos implementados na própria linguagem e sistemas.

Data-Driven Designs: uso de dados para declaração dos comportamentos do sistema em tempo de execução.

  • Service Lookup: serviço de localização de recursos por nome.

  • Interpreter-Driven Designs: interpretação de código.

  • Reflective or Meta-Level Designs: reflexão e meta programação.

Uniform Access: recurso de propriedade da linguagem.

Standard Languages: linguagens padronizadas utilizadas internamente.

The Liskov Substitution Principle: ver LSP.

results matching ""

    No results matching ""