Ir para o conteúdo

GRASP

Introdução

Os principios e padrões GRASP ajudam a entender o essencial de desenho de objetos e aplicar raciocínio de desenho de uma forma metódica, racional, de forma bem explicável. Essa abordagem para o entendimento e uso de princípios de desenho é baseado em padrões de atribuição de responsabilidades (CRAIG, 2004).

Palavras-chave

Vendedor, Comprador, Anúncio

Discussões entre integrantes

Para a elaboração deste documento foi discutido por várias semanas durante o período da entrega. Algumas dessas discussões estão documentadas nas atas de reuniões. Os pontos principais discutidos foram:

  • Os integrantes haviam pensado na criação do serviço API adapter antes mesmo de estudar GRASPs, e viram posteriormente que o padrão se aplicava.
  • Pensamos em como armazenar as fotos de maneira a não deixá-las acopladas às classes que as utilizam (anúncio e usuário), e chegamos a conclusão de que a melhor maneira de fazer isso, seria criando uma model para ela. Dessa forma, teríamos um código mais organizado e manutenível.
  • Os integrantes pensaram em criar views para comprador e vendedor, pois por mais que ambos sejam usuários possuem ações diferentes. Para isso foi preciso estudar o padrão arquitetural MVC e MVT para ver se isso não violaria seus princípios. E também foi conversado com a professora para tirar algumas dessas dúvidas (vide ata dia 22/03)

Padrões

Creator (Criador)

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

Solução: Dê a responsabilidade de criação para B, se uma ou mais das situações abaixo for válida.

  • Se A compõe B
  • Se B salva A
  • Se B usa A de forma próxima
  • Se B possui os dados de inicialização de A

Expert (Especialista)

Problema: Qual é um princípio geral para atribuir responsabilidades para objetos?

Solução: Dê a responsabilidade para B que contém a informação necessária para satisfazer a responsabilidade.

Comentário: No geral, é uma classe especialista em relação a uma classe, pois conhece as informações acerca daquela classe, como também seus métodos, comportamentos e até estados.

Low Coupling (Baixo acoplamento)

Problema: Como suportar baixa dependência, baixo impacto de mudança e aumentar o reúso?

Solução: Atribua responsabilidades para que o acoplamento mantenha-se baixo. Use esse princípio para avaliar as alternativas.

High Cohesion (Alta Coesão)

Problema: Como manter os objetos focados, entendíveis, gerenciáveis e além disso possuir um baixo um baixo acoplamento?

Solução: Atribuir uma responsabilidade de forma a manter a coesão alta.

Indirection (Indireção)

Problema: A quem atribuir a responsabilidade para evitar acoplamento direto entre dois (ou mais) coisas? Como desacoplar objetos para que o baixo acoplamento seja suportado e o reúso se mantenha potencialmente alto?

Solução: Dê a responsabilidade para um objeto intermediário entre os componenetes ou serviços de forma que eles não estejam diretamente acoplados.

Protected Variations (Variações Protegidas)

Problema: Como desenhar objetos, subsistemas e sistemas para que variações ou instabilidades nesses elementos, não tenham um impacto indesejado em outros elementos

Solução: Identifique pontos de variações ou instabilidades previstas, atribua responsabilidades para criar uma interface (no sentido geral) estável em volta destes pontos;

Casos Aplicados

Chat e Mensagem

GRASPs:

  • Criador
  • Especialista

Visto que a relação entre Chat e Mensagem se encaixam em todos os critérios estabelicidos para criador

  • Se Mensagem compõe Chat
  • Se Chat salva Mensagem
  • Se Chat usa Mensagem de forma próxima
  • Se Chat possui os dados de inicialização de Chat

Além do mais, o Chat possui todas as informações que compõem as mensagens, no caso o contéudo e quando ela foi enviada, ele receberá a responsabilidade de não somente criar, mas também salvar e recuperar as mensagens, tornando-o assim num especialista de informações das Mensagens.

Usuário e anúncio

GRASPs:

  • Criador

Visto que a relação entre Usuário e Anúncio se encaixam em alguns dos critérios citados acima, mas principalmente por deter dos dados iniciais e da responsabilidade de salvar o anúncio.

  • Se Anúncio compõe Usuário
  • Se Usuário salva Anúncio
  • Se Usuário usa Anúncio de forma próxima
  • Se Usuário possui os dados de inicialização de Anúncio

Serializers

GRASPs:

  • Especialista
  • Criador (quando aplicável)

As Serializers do padrão django-rest podem ser consideradas especialistas em uma ou mais models dada uma necessidade e um tipo de informação. Além do mais algumas delas são as responsáveis por criar novas instâncias das models e salvá-las na camada de persistência.

PersonSerializer cria Person e User

Visto que há uma especialização de Pessoa (Person) e Usuário (User) é conveniente que o usuário seja iniciado vazio. A classe PersonSerializer, no back-end, tem a responsabilidade de criar tanto a Model Person com os dados de Pessoa e a Model User como especialização. Vale lembrar também que a Model User não possui dados de inicialização além da chave de especialização.

  • Se Person e ser compõe PersonSerializer
  • Se PersonSerializer salva Person e User
  • Se PersonSerializer usa Person e User de forma próxima
  • Se PersonSerializer possui os dados de inicialização de Person e User

Anúncio E Foto

GRASPs:

  • Low-coupling
  • Alta Coesão
  • Variações protegidas

Ter uma model de fotos permite que as fotos sejam desacopladas da model de anúncio e estabelecidas como uma associação. Desse modo o componente Foto pode possuir suas próprias regras de funcionamento.

Suponha uma situação em que você precise trocar o sistema, no caso qual módulo vai servir as fotos, no caso trocar do armazamento de estáticos (imagens e afins) da AWS para um servidor próprio Apache ou Nginx. As regras de upload e obtenção da URL vai permanecer sendo responsabilidade do componente Foto. Desse modo diminui o efeito de mudanças nas regras de Foto.

Api handler (API Adapter) sabe como conversar com a API

GRASPs:

  • Indirection
  • Alta coesão
  • Variações protegidas

É uma indireção pois é um componente para lidar com a conversa entre os componentes do front-end e a API. Isso fornece uma maior coesão, pois os componentes do front-end não precisam implementar a lógica de conversa com a API, mantendo-se apenas nas suas próprias responsabilidades.

Dessa forma é criado o API Adapter que é uma classe que possui uma instância privada do Axios além dos verbos HTTP (biblioteca usada para requisições HTTP em Javascript), essa instância só pode ser acessada dentro da classe protegendo-a de mudanças externas.

Django Views

GRASPs:

  • Polimorfismo
  • Indirection
  • High Cohesion

BuyerView

A ideia é que a View de Buyer (Comprador) seja responsável pelas ações relacionadas ao comprador.

SellerView

A ideia é que a View de Seller (Vendedor) seja responsável pelas ações relacioadas ao vendedor.

Pacotes front-end

GRASPs:

  • Low Coupling
  • High Cohesion

Pacote de services

Esse pacote de services, no Front-end, vai conter serviços comuns que são utilizados por diversos componentes, por exemplo, a API Adapter está na pacote de services e outras funcionalidades podem vir a ser adicionas.

Pacote de utils

Esse pacote de utils, no Front-end, vai conter utilidades comuns que são usadas por vários componentes, por exemplo, parse de datas e horas.

Referências

CRAIG. Larman. "Applying UML and Patterns: An Introduction to Object-Oriented Analysis and Design and Iterative Development". Prentice Hall. Pearson 2005.

Versionamento

Versão Data Modificação Motivo Autor
1.0 04/04/2021 Criação do documento - Todos os integrantes