Ir para o conteúdo

GRASPs e GoFs: WebScraper

Histórico de revisões

Data Versão Descrição Autor(es)
20/05/2019 0.1 Iniciação do documento Joberth Rogers
24/06/2019 0.2 Adição dos padrões GRASP Daniel Maike
26/06/2019 0.3 Adição do padrão Object Pool Daniel Maike
26/06/2019 1.0 Adição do padrão Facade Daniel Maike
26/06/2019 1.1 Melhorando textos Joberth Rogers
26/06/2019 1.2 Correções nos textos Guilherme Guy

Sumario

1. Introdução

2. GOFs utilizados

3. GRASPs utilizados

4. Referências encontradas

1. Introdução

Como apresentado em dinâmicas passadas, o script do Mwscanner foi desenvolvido logo nas primeiras sprints envolvendo código, devido a crucialidade da funcionalidade para o andamento do projeto. O Mwscanner tem por objetivo coletar todos os dados relacionados a vida acadêmica da Universidade de Brasília. Por ser algo urgente e de extrema importância, o grupo se preocupou apenas em criar um script funcional, não se importando com a arquitetura e qualquer tipo de padrão de projeto no início do desenvolvimento, já que o conhecimento ainda não tinha sido adiquirido pelos responsáveis por esta frente do projeto na época da criação da funcionalidade. Nas últimas semanas esses conceitos foram absorvidos e os mais adequados foram abstraídos para o MWscanner. Os padrões levantados foram:

2. Padrões GOF

Os Padrões GOF utilizados no projeto foram:

2.1 Singleton (GOF Criacional)

Esse padrão de projeto que por muitos autores é considerado como anti-pattern, para o script Mwscaner foi um fator crucial para o aumento do desempenho do script. Como o script lida com a coleta e o salvamento dos dados no banco de dados, havia uma diminuição no desempenho logo ao executar o script, devido à criação de uma instância do objeto de conexão com o MongoDB a cada vez que uma nova etapa do Matrícula Web era visitada. Logo foi necessário o uso do padrão de projeto Singleton para cuidar da criação de uma única instância no começo da execução do MWscanner, no qual seria usada por quem necessitasse durante todo o fluxo de execução. Caso alguma das partes necessitasse da conexão com o banco de dados, usará o objeto já instanciado, aumentando assim a performance do programa e evitando a criação de objetos relacionados a conexão com o banco de dados de modo desnecessário, além de não precisar esperar para que a conexão seja feita todas as vezes, apenas reutilizando uma já criada. O código referente ao Singleton está presente abaixo:

singleton-mwscanner

Ao aplicar o padrão tivemos a queda no tempos de execução da build de:

build_gitlab-mwscanner

Para:

build_gitlab-mwscanner

Ou seja, o nível de satisfação do padrão foi ótimo na aplicação do MWScanner, obtendo resultados favoráveis e destruindo o gargalo na hora da conexão do banco. Com a aplicação do padrão Singleton o tempo caiu em média de 50%.

Para verificar os links da build, acesse:
Depois da aplicação do padrão https://gitlab.com/ads-unigrade-2019-1/MWScanner/-/jobs/214912533
Antes da aplicação do padrão https://gitlab.com/ads-unigrade-2019-1/MWScanner/-/jobs/203499362

2.2 Builder (GOF Criacional)

Como abordado na definição, o padrão do tipo builder tem por objetivo tentar encapsular a lógica de construção dos objetos criados, devido a complexidade da criação deles, que em alguns casos podem ser muito alta. Portanto, esse padrão tem como objetivo separar o processo de construção de um objeto de sua representação e permitir sua criação passo-a-passo, a fim de criar objetos de forma simples para a aplicação tornando o código e as estrutura mais agradável e de fácil manutenção.

builderuml

Exemplo de um trecho de código no MWScanner envolvendo Builder:
builderclass-mwscanner

2.3 Object Pool (Criacional, não GOF)

O padrão Object Pool tem o objetivo de reduzir o tempo e custo das instanciações, reaproveitando objetos, melhorar o desempenho e o controle sobre os recursos. Devido grande quantidade de dados que o MWScanner trata é necessário a criação de threads para que diminua o tempo de execução do script. Instanciar um objeto requer tempo de processamento do computador, e para isto as Threads são criadas e reutilizadas, o Thread Pool é um exemplo de Object Pool.

Exemplo de trecho de código no MWScanner envolvendo o Object Pool:
threadpool

2.4 Facade (GOF Estrutural)

O padrão GOF estrutural Facade tem como objetivo prover uma interface simplificada para a utilização de várias interfaces de um subsistema. No MWScanner após a extração dos dados, é necessário que eles sejam salvos em um banco de dados não relacional MongoDB, hospedado no Atlas, nesse processo a main chama a classe SaveDataFacade para que ela possa interagir com as classes responsáveis por salvar cada Collection no banco de dados.

facadeuml

3. Padrões GRASP

General Responsibility Assignment Software Principles – Princípios Gerais do Software de Atribuição de Responsabilidade

Representam os princípios e o racicínio utilizado para atribuir responsabilidades de objetos que podem ser descritos de modo metódico, explicável e repetível.

Os padrões GRASP utilizados no projeto foram:

  • Criador;
  • Especialista;
  • Invenção Pura;
  • Baixo Acoplamento;
  • Alta Coesão;
  • Indireção.

Descritos a seguir:

O padrão GRASP Criador, em que se determina a responsabilidade da criação da instância de um objeto a uma classe, é visualizado nas classes do Builder do MWScanner, elas são responsáveis por criar instancias das classes em que elas possuem os dados, também é visualizado o padrão GRASP Especialista, com a atribuição de responsabilidade de criar instancia de classe nas classes do Builder.

O padrão GRASP Invenção Pura é uma classe que não representa um conceito no domínio do problema, especialmente criado para alcançar baixo acoplamento, alta coesão e o potencial de reutilização. Com isto é visualizado o GRASP Invenção Pura nos Mixins que são classes que não são classes exatamente necessárias no projeto mas que foram criadas para aumentar o potencial de reutilização pelas classes de extração de dados do Matricula Web, com isso, é visto o GRASP Baixo Acoplamento por diminuir o acoplamento com a distribuição de responsabilidades entre as classes e aumento da coesão (GRASP Alta Coesão) e do uso do GRASP Especialista com classes focadas em suas responsabilidades, classes que não realizam grande volume de trabalho.

O padrão GRASP Indireção é a utilização de uma classe intermediária para melhor distribuição das responsabilidades e evitando um acoplamento direto. É possível observar nas classes de salvamento dos dados, cada Collection possui uma classe em que pega os dados extraídos pelo Webscraper e os coloca na forma esperada a ser salva nas Collections do banco de dados MongoDB Atlas, cada classe é responsável por uma Collection e depois a classe saveData salva o que vem de cada classe para o banco de dados. Também possui uma Indireção entre as turmas e as disciplinas, para a classe de salvamento das discplinas não ficar com um grande volume de trabalho, foi criada uma classe para tratar das turmas e já devolver a classe das disciplinas da forma esperada. A Indireção também fortalece a responsabilidade de cada classe, divide as responsabilidades para não deixar grande volume de trabalho para cada classe. Com isto, também fortalece os GRASPS de Alta Coesão, Baixo Acoplamento e o Especialista, esses três colaboram um com o outro dentro do projeto.

4. Referências

  • Slide padrões GOF - disciplina de Arquitetura e Desenho de Software da UnB-Gama - Professora: Milene Serrano