Baixe o app para aproveitar ainda mais
Prévia do material em texto
Universidade Federal do Rio Grande do Norte Instituto Metrópole Digital Programa de Pós-graduação em Engenharia de Software Mestrado Profissional em Tecnologia da Informação Definição e Detecção de Design Smells em Aplicações de Processamento em Lotes Utilizando Spring Batch Framework Deyvisson Carlos Borges de Melo Natal-RN Agosto de 2020 Deyvisson Carlos Borges de Melo Definição e Detecção de Design Smells em Aplicações de Processamento em Lotes Utilizando Spring Batch Framework Dissertação apresentada ao Programa de Pós- graduação em Tecnologia da Informação da Universidade Federal do Rio Grande do Norte como requisito parcial para a obtenção do grau de Mestre em Tecnologia da Informação. Universidade Federal do Rio Grande do Norte – UFRN Instituto Metrópole Digital – IMD Programa de Pós-Graduação em Engenharia de Software Orientador: Dr. Eiji Adachi Medeiros Barbosa Natal/RN 2020 Melo, Deyvisson Carlos Borges de. Definição e detecção de design smells em aplicações de processamento em lotes utilizando spring batch framework / Deyvisson Carlos Borges de Melo. - 2020. 86f.: il. Dissertação (Mestrado) - Universidade Federal do Rio Grande do Norte, Instituto Metrópole Digital, Mestrado Profissional em Tecnologia da Informação, Natal, 2020. Orientador: Dr. Eiji Adachi Medeiros Barbosa. 1. Aplicações batches - Dissertação. 2. Arquitetura de software - Dissertação. 3. Code smells - Dissertação. 4. Design smells - Dissertação. 5. Processamento em lotes - Dissertação. I. Barbosa, Eiji Adachi Medeiros. II. Título. RN/UF/BCZM CDU 004.4 Universidade Federal do Rio Grande do Norte - UFRN Sistema de Bibliotecas - SISBI Catalogação de Publicação na Fonte. UFRN - Biblioteca Central Zila Mamede Elaborado por Raimundo Muniz de Oliveira - CRB-15/429 Agradecimentos A Deus, por possibilitar minha jornada de constante evolução, provendo fé, capaci- dade, conhecimento e força de vontade. À minha mãe e esposa, por representarem minha fortaleza e alicerce servindo de base psicológica e emocional em minha vida. Ao professor Eiji Adachi, por me ajudar no retorno ao ambiente acadêmico e por sua importante orientação para elaboração desse trabalho. À DATAPREV, por viabilizar minha participação no programa de mestrado profis- sional. Resumo Para atender as constantes mudanças de requisitos e necessidades de novas funcionalidades, os sistemas de software permanecem sempre em um estado de constante evolução. O controle do processo de evolução e manutenção de um software é crucial e uma das fases mais complicadas do desenvolvimento de software. Se esse controle não for gerenciado, os sistemas correm o risco de degradação de importantes atributos de qualidade que consequentemente afetam diretamente o grau de manutenibilidade das aplicações. Fatores como inexperiência, falta de conhecimento e pressões em relação ao tempo de conclusão de tarefas levam a adoção de más práticas de design de software e são a origem dos Design Smells. Para se obter um melhor controle do processo de evolução e manutenção de um software, é importante saber identificar a ocorrência de Design Smells nos projetos, e novos estudos indicam que a utilização de informações específicas do contexto da aplicação, como a natureza dos programas ou papeis arquiteturais utilizados, podem influenciar no processo de detecção e na identificação de problemas que só existem no contexto estudado. Este trabalho realiza um estudo para a definição e identificação de Design Smells específicos ao contexto das aplicações de processamento em lotes, e propõe a definição de um catálogo de 7 Design Smells e a implementação de uma ferramenta para automatizar o processo de detecção. A ferramenta implementada foi utilizada em um estudo de caso em que os códigos de 40 sistemas foram analisados. Nesse estudo, observou-se que os smells específicos ao contexto das aplicações de processamento em lotes afetaram quase 20% das classes e mais que 30% das linhas de código dos sistemas analisados. Também foi possível observar, por meio da aplicação da ferramenta em várias versões de dois sistemas, que o número de smells se manteve constante ao longo das versões, e em alguns casos até cresceu. O que pode evidenciar a falta de conhecimento da existência dos smells e dos impactos negativos que podem incorporar nas aplicações. Palavras-chave: aplicações batches. arquitetura de software. code smells. design smells. processamento em lote. spring batch. Abstract To meet the constant changes of requirements and needs for new features, software systems always remain in a state of constant evolution. The control of the software evolution and maintenance process is crucial and one of the most complicated phases of software development. If this control is not managed, systems are at risk of degradation of important quality attributes, that consequently directly affect the degree of maintainability of applications. Factors such as inexperience, lack of knowledge and pressure in relation to the time to complete tasks lead to the adoption of bad practices of software design and are the origin of Design Smells. In order to obtain a better control of the software evolution and maintenance process, it is important to know how to identify the occurrence of Design Smells in projects, and new studies indicate that the use of information specific to the context of the application, such as the nature of the programs or architectural roles used, can influence the detection process and the identification of problems that only exist in the studied context. This work carries out a study to define and identify Design Smells specific to the context of batch applications, and proposes the definition of a catalog with 7 Design Smells and the implementation of a tool to automate the detection process. The implemented tool was used in a case study in which the codes of 40 systems were analyzed. In this study, it was observed that smells specific to the context of batch processing applications affected almost 20% of the classes and more than 30% of the lines of code of the systems analyzed. It was also possible to observe, through the application of the tool in several versions of two systems, that the number of smells remained constant throughout the versions, and in some cases it even grew. What can evidence the lack of knowledge about the existence of the smells and the negative impacts that they can incorporate in the applications. Keywords: batch applications. software architecture. code smells. design smells. batch processing. spring batch. Lista de ilustrações Figura 1 – Etapas do processo de migração tecnológica do CV3. . . . . . . . . . . 14 Figura 2 – Exemplo básico de uma aplicação de processamento em lotes. . . . . . 19 Figura 3 – Arquitetura de referência para aplicações de processamento em lotes. . 20 Figura 4 – Exemplo de diagrama de sequência UML da execução do processamento em lotes utilizando a arquitetura de referência. . . . . . . . . . . . . . . 22 Figura 5 – Divisão do catálogo de Smells por atributos de qualidade afetado. . . . 29 Figura 6 – Ilustração do Global Processor . . . . . . . . . . . . . . . . . . . . . . . 30 Figura 7 – Estratégia de detecção para Global Processor . . . . . . . . . . . . . . 31 Figura 8 – Estratégia 01 de refatoração para Global Processor . . . . . . . . . . . 32 Figura 9 – Estratégia 02 de refatoração para Global Processor . . . . . . . . . . . 32 Figura 10 – Exemplo de um Item Reader afetado pelo Brain Reader . . . . . . . . 33 Figura 11 – Estratégia de detecção para o Brain Reader . . . . . . . . . . . . . . . 34 Figura 12 – Estratégia de refatoração para o Brain Reader . . . . . . . . . . . . . . 35 Figura 13 – Estratégia de detecção para o Brain Processor . . . . . . . . . . . . . . 36 Figura 14 – Estratégia de refatoração para o Brain Processor . . . . . . . . . . . . 37 Figura 15 – Estratégia de detecção para o Brain Writer . . . . . . . . . . . . . . . 38 Figura 16 – Estratégiade refatoração para o Brain Writer . . . . . . . . . . . . . . 39 Figura 17 – Exemplo de aplicação batch sem ocorrência de consultas na fase de processamento. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40 Figura 18 – Exemplo de aplicação batch com ocorrência de consultas na fase proces- samento. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40 Figura 19 – Estratégia de detecção para o Readaholic Component. . . . . . . . . . . 41 Figura 20 – Impacto causado pelo Amateur Writer com a inclusão de 10.000 requi- sições de escrita. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42 Figura 21 – Estratégia de detecção do Amateur Writer . . . . . . . . . . . . . . . . 43 Figura 22 – Refatoração de um Amateur Writer utilizando a composição de Item Writers. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43 Figura 23 – Step de um processamento em lotes afetado pelo Improper Communication. 44 Figura 24 – Estratégia de detecção para o Smell Improper Communication. . . . . 45 Figura 25 – Refatoração para o Smell Improper Communication do exemplo da figura 23. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45 Figura 26 – Fluxo de execução da ferramenta SBSD . . . . . . . . . . . . . . . . . 49 Figura 27 – Diagrama de classes do componente de métricas da ferramenta SBSD. . 50 Figura 28 – Diagrama de classes do componente de dependências da ferramenta SBSD. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52 Figura 29 – Diagrama de classes do componente de Design Smells da ferramenta SBSD. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52 Figura 30 – Exemplo de representação do diagrama de classes na estrutura de árvore de dependências. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55 Figura 31 – Pseudocódigo para identificar quais serviços foram impactados pelo Global Processor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56 Figura 32 – Pseudocódigo para identificar quais leitores foram impactados pelo Brain Reader . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57 Figura 33 – Pseudocódigo para identificar quais processadores foram impactados pelo Brain Processor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57 Figura 34 – Pseudocódigo para identificar quais escritores foram impactados pelo Brain Writer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58 Figura 35 – Pseudocódigo para identificar quais componentes foram impactados pelo Readaholic Component. . . . . . . . . . . . . . . . . . . . . . . . . 59 Figura 36 – Pseudocódigo para identificar quais componentes foram impactados pelo Amateur Writer . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59 Figura 37 – Pseudocódigo para identificar quais componentes foram impactados pelo Improper Communication. . . . . . . . . . . . . . . . . . . . . . . 60 Figura 38 – Histograma da distribuição do total de linhas de código dos programas utilizados no estudo de caso - Massa inicial. . . . . . . . . . . . . . . . 65 Figura 39 – Boxplot da distribuição do total de linhas de código dos programas utilizados no estudo de caso - Massa inicial. . . . . . . . . . . . . . . . 66 Figura 40 – Histograma da distribuição do total de linhas de código dos programas utilizados no estudo de caso - Massa filtrada. . . . . . . . . . . . . . . 67 Figura 41 – Boxplot da distribuição do total de linhas de código dos programas utilizados no estudo de caso - Massa filtrada. . . . . . . . . . . . . . . 67 Figura 42 – Percentual de classes por papel arquitetural - Cálculo dos limites esta- tísticos. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69 Figura 43 – Percentual de classes por papel arquitetural - Estudo de caso. . . . . . 73 Figura 44 – Resultado estudo de caso - Fase 01 - Método 01. . . . . . . . . . . . . . 74 Figura 45 – Resultado estudo de caso - Fase 01 - Método 02. . . . . . . . . . . . . . 75 Figura 46 – Resultado estudo de caso - Fase 02 - Programa 01. . . . . . . . . . . . 78 Figura 47 – Resultado estudo de caso - Fase 02 - Programa 02. . . . . . . . . . . . 79 Lista de tabelas Tabela 1 – Métricas de software utilizadas para detecção dos Design Smells. . . . 51 Tabela 2 – Conjunto de classes e interfaces associadas aos papeis arquiteturais das aplicações batches. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53 Tabela 3 – Lista de operadores da linguagem SQL utilizados no cálculo da métrica SQLComplexity. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54 Tabela 4 – Visão geral dos sistemas selecionados para validação da ferramenta SBSD. 60 Tabela 5 – Resultado da análise manual de Design Smells. . . . . . . . . . . . . . 61 Tabela 6 – Resultado da análise automática de Design Smells. . . . . . . . . . . . 61 Tabela 7 – Comparação dos resultados das análises manual e automática de Design Smells. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62 Tabela 8 – Número de ocorrências de falsos positivos e falsos negativos. . . . . . . 62 Tabela 9 – Cálculo das métricas Precision, Recall e F-measure. . . . . . . . . . . . 63 Tabela 10 – Massa de dados inicial para o estudo de caso. . . . . . . . . . . . . . . 64 Tabela 11 – Resumo estatístico do total de linhas de código dos programas utilizados no estudo de caso - Massa inicial. . . . . . . . . . . . . . . . . . . . . . 65 Tabela 12 – Massa de dados filtrada para o estudo de caso. . . . . . . . . . . . . . 66 Tabela 13 – Resumo estatístico do total de linhas de código dos programas utilizados no estudo de caso - Massa filtrada. . . . . . . . . . . . . . . . . . . . . 66 Tabela 14 – Bases de dados finais para o cálculo de limites estatísticos e execução do estudo de caso. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68 Tabela 15 – Bases de dados de papéis arquiteturais para cálculo de limites estatísticos. 68 Tabela 16 – Limites estatísticos calculados pelo método de análise de percentis. . . 70 Tabela 17 – Limites estatísticos calculados pelo método de análise de variabilidade. 72 Tabela 18 – Base de dados para execução do estudo de caso. . . . . . . . . . . . . . 73 Tabela 19 – Programas utilizados na segunda fase do estudo de caso - Estudo do comportamento dos smells. . . . . . . . . . . . . . . . . . . . . . . . . 73 Tabela 20 – Resultado do cálculo da métrica Smell Density para os programas analisados no estudo de caso. . . . . . . . . . . . . . . . . . . . . . . . 76 Lista de abreviaturas e siglas AST Abstract Syntax Tree COBOL Common Object Business Model DATAPREV Empresa de Tecnologia e Informações da Previdência FICP Fan-IN Class Processor FIMP Fan-IN Method Processor INSS Instituto Nacional de Seguridade Social JCP Java Community Process JSR Java Specification Reference LCOM Lack Of Cohesion LOC Lines Of Code MVC Model-View-Controller MTV Model-Template-View SBSD Spring Batch Smell Detector SQL Structured Query Language UML Unified Modeling Language WMC Weighted Method Count Sumário 1 INTRODUÇÃO . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 1.1 Contexto . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 1.2 Problema de Pesquisa . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 1.3 Objetivo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 1.4 Metodologia . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 1.5 Estrutura do Documento . . . . . . . . . . . . . . . . . . . . . . . . . 17 2 REFERENCIAL TEÓRICO . . . . . . . . . . . . . . . . . . . . . . . 18 2.1 Aplicações de processamento em lotes . . . . . . . . . . . . . . . . . 18 2.2 Spring Batch framework . . . . . . . . . . . . . . . . . . . . . . . . . . 19 2.3 Especificação JSR-352 . . . . . . . . . . . . . . . . . . . . . . . . . . . 20 2.4 Arquitetura de referência . . . . . . . . . . . . . . . . . . . . . . . . .20 2.4.1 Execução do processamento em lotes . . . . . . . . . . . . . . . . . . . . 22 2.5 Design Smells . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22 2.6 Detecção de Design Smells . . . . . . . . . . . . . . . . . . . . . . . . 24 3 TRABALHOS RELACIONADOS . . . . . . . . . . . . . . . . . . . . 25 3.1 Design Smells . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25 3.2 Detecção de Design Smells . . . . . . . . . . . . . . . . . . . . . . . . 26 4 DESIGN SMELLS EM APLICAÇÕES COM SPRING BATCH FRA- MEWORK . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28 4.1 Catálogo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28 4.1.1 Global Processor (Classe de Processamento Global) . . . . . . . . . . . . . 30 4.1.2 Brain Reader (Leitor Complexo) . . . . . . . . . . . . . . . . . . . . . . . 33 4.1.3 Brain Processor (Processador Complexo) . . . . . . . . . . . . . . . . . . 35 4.1.4 Brain Writer (Escritor Complexo) . . . . . . . . . . . . . . . . . . . . . . 37 4.1.5 Readaholic Component (Leitor Compulsivo) . . . . . . . . . . . . . . . . . 39 4.1.6 Amateur Writer (Escritor Amador) . . . . . . . . . . . . . . . . . . . . . . 41 4.1.7 Improper Communication (Comunicação Indevida) . . . . . . . . . . . . . 44 5 FERRAMENTA DE DETECÇÃO . . . . . . . . . . . . . . . . . . . . 47 5.1 Levantamento do Estado da Prática . . . . . . . . . . . . . . . . . . . 47 5.2 Visão Arquitetural . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49 5.3 Implementação . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53 5.3.1 Módulo de Métricas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53 5.3.1.1 Métrica ArchitectureRole . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53 5.3.1.2 Métrica ReferencedClasses . . . . . . . . . . . . . . . . . . . . . . . . . . . 54 5.3.1.3 Métrica ReferencedMethods . . . . . . . . . . . . . . . . . . . . . . . . . . 54 5.3.1.4 Métrica SQLComplexity . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54 5.3.2 Módulo de Dependências . . . . . . . . . . . . . . . . . . . . . . . . . . . 54 5.3.3 Módulo de Design Smells . . . . . . . . . . . . . . . . . . . . . . . . . . . 56 5.3.3.1 Global Processor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56 5.3.3.2 Brain Reader . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56 5.3.3.3 Brain Processor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57 5.3.3.4 Brain Writer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57 5.3.3.5 Readaholic Component . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58 5.3.3.6 Amateur Writer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59 5.3.3.7 Improper Communication . . . . . . . . . . . . . . . . . . . . . . . . . . . 60 5.4 Validação . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60 5.4.1 Resultados . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61 6 ESTUDO DE CASO . . . . . . . . . . . . . . . . . . . . . . . . . . . 64 6.1 Preparação da Base de Dados . . . . . . . . . . . . . . . . . . . . . . 64 6.2 Cálculo dos Limites Estatísticos . . . . . . . . . . . . . . . . . . . . . 68 6.3 Execução da Ferramenta . . . . . . . . . . . . . . . . . . . . . . . . . 72 6.4 Resultados . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74 6.4.1 Primeira Fase (RQ1, RQ2 e RQ3) . . . . . . . . . . . . . . . . . . . . . . 74 6.4.2 Segunda Fase (RQ4 e RQ5) . . . . . . . . . . . . . . . . . . . . . . . . . 77 7 CONSIDERAÇÕES FINAIS . . . . . . . . . . . . . . . . . . . . . . . 81 7.1 Generalização do Catálogo de Design Smells . . . . . . . . . . . . . . 81 7.2 Principais Contribuições . . . . . . . . . . . . . . . . . . . . . . . . . . 82 7.3 Ameaças à Validade . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82 7.3.1 Ameaças à validade do estudo . . . . . . . . . . . . . . . . . . . . . . . . 82 7.3.2 Ameaças à validade da ferramenta . . . . . . . . . . . . . . . . . . . . . . 83 7.4 Trabalhos Futuros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84 REFERÊNCIAS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85 12 1 Introdução Controlar o processo de manutenção e evolução do software é de extrema importân- cia para definir o grau de qualidade e longevidade de um sistema. Trata-se de uma tarefa complexa em que os problemas são latentes devido à natureza da evolução continua que um software possui. Muitos fatores impactam na qualidade desse processo, tais como: tamanho do código fonte, complexidade, frequência de modificações, documentação, experiência e estabilidade da equipe de desenvolvimento (ALKHARABSHEH et al., 2019). Questões como inexperiência, falta de conhecimento e pressões em relação ao tempo de conclusão de tarefas levam a adoção de más práticas de design, que são a origem dos Design Smells (GARCíA, 2011). Design Smells não produzem erros de compilação ou execução, mas afetam negativamente importantes atributos de qualidade, como compreensibilidade, tes- tabilidade, extensibilidade, reusabilidade e a manutenibilidade (ALKHARABSHEH et al., 2019). São visualizados como pistas de que algo pode estar errado na estrutura do sistema, servindo de alertas, oportunidades de refatoração (BAVOTA et al., 2015) ou indicativos de um aumento da dívida técnica dos projetos (ALKHARABSHEH et al., 2019). A presença de Design Smells pode sinalizar possíveis pontos de degradação. De acordo com Martin (2002), os Design Smells penetram em toda a estrutura do software, e podem ser encontrados quando os sistemas apresentam sintomas de rigidez, fragilidade, imobilidade, viscosidade, complexidade desnecessária, repetição ou opacidade. Devido a essa natureza pervasiva e ao grande número de projetos de software que possuem grandes dimensões, a detecção manual de Design Smells pode se tornar uma tarefa não realista (ALKHARABSHEH et al., 2019). Por esses motivos, muitos estudos estão sugerindo variadas técnicas para automatizar a detecção, sendo uma grande parte baseada em métricas de software. Em 2018, Khalid Alkharabsheh realizou uma revisão sistemática de 395 artigos publicados num período de 17 anos referentes à técnicas de detecção de Design Smells (ALKHARABSHEH et al., 2019). A revisão constatou que 34% dos estudos propuseram abordagens baseadas na medição de métricas de software, como coesão, herança, dependência e acoplamento. Mas apenas extrair métricas dos componentes de software não nos dá uma ideia do contexto geral da aplicação. É necessário ter uma referência para entender se os valores extraídos para uma determinada métrica representam realmente um problema. Para isso, é preciso entender a distribuição das métricas ao longo do sistema e conhecer os fatores que as influenciam. O trabalho de Dósea, Sant’Anna e Silva (2018) verificou que decisões de design podem influenciar na distribuição das métricas, evidenciando a importância de se considerar fatores como o tipo de aplicação, arquitetura utilizada e o papel arquitetural Capítulo 1. Introdução 13 de cada componente analisado. Além de influenciar a distribuição dos valores, cada tipo de aplicação que utiliza determinada arquitetura pode sofrer problemas específicos e apresentar novos tipos de Design Smells ainda não documentados. Outros trabalhos estão aplicando essa abordagem e definindo Design Smells específicos para arquiteturas analisadas, como os trabalhos de Aniche et al. (2018), Correia e Adachi (2019), Carvalho et al. (2019) e Laigner et al. (2019), que definem respectivamente smells específicos para as arquiteturas MVC - Model-View-Controller, MTV - Model-Template-View, Aplicações Android e injeção de dependência em aplicações Java. Desta forma, a definição e identificação de smells específicos para uma determinada arquitetura, aparenta ser uma estratégia efetiva para mitigar problemas relacionados ao contexto específico da aplicação, e por consequência, minimizara degradação arquitetural causada pelas sucessivas ações de atualização e manutenção que o software recebe ao longo de seu tempo de vida. 1.1 Contexto O contexto de estudo desse trabalho é o projeto de migração tecnológica realizado pela DATAPREV, empresa pública que fornece soluções de tecnologia da informação e comunicação para programas de políticas sociais do Estado brasileiro. O projeto “Migração CV3” corresponde a migração de sistemas desenvolvidos em tecnologias legadas para tecnologias mais contemporâneas, e compreende sistemas críticos da empresa, responsáveis principalmente pelo processamento de toda folha de pagamento previdenciária do INSS - Instituto Nacional de Seguridade Social, algo por volta de mais de 54 milhões de registros de benefícios por mês. Os programas foram originalmente desenvolvidos na linguagem de programação COBOL -Commom Object Business Model, para serem executados em Mainframes compa- tíveis com essa tecnologia. Essa arquitetura impôs a empresa uma dependência tecnológica de hardware e mão de obra especializada, pois os Mainframes utilizados contam com apenas um fornecedor e a cada dia a disponibilidade de profissionais especializados na linguagem legada vem decaindo. Grande parte desses programas utilizam o modelo de processamento de informações em lotes e são executados de forma automatizada com o mínimo de intervenção humana. A figura 1 apresenta o diagrama do projeto de migração dos programas legados. Capítulo 1. Introdução 14 Figura 1 – Etapas do processo de migração tecnológica do CV3. Conforme explícito na figura 1, o projeto de migração utilizou uma estratégia de tradução automatizada de código, onde o código legado COBOL foi automaticamente traduzido para código Java utilizando uma ferramenta proprietária de mercado. O resultado de cada tradução foi um programa equivalente escrito na linguagem de programação Java, utilizando o framework de desenvolvimento de programas de processamento em lotes Spring Batch. Após a fase de tradução, foi necessária a realização de ajustes e otimizações no código traduzido, para equiparar os resultados entre as execuções dos programas Cobol e Java, eliminando os defeitos funcionais provenientes do processo de tradução, e melhorar o desempenho das novas aplicações, aplicando refatorações com foco na otimização da execução dos programas. Essa fase de otimização já era esperada devido à natureza da linguagem legada, que utiliza paradigma de desenvolvimento procedural, com programas muitas vezes escritos em grandes blocos de código de um único arquivo, que foram idealizados para serem executados em um hardware específico, não considerando critérios de desempenho necessários para execução em equipamentos mais modernos. Essas características da linguagem legada resultavam na tradução de programas Java com classes muito extensas, complexas e com uma quantidade exagerada de acessos a repositórios de dados, que degradavam o desempenho das aplicações. Nessa última fase de otimização, os desenvolvedores tinham a missão de alterar os programas visando a eliminação de defeitos funcionais e melhorar a qualidade do código migrado com base em critérios de manutenibilidade e desempenho. Porém, não existiam referências de como realizar essa otimização, ou de indicadores de problemas específicos do contexto da programação em lotes. Por esse motivo, a maioria das refatorações foram aplicadas apenas para correção dos defeitos funcionais, desconsiderando particularidades Capítulo 1. Introdução 15 da arquitetura de processamento em lotes que poderiam elevar ainda mais o grau de qualidade dos programas migrados. Portanto, para auxiliar a equipe de desenvolvimento na fase de otimização do projeto, seria interessante a elaboração de uma documentação de referência que defina os impactos, indicadores e técnicas para localização de possíveis problemas relacionados ao contexto das aplicações de processamento em lotes, bem como, a criação de uma ferramenta de análise automatizada para auxiliar na identificação dos pontos onde ocorrem. A ausência de uma documentação de referência e um apoio ferramental pode impedir que se obtenha resultados ainda mais favoráveis nas tarefas de otimização dos sistemas, que sem um processo de refatoração considerando particularidades do contexto das aplicações, dificulta a busca e análise de pontos de melhoria no código das aplicações. Não saber quando determinado componente se mostra muito complexo, de acordo com o papel arquitetural que desempenha, ou está impondo uma complexidade desnecessária aos demais componentes ao qual se relaciona, impede que melhorias sejam aplicadas para diminuir a complexidade do processamento e aumentar o grau de manutenibilidade geral da aplicação. O mesmo ocorre quando não se conhece os fatores que podem estar degradando o desempenho da execução, resultando em buscas mais amplas, custosas, e por vezes sem resultados, para identificação desses pontos de degradação. 1.2 Problema de Pesquisa Aplicações de processamento em lotes, ou aplicações batches, tem sua origem atrelada a própria história da computação. As primeiras aplicações surgiram na década de 50 com o surgimento dos transistores, que deram origem aos computadores de grande porte. São caracterizadas pela manipulação de um grande volume de dados ou de um extensivo e longo processamento computacional. Geralmente são executadas em segundo plano e não necessitam de interação com usuários (VIGNOLA, 2013). Apesar de possuírem uma longa história, as aplicações batches ainda são relevante no contexto da computação atual. Transações bancárias, serviços de envio de e-mails, geração de modelos de recomendação para grandes corporações e orquestração de tarefas em sistemas de Big Data são exemplos de operações executadas através de processamento em lotes (MINELLA, 2019). Como em qualquer outro tipo de arquitetura, os sistemas de processamento em lotes necessitam evitar a degradação estrutural e se manterem no projeto arquitetural pretendido, por esses motivos, é importante conhecer as regras da arquitetura utilizada e saber identificar onde ocorrem violações. A definição de um catálogo de Design Smells, específicos para contexto de aplicações batches, pode ser um grande aliado para garantir a manutenção da arquitetura pretendida. Definir Design Smells específicos ajuda a expor possíveis problemas que só existem no contexto de processamento em lotes, e uma vez Capítulo 1. Introdução 16 conscientes desses problemas, as equipes de desenvolvimento podem atuar e garantir um nível mais elevado de qualidade para as aplicações, evitando a degradação da estrutura proposta para o sistema. Outros tipos de arquitetura já possuem trabalhos semelhantes nos quais propõem a definição de Design Smells específicos, como as arquiteturas MVC (ANICHE et al., 2018), MTV (CORREIA; ADACHI, 2019), aplicações Android (CARVALHO et al., 2019) e injeção de dependência (LAIGNER et al., 2019) em programas Java. Porém, não foram encontrados estudos referentes a definição ou análise de Design Smells específicos para aplicações de processamento em lotes, sendo o principal problema de pesquisa a ser resolvido por essa dissertação. Além disso, é importante garantir a aplicabilidade da análise dos Design Smells que serão definidos, pois devido ao aumento constante das dimensões de tamanho e complexidade das aplicações desenvolvidas atualmente, a detecção manual pode não ser uma tarefa realista, o que torna a implementação de uma ferramenta de detecção automatizada de Design Smells específicos para aplicações batches o segundo problema de pesquisa a ser resolvido pela dissertação. 1.3 Objetivo O objetivo geral deste trabalho é: Definir e apoiar a detecção de Design Smells específicos à arquitetura de sistemas de processamento em lotes. São objetivos específicos deste trabalho: • Elaboração de um catálogo de Design Smells para problemas específicos da arquite- tura de referência. • Implementação de ferramenta de apoio na identificação dos Design Smells definidosno catálogo elaborado. 1.4 Metodologia A metodologia para execução deste trabalho utilizou os seguintes procedimentos: • Revisão da literatura: Com o objetivo de identificar trabalhos relacionados ao estudo de smells referentes ao contexto das aplicações de processamento em lotes, elaborar a definição de estratégias de detecção de violações arquiteturais e a identificar smells tradicionais que possam se adequar ao contexto estudado, foi realizada uma revisão de literatura para servir de base para a construção do catálogo de Design Smells. Capítulo 1. Introdução 17 • Elaboração do catálogo de Design Smells: As violações identificadas referentes ao contexto das aplicações de processamento em lotes foram documentadas por meio de um catálogo de Design Smells. O catálogo apresenta a definição de cada violação, expõe os impactos gerados, define estratégias de detecção e apresenta propostas para refatoração. • Implementação de ferramenta para identificação de Design Smells: Para auxiliar o processo de identificação dos Design Smells, foi desenvolvida uma ferra- menta para análise do código fonte que utiliza as estratégias de detecção definidas no catálogo do item anterior. • Avaliação da ferramenta de identificação de Design Smells: Para validar a utilização da ferramenta de identificação, foi realizado um processo de avaliação, onde foram comparados os resultados da identificação dos Design Smells realizados pela ferramenta, contra os resultados do processo de identificação manual realizado pelo autor dessa dissertação. Foram avaliados critérios de precisão e relevância dos resultados encontrados. • Estudo de caso: Para verificar a aplicabilidade do catálogo proposto, a ferramenta de identificação foi aplicada em um estudo de caso com os programas que participaram do projeto de migração tecnológica da DATAPREV. Esse estudo buscou, além da validação das estratégias de detecção, identificar padrões de comportamento dos Design Smells ao longo do tempo do projeto. 1.5 Estrutura do Documento As seções seguintes desse documento estão estruturadas da seguinte forma: Ca- pítulo 2 - Referencial teórico, contém as principais definições para o entendimento dos assuntos discutidos. Capítulo 3 - Trabalhos relacionados, apresenta os trabalhos publicados relacionados ao tema. Capítulo 4 - Definição do catálogo de Design Smells para aplicações utilizando o Spring Batch framework. Capítulo 5 - Implementação da ferramenta de detecção dos Design Smells definidos no catálogo do capítulo 3. Capítulo 6 - Estudo de caso realizado com os programas da migração tecnológica. Capítulo 7 - Considerações finais, contendo as considerações finais para trabalho, as principais contribuições e as propostas de trabalhos futuros. 18 2 Referencial Teórico Essa seção tem por objetivo apresentar um referencial teórico para os principais conceitos utilizados no estudo dessa dissertação. Serão apresentados: a definição de uma aplicação de processamento em lotes ou aplicação batch, seu histórico e evolução; o framework Spring Batch, desenvolvido para construção de aplicações de processamento em lotes; a especificação JSR-352, que define um modelo de programação para aplicações batches na linguagem de programação JAVA; a arquitetura de referência utilizada pelo framework Spring Batch e a especificação JSR-352 ; e a definição de Design Smells. 2.1 Aplicações de processamento em lotes O conceito de aplicações de processamento em lotes tem origem atrelada a pró- pria história da computação. As primeiras aplicações surgiram na década de 50 com o surgimento dos transistores, que deram origem aos computadores de grande porte. Essas máquinas possuíam altos custos e apenas grandes corporações, agências do governo e universidades dispunham de recursos para aquisição. Devido ao alto valor do equipamento foi necessário buscar uma forma de otimizar o uso, evitando períodos de ociosidade, ocasionados principalmente pela necessidade de intervenção dos usuários para troca de programas a cada execução de uma nova tarefa. A solução adotada foi reunir um lote de tarefas para que fossem processadas sequencialmente. A cada ciclo, um conjunto de tarefas era lido, executado e gravado sem a necessidade de interação com usuários, reduzindo o tempo ocioso de máquina (TANENBAUM; BOS, 2016). Aplicações de processamento em lotes, ou aplicações batches, são caracterizadas pela manipulação de um grande volume de dados ou de um extensivo e longo processamento computacional. Geralmente são executadas em segundo plano e não necessitam de interação com usuários (VIGNOLA, 2013). Atualmente, muitas aplicações corporativas utilizam esse conceito para concretizar operações críticas de negócio, como exemplos: processos complexos que atuam em grandes volumes de dados e são executados de forma mais eficiente sem a interação de usuários; aplicações periódicas de regras de negócio em grandes massas de dados; ou integração de sistemas distintos que necessitam realizar pré-processamentos nas informações trocadas (WARD DAVE SYER; HASSINE, 2019). A figura 2 ilustra um exemplo comum do uso das aplicações de processamento em lotes. Capítulo 2. Referencial Teórico 19 Figura 2 – Exemplo básico de uma aplicação de processamento em lotes. A figura 2 mostra um exemplo básico de uma aplicação de processamento em lotes na integração de sistemas. Os dados do sistema A são extraídos, processados e armazenados em lotes no sistema B sem a necessidade de interação com o usuário. Apesar de importantes e muito utilizadas, é perceptível ao longo dos anos uma falta de foco na criação de uma arquitetura padrão e reutilizável voltada às aplicações batches, tanto em programas legados quanto em aplicações desenvolvidas em linguagens mais contemporâneas como Java. Como consequência, ocorreu uma proliferação de soluções personalizadas desenvolvidas para atender as necessidades de cada instituição (WARD DAVE SYER; HASSINE, 2019). No intuito de contornar esse cenário, alguns projetos de definição de arquiteturas padronizadas e criação de frameworks foram criados para auxilio ao desenvolvimento. As próximas seções descrevem com mais detalhes esses projetos e apresentam a arquitetura de referência adotada por eles. 2.2 Spring Batch framework O Spring Batch é resultado de uma parceria entre as empresas Pivotal (empresa responsável pelo framework Spring) e a Accenture (empresa multinacional de desenvol- vimento de software) para construção de um framework com o objetivo de promover a padronização de abordagens, estruturas e ferramentas de processamento de software que possam ser constantemente aproveitadas pelos usuários corporativos ao criar programas de processamento em lotes. O Spring Batch descreve uma arquitetura de referência elencando papeis e responsabilidades, define uma linguagem de domínio comum para aplicações bat- ches e disponibiliza funcionalidades para atendimento a requisitos não funcionais comuns, como log, backup e processamento paralelo (WARD DAVE SYER; HASSINE, 2019). Capítulo 2. Referencial Teórico 20 2.3 Especificação JSR-352 A JSR-352 é uma requisição de especificação para linguagem JAVA elaborada pelo Java Community Process (JCP), a qual propõe um modelo de programação para aplicações de processamento em lotes. Essa especificação utiliza a mesma arquitetura de referência e linguagem de domínio definidas pelo framework Spring Batch e adicionalmente propõe uma linguagem para configuração do processamento em lotes no formato XML (VIGNOLA, 2013). 2.4 Arquitetura de referência Durante a iniciativa do projeto Spring Batch, a Accenture contribuiu com a de- finição de uma arquitetura padrão de estruturas comumente utilizadas em projetos de processamento em lotes, desenvolvidos pela empresa ao longo de décadas de experiência com variadas gerações de plataformas, COBOL/Mainframe, C++/Unix e Java. A figura 3, retirada da documentação oficial do framework Spring Batch (WARD DAVE SYER; HASSINE, 2019), exibe os principais componentes da arquitetura de referência e seus relacionamentos.Figura 3 – Arquitetura de referência para aplicações de processamento em lotes. O principal elemento da arquitetura é o Job, que serve de contêiner para toda configuração da aplicação batch. O Job é responsável por agrupar as etapas do processo, organizar o fluxo de execução, configurar parâmetros globais e definir se o processo pode ser reinicializado em caso de falhas. O Step é um objeto de domínio que representa uma fase independente do processa- mento. Um Job é composto por um ou mais Steps que são agrupados e organizados de acordo com o fluxo de execução do processo em lotes. Dentro do Step são configuradas as Capítulo 2. Referencial Teórico 21 ações do processo, que geralmente compreendem a leitura de uma fonte de dados, seguida pelo processamento das informações e finalizando com a escrita do conteúdo processado em um repositório de dados. O Item Reader é uma abstração que representa o procedimento de leitura de dados de um Step. O papel representado por esse componente é ler de uma fonte de dados e repassar as informações para o componente de processamento. Esse leitor não está interessado como os dados serão manipulados, outro componente da arquitetura será responsável por transformar esses dados em um formato legível ao processamento da aplicação. Apesar de não estarem explícitos no diagrama da figura 3, osMappers desempenham um papel importante na arquitetura. São eles que transformam as informações extraídas pelos leitores em objetos de domínio que são compreendidos pelo processamento da aplicação. O componente Item Processor é responsável pelo processamento das informações, nesse ponto as regras de negócio devem ser aplicadas. O Item Processor recebe os dados do Item Reader , já convertidos em objetos de domínio pelo Mapper , e os processa um a um. Ao final de cada iteração, é gerado um objeto que será repassado para o armazenamento em um repositório de dados. O Item Writer possui função contrária ao Item Reader . Esse componente é respon- sável pela escrita das informações processadas em um repositório de dados. Diferente do Item Processor , que trabalha com um item por vez, esse escritor trabalha com uma lista de itens que são armazenados a cada ponto de checagem do processamento em lotes. O tamanho dessa lista vai variar de acordo com parâmetro configurado no Step. Para manter as informações de controle de um Job, a arquitetura de referência especifica um banco de metadados chamado Job Repository. Nele são armazenadas infor- mações de execução, como exemplo: data das últimas execuções; situação da execução atual; resultado dos últimos processamentos; número de registros lidos, processados e gravados. Durante toda execução os componentes da arquitetura devem se comunicar com o repositório para armazenar a situação atual do processamento. É através desse mecanismo que a arquitetura permite que um processamento em lotes seja reinicializado do ponto onde parou em caso de falhas. O componente Job Operator é responsável por prover uma interface de gerencia- mento para o Job. Ele disponibiliza funcionalidades para iniciar, pausar ou cancelar uma execução e também métodos de acesso e manipulação do repositório de metadados. Capítulo 2. Referencial Teórico 22 2.4.1 Execução do processamento em lotes A figura 4 exibe o diagrama de sequência UML de uma aplicação de processamento batch utilizando a arquitetura de referência. Todo o procedimento inicia com a execução do Job por meio do Job Operator . O Job irá executar os Steps na ordem em que foram configurados. Cada Step enviará solicitações de leitura para seu respectivo Item Reader , que obterão as informações de uma fonte de dados e delegarão aos Mappers a conversão para um formato legível para aplicação. Com os dados obtidos, o Step requisitará ao Item Processor o processamento e aplicação de regras de negócio, para cada item por vez. Após processado, cada item será armazenado em uma lista de itens processados, onde aguardarão um ponto de checagem da aplicação para serem enviados de uma só vez ao Item Writer , que realizará a escrita em um repositório de dados. Figura 4 – Exemplo de diagrama de sequência UML da execução do processamento em lotes utilizando a arquitetura de referência. 2.5 Design Smells Fowler e Beck (1999) foram os primeiros a utilizar o termo Code Smells, definindo-o como a ocorrência de certas estruturas no código que sugerem a possibilidade de aplicações de refatorações. O foco dos Code Smells é o código fonte das aplicações, que incluem classes, métodos ou blocos menores de instruções. A ideia principal é identificar estruturas de código que indiquem determinados pontos da aplicação que estão sofrendo degradação de atributos importantes de qualidade, como compreensibilidade, extensibilidade e manutenibilidade. Para isso, eles apresentaram um catálogo com 22 tipos de Code Smells que podem identificar a ocorrência desses problemas, indicando como pontos de verificação a presença de trechos Capítulo 2. Referencial Teórico 23 de código repetidos, métodos e classes muito extensas, longa lista de parâmetros e outras estruturas que podem ser vistas em (FOWLER; BECK, 1999). Semelhante aos Code Smells mas com um escopo de atuação mais amplo, existem os Architectural Smells. Que foram definidos por Garcia et al. (2009a) como decisões arquiteturais comumente utilizadas que impactam negativamente a qualidade dos sistemas. Os Architectural Smells não afetam apenas estruturas de mais alto nível, como pacotes e subsistemas, mas também impactam na própria organização e modo de execução, pois podem afetar a forma em que um sistema é organizado, como os componentes se relacionam e como suas funcionalidades são distribuídas. Podem ser incorporados às aplicações ao se utilizar soluções de design em contextos inapropriados, misturar diferentes soluções arquiteturais que podem ser incompatíveis e resultar em comportamentos indesejáveis, ou aplicar abstrações de design em níveis de granularidade equivocados, como uma solução que deveria ser aplicada em uma hierarquia de classes ser aplicada a nível de subsistemas (GARCIA et al., 2009a). Os Code Smells possuem um escopo mais localizado, identificando problemas rela- cionados a aspectos de código, diferente dos Architectural Smells, que possuem um escopo mais amplo com foco em aspectos da arquitetura da aplicação. Já o termo Design Smells definido por Martin (2002) e unificado por García (2011), possui um escopo mais amplo co- brindo todas as estruturas do software, o que vai ao encontro do comportamento pervasivo apresentado pelos Smells, que podem afetar desde de pequenas estruturas de código, como variáveis e blocos de instruções, a artefatos arquiteturais, como pacotes e subsistemas. Design Smells são problemas encontrados na estrutura do software (código ou design), que não produzem erros de compilação ou execução, mas afetam negativamente fatores de qualidade como a compreensibilidade, reusabilidade, testabilidade e a manutenibilidade em geral (GARCíA, 2011). De acordo com Martin (2002), os Design Smells penetram em toda a estrutura do software, e podem ser encontrados quando os sistemas apresentam sintomas de rigidez, fragilidade, imobilidade, viscosidade, complexidade desnecessária, repetição e opacidade. Apesar de estarem diretamente ligados a fatores negativos, os Design Smells não representam diretamente um defeito, mas sua presença serve de alerta para possíveis problemas na estrutura do software, podendo ser considerada o indicativo de uma estrutura fraca de código que contribui para o aumento da dívida técnica (ALKHARABSHEH et al., 2019), e consequentemente sinalizar oportunidades de refatoração do software (BAVOTA et al., 2015). Este trabalho utilizará a definição de Design Smells conforme García (2011), e considerará toda estrutura do software (código ou design) passível de análise. Capítulo 2. Referencial Teórico 24 2.6 Detecção de Design Smells Devido à natureza pervasiva dos Design Smells e ao grande número de projetos de software que possuemgrandes dimensões, a detecção manual pode se tornar uma tarefa não realista (ALKHARABSHEH et al., 2019), por esses motivos, muitos estudos estão sugerindo variadas técnicas para automatizar a detecção. Alkharabsheh et al. (2019) realizaram uma revisão sistemática com 395 artigos publicados num período de 17 anos referentes à técnicas de detecção de Design Smells, e constataram a utilização de estratégias baseadas em regras lógicas, aprendizado de máquina, grafos, análise de especialistas e métricas de software. Uma grande parte dos trabalhos encontrados foram baseados em métricas de software, a revisão constatou que 34% dos estudos propuseram abordagens baseadas na medição de métricas como coesão, herança, dependência e acoplamento. Porções do software que apresentassem métricas com valores destoantes de determinados limites, definidos pelas técnicas utilizadas, eram apontados como possíveis focos de Design Smells. Utilizando essa abordagem, Lanza e Marinescu (2007) propuseram um conjunto de estratégias de detecção baseadas na análise de métricas extraídas dos sistemas analisados. Para cada métrica utilizada, uma análise estatística foi realizada, considerando todo o software, para definir intervalos que seriam considerados valores médios, altos ou muito altos. As estratégias de detecção se basearam nesses limites para identificar pontos que apresentavam um conjunto de métricas com valores dissonantes do restante da aplicação. Dada a utilização de métricas nas estratégias de detecção de Design Smells, o trabalho de Dósea, Sant’Anna e Silva (2018) procurou verificar a influência das decisões de design na distribuição de seus valores, e constatou que os papeis arquiteturais de- sempenhados pelos componentes do software influenciam diretamente nessa distribuição, evidenciando a importância de se considerar fatores como o tipo de aplicação, arquitetura utilizada e o papel arquitetural de cada componente analisado. Seguindo essa linha de raciocínio, outras técnicas para detectar Design Smells sensíveis ao contexto estudado foram propostas, e levam em conta aspectos específicos das aplicações analisadas, como padrão arquitetural escolhido, plataforma de execução ou framework utilizado. 25 3 Trabalhos Relacionados Este capítulo apresenta os principais trabalhos relacionados à definição, estudo e estratégia de detecção de Design Smells que serviram de base para criação do catálogo proposto no capítulo 4. 3.1 Design Smells Na literatura, diversos trabalhos definem os Design Smells por meio de diferentes termos: Code Smells ou Bad Smells (FOWLER; BECK, 1999), Architectural Smells (GARCIA et al., 2009b), antipadrões (BROWN et al., 1998), desarmonias (LANZA; MARINESCU, 2007), falhas de design (SALEHIE; LI; TAHVILDARI, 2006), defeitos de design (MOHA, 2007), anomalias de código (WASYLKOWSKI; ZELLER; LINDIG, 2007) ou débitos de design (ZAZWORKA et al., 2011). Yamashita e Moonen (2013) constataram que 27% dos problemas encontrados na manutenção do software estudado ocorreram devido a presença de Code Smells. Fowler e Beck (1999) foram os primeiros a utilizar o termo Code Smells, eles apresentaram um catálogo com 22 Code Smells referentes a problemas genéricos de design de código que poderiam afetar qualquer tipo de aplicação. Brown et al. (1998) apresentaram uma nova nomenclatura para os smells, denominada Antipatterns ou antipadrões, eles descreveram 41 antipadrões que não apenas abordaram o escopo de código, mas expandiram a análise para a arquitetura do sistema e até o gerenciamento de projetos. Lanza e Marinescu (2007) definiram um catálogo de Design Smells denominados de “desarmonias”, o trabalho afirmava que cada artefato de software deveria estar em harmonia com ele mesmo (tamanho e complexidade), em harmonia com outros artefatos que se relaciona (acoplamento), e em harmonia com seus ancestrais e descendentes (herança). Também foram definidas estratégias de detecção baseadas em análise de métricas de software, e sugestões de refatoração para cada uma das desarmonias. Garcia et al. (2009a) introduziram o conceito de Architectural Smells, demostrando o que possuíam de diferente dos Code Smells e dos Antipatterns, também descreveram a definição de 4 Architectural Smells extraídos por meio da análise de engenharia reversa de 18 projetos de software. Macia et al. (2012) reportaram uma relação entre problemas arquiteturais e a presença de smells, e Fontana et al. (2019) realizaram um estudo para determinar se existia uma correlação entre a presença de Code Smells e Architectural Smells, utilizaram 111 projetos de software para a análise entre 4 tipos de Architectural Smells e 19 tipos de Code Smells, e constataram que não existia correlação significativa entre os dois tipos de smells, direcionando a conclusão que a presença de Code Smells não depende e não está relacionada a presença de Architectural Capítulo 3. Trabalhos Relacionados 26 Smells. Moha (2007) propôs um framework para especificar, detectar e visualizar os Design Smells, também desenvolveu uma linguagem de domínio específico que permite aos usuários a especificação de novos smells (MOHA et al., 2008). E Sobrinho, Lucia e Maia (2018) elaboraram uma revisão de literatura sobre Bad Smells de trabalhos publicados entre os anos de 1990 e 2017, a revisão buscou analisar de forma ampla o ambiente de pesquisa sobre Bad Smells, identificando quais os tipos presentes na literatura, como o interesse sobre o tema tem se comportado com o tempo, os principais objetivos buscados pelas pesquisas, quem são os principais pesquisadores do tema e onde são realizadas as principais pesquisas sobre o assunto. 3.2 Detecção de Design Smells Muitos estudos estão sugerindo variadas técnicas para automatizar a detecção de Design Smells. Alkharabsheh et al. (2019) realizaram uma revisão sistemática com 395 artigos publicados num período de 17 anos referentes à técnicas de detecção de Design Smells, e constataram a utilização de estratégias baseadas em regras lógicas, aprendizado de máquina, grafos, análise de especialistas e métricas de software. Uma grande parte dos trabalhos encontrados foram baseados em métricas de software. Lanza e Marinescu (2007) propuseram um conjunto de estratégias de detecção baseadas na análise de métricas extraídas dos sistemas analisados. E construíram um catálogo de “desarmonias” que identificavam pontos com valores de métricas dissonantes do restante da aplicação. Azadi, Fontana e Taibi (2019) catalogaram 11 Architectural Smells que possuíam estratégias de detecção bem definidas e ferramentas automatizadas de detecção. O catálogo trouxe uma definição de cada Architectural Smell, as variações de nomenclatura que os smells possuíam, os princípios arquiteturais violados, as ferramentas de detecção existentes e as estratégias utilizadas por cada ferramenta. Dada a utilização de métricas nas estratégias de detecção de Design Smells, o trabalho de Dósea, Sant’Anna e Silva (2018) constatou que os papeis arquiteturais de- sempenhados pelos componentes do software influenciam diretamente na distribuição das métricas, evidenciando a importância de se considerar fatores do contexto da aplicação na análise. Seguindo essa linha de raciocínio, alguns trabalhos procuraram definir e detectar Design Smells sensíveis ao contexto estudado. Aniche et al. (2018) definiram 6 smells específicos para aplicações de internet que utilizam o padrão arquitetural MVC e a linguagem de programação Java. A definição se deu por meio de pesquisas e entrevistas com 53 desenvolvedores que utilizavam o padrão há pelo menos um ano. Os smells foram validados utilizando diferentes perspectivas, como a relação com a propensão a alterações e surgimento de falhas, o ciclo de vida de cada Smell, a perspectiva de diferentes desenvolvedores sobre o catálogo e a possibilidade de Capítulo 3. Trabalhos Relacionados 27 generalização para outras linguagens de programação. E constataram que a ocorrência dos smells aumenta as chances de necessidade de alterações e correçõesdos sistemas, que geralmente surgem com a criação dos arquivos e possuem um longo tempo de vida, são percebidos como problemas severos nas aplicações e que o catálogo proposto possui a capacidade de ser aplicado em outras linguagens de programação que utilizem o mesmo padrão arquitetural. Correia e Adachi (2019) se basearam no trabalho de Aniche et al. (2018) para definir um catálogo de 5 Code Smells para aplicações Web utilizando o padrão MTV do framework Django e a linguagem de programação Python. Eles também implementaram uma ferramenta para automatizar a análise e detecção dos smells propostos, e realizaram um estudo de caso em um sistema com mais de 175 mil linhas de código utilizado por mais de 30 instituições de ensino brasileiras. O estudo concluiu que mais de 50% das violações de design encontradas eram ocasionadas por apenas um dos Smell definidos, e semelhante ao trabalho de Aniche et al. (2018), constataram que o número de violações se mantém constante ao longo do ciclo de vida das aplicações. Carvalho et al. (2019) realizaram um estudo envolvendo 246 desenvolvedores para definir um catálogo de smells referentes a violações que afetam a camada de apresentação de aplicações para dispositivos móveis utilizando a plataforma Android. Eles utilizaram um questionário com 25 questões para obter informações dos desenvolvedores sobre os principais problemas encontrados na implementação dessa camada. Com os resultados obtidos foram definidos 20 smells, que foram avaliados pelos desenvolvedores em relação a frequência e importância. Também foi desenvolvida uma ferramenta para automatizar o processo de análise e detecção, que foi aplicada em um estudo de caso envolvendo 619 aplicações que utilizam a plataforma Android. Ao final do estudo, os resultados sugeriram que os desenvolvedores estão cientes da existência de smells específicos à camada de apresentação das aplicações móveis, que os mesmos desenvolvedores consideram que smells propostos possuem grande importância e aparecem com frequência nas aplicações Android, e que as violações realmente acontecem em programas no mundo real, não sendo apenas problemas teóricos. Apesar da importância e ampla utilização das aplicações batches, não foram en- contrados trabalhos referentes a definição ou detecção de Design Smells específicos a esse contexto. 28 4 Design Smells em Aplicações com Spring Batch Framework Este capítulo apresenta um catálogo de Smells aplicado a arquitetura de programas de processamento em lotes utilizando o Spring Batch Framework. Todos os Smells propostos foram idealizados considerando o contexto das aplicações de processamento em lotes e a especificação JSR-352. 4.1 Catálogo A ideia da produção de um catálogo com problemas que afetam especificamente softwares de processamento em lotes surgiu da participação do autor dessa dissertação no projeto de migração tecnológica CV3. O projeto utilizou a estratégia de tradução automa- tizada de código para converter programas legados COBOL em programas modernizados Java por meio de uma ferramenta proprietária de mercado. Após a tradução, uma fase de otimização foi necessária para melhoria do código e correção de defeitos funcionais. Nessa fase, as melhorias que não eram relacionadas a correção de defeitos funcionais tinham o objetivo de melhorar atributos de qualidade com foco apenas em princípios e boas práticas relacionadas a orientação a objetos, como herança, encapsulamento, coesão e acoplamento, sem uma visão relacionada a arquitetura utilizada para processamento em lotes. Como resultado, mesmo com as refatorações realizadas, o processo de manutenção ainda relatava dificuldades referentes a complexidade, e o desempenho das aplicações não alcançava um resultado satisfatório. De face a esse cenário, verificou-se a necessidade de buscar estudos e documentações de referência sobre boas práticas e resoluções de problemas relacionados ao contexto das aplicações de processamento em lotes. O objetivo dessa pesquisa foi encontrar problemas que frequentemente afetam esses tipos de aplicações e quais foram as soluções propostas. Porém, não foram encontrados trabalhos com foco na melhoria do processo de desenvolvimento ou algum catálogo com problemas específicos ao contexto das aplicações batches. Por esse motivo, surgiu a necessidade de elaborar uma documentação que pudesse orientar o processo de migração e manutenção na melhoria do código visando as características da arquitetura utilizada. Para confecção dessa documentação, foi realizado um estudo aprofundado da arquitetura de referência para tentar identificar estruturas que representassem violações dos princípios de design definidos na especificação JSR-352. E baseado no trabalho de Lanza e Marinescu (2007), buscou-se encontrar possíveis formas de desarmonias entre os componentes da arquitetura de referência, bem como, a definição de estratégias de detecção, Capítulo 4. Design Smells em Aplicações com Spring Batch Framework 29 utilizando métricas retiradas das aplicações analisadas, e sugestões de refatoração para cada violação encontrada. O resultado final foi a elaboração de um catálogo com problemas comuns que podem ser encontrados no desenvolvimento de aplicações de processamento em lotes, utilizando a arquitetura referenciada nessa dissertação. O catálogo gerado procurou possuir um aspecto prático, voltado principalmente a questões que realmente impactam o processo de desenvolvimento e manutenção, e não apenas definir os Smells propostos, mas também apresentar estratégias para detecção e refatoração dos problemas apresentados. O catálogo apresentado nesse documento foi baseado no trabalho de Fowler e Beck (1999), que propõe uma lista de indicadores de potenciais problemas de codificação, deno- minados de Bad Smells, para aplicação ao contexto das aplicações de processamento em lotes (Global Processor , Brain Reader , Brain Processor e Brain Writer). Também foram sugeridos novos Smells referentes a problemas específicos na utilização da arquitetura de aplicações batches (Readaholic Component, Amateur Writer e Improper Communication). Para cada definição de Smell, foram definidas estratégias de detecção e de refatoração, semelhantes as definidas no trabalho de Lanza e Marinescu (2007), ao qual propõe estraté- gias de detecção e técnicas de refatoração para desarmonias entre os componentes de uma aplicação. O catálogo pode ser dividido de acordo com os atributos de qualidade afetados pelos Smells propostos: complexidade, desempenho e quebra de papéis arquiteturais. Figura 5 – Divisão do catálogo de Smells por atributos de qualidade afetado. A figura 5 exibe a lista de Design Smells propostos categorizados de acordo com o principal atributo de qualidade afetado. Os Design Smells Global Processor , Brain Reader , Brain Processor e Brain Writer afetam principalmente a complexidade das aplicações; os Smells Readaholic Component e Amateur Writer degradam o desempenho dos programas ao realizarem excessivas operações de leitura e escrita de dados; e o Improper Communication evidencia a quebra de papeis arquiteturais identificando componentes que Capítulo 4. Design Smells em Aplicações com Spring Batch Framework 30 executam processos fora de seus escopos. Durante todo esse trabalho, estaremos utilizando o termo complexidade para indicar fatores que podem prejudicar a compreensão, legibilidade e a manutenibilidade do código fonte das aplicações. Ao se afirmar que um determinado artefato é muito complexo, busca- se dizer que existe uma dificuldade no processo de manutenção de suas funcionalidades. Quando nos referirmos a métrica de software de complexidade, ficará explícito no texto que estamos falando sobre a métrica de complexidade estrutural WMC (Weighted Method Count). 4.1.1 Global Processor (Classe de Processamento Global) Definição: A arquitetura de referência utilizada pelo Spring Batch (WARD DAVE SYER; HASSINE, 2019) define a entidade Item Processor como responsável pelo processamento dos dados coletados pela aplicaçãobatch. Toda inteligência de negócio necessária para o processamento de um Step deve ser implementada em um Item Processor . Porém, é comum a utilização de classes de serviços para implementação de funcionalidades que podem ser compartilhadas com outros Steps. Idealmente, essas classes devem conter apenas funcionalidades compartilhadas e que sejam referentes a um determinado contexto de negócio, para que possam se manter coesas. Uma classe que apresenta o comportamento de Global Processor possui alto acoplamento, por prover muitas funcionalidades a múltiplos Item Processors, e baixa coesão, por conter funcionalidades que não se relacionam com o propósito da classe, basicamente acumula lógica de processamento de vários Steps. A figura 6 exibe o diagrama de classes UML típico de classes afetadas pelo Global Processor . Figura 6 – Ilustração do Global Processor Conforme visto na figura 6, é possível observar que a classe Service possui relacio- namento com mais de um Item Processor e acumula várias funcionalidades, que em sua Capítulo 4. Design Smells em Aplicações com Spring Batch Framework 31 maioria são utilizadas por apenas um Item Processor . Referente ao contexto do processa- mento em lotes, a classe Service não apresenta um grau satisfatório de coesão, pois está armazenando a lógica de processamento de vários Steps, que são unidades independentes de processamento. Impacto: O fato da classe afetada acumular funcionalidades de processamento de vários Steps, que por definição da arquitetura são etapas independentes, contribui para piorar o grau de coesão da classe. Além do fato de que vários Item Processors necessitarão referenciar a mesma classe, o que levará ao aumento do grau de acoplamento. Estratégia de detecção: A detecção de um Global Processor é baseado em duas características: 1. A classe afetada é uma classe que desempenha papel de provedora de serviços sendo referenciada por mais de um Item Processor ; 2. A classe afetada apresenta mais de um terço de seus métodos não sendo comparti- lhados, acessados por apenas um Item Processor . A primeira etapa para detecção de um Global Processor é encontrar classes que desempenham papel de classes de serviço e se relacionam com mais de um Item Processor . Para isso foi utilizada uma variação da métrica Fan-In (LORENZ; KIDD, 1994), que contabiliza o número de classes que acessam um determinado método, para contabilizar o número de Item Processors que acessam os métodos da classe analisada (FICP - Fan-IN Class Processor). Caso uma classe seja referenciada por mais de um Item Processor , outra variação da métrica Fan-In, que contabiliza apenas chamadas efetuadas por Item Processors (FIMP - Fan-In Method Processor), é calculada para cada método da classe. Se mais que um terço dos métodos forem referenciados por apenas um Item Processor então a classe analisada pode estar sendo afetada pelo Global Processor . A valor de 1/3 dos métodos foi escolhido para desconsiderar classes que possuem poucos métodos afetados pelo Global Processor , pois apesar de possivelmente representar um problema, o número reduzido de ocorrências não afeta negativamente a legibilidade e a manutenibilidade do código. A figura 7 exibe o processo lógico para identificação do Global Processor . Figura 7 – Estratégia de detecção para Global Processor Capítulo 4. Design Smells em Aplicações com Spring Batch Framework 32 Refatoração: Duas propostas de refatoração foram elaboradas para correção do Global Processor . A primeira proposta é mover os métodos que possuem único acesso para os Item Processors correspondentes, deixando apenas os métodos compartilhados na classe de serviço, conforme visto na figura 8. A segunda proposta pode ser utilizada caso seja necessário manter os métodos de acesso único separados dos Item Processors correspondentes, por motivos de coesão ou separação de contexto. Deve-se criar uma classe Service com os métodos de acesso único para cada Item Processor correspondente, mantendo os métodos compartilhados em uma classe de serviço separada, esse processo é exibido na figura 9. Figura 8 – Estratégia 01 de refatoração para Global Processor Figura 9 – Estratégia 02 de refatoração para Global Processor É importante observar que as propostas de refatoração para o Global Processor podem adicionar outros pontos de complexidade no projeto, seja pela introdução de novos métodos nos Item Processors pela estratégia da figura 8, ou na inclusão de novas classes de serviços realizada pela estratégia da figura 9. Capítulo 4. Design Smells em Aplicações com Spring Batch Framework 33 4.1.2 Brain Reader (Leitor Complexo) Definição: Classes Item Readers desempenham o papel de leitores de dados, sendo responsáveis pela aquisição das informações do processamento. Esses componentes concen- tram a lógica para leitura de dados, que idealmente deve ser simples e não possuir lógica de negócio associada, pois o processamento das informações coletadas deve ser responsa- bilidade dos Item Processors. Um Item Reader afetado pelo Brain Reader apresenta um elevado grau de complexidade estrutural devido a utilização de muitos fluxos condicionais, ou apresenta instruções de consultas a repositórios de dados com muitos operadores SQL. Figura 10 – Exemplo de um Item Reader afetado pelo Brain Reader A figura 10 exemplifica a ocorrência do Brain Reader . Fica evidente, com a presença dos múltiplos fluxos condicionais, que a classe pode gerar diferentes versões da instrução de leitura, tornando-se mais complexa e aumentado a complexidade dos componentes que realizarão o processamento das informações, que devem estar prontos para processar os dados obtidos por todas as versões possíveis da instrução de leitura. Impacto: A presença de lógica com muitos fluxos condicionais, para geração de consultas dinâmicas, ou mesmo consultas SQL que utilizam muitos operadores podem aumentar o grau de complexidade estrutural e prejudicar a manutenibilidade do código. Estratégia de detecção: A estratégia de detecção de um Brain Reader se baseia na estratégia para detecção da desarmonia de identidade Brain Method desenvolvida por Lanza e Marinescu (2007), e basicamente verifica o tamanho e a complexidade estrutural de um Item Reader . Como os Item Readers também podem realizar leitura de fontes de dados utilizando o padrão de linguagem de consulta SQL, a definição do Brain Method é estendida nesse trabalho levando-se em consideração também a medida da complexidade das instruções SQL. A figura 11 exibe a estratégia de detecção para um Brain Reader . Capítulo 4. Design Smells em Aplicações com Spring Batch Framework 34 Figura 11 – Estratégia de detecção para o Brain Reader 1. Classe extensa: Classes longas tendem a serem mais complexas e de difícil ma- nutenção. A medição do tamanho da classe de leitura será realizada por meio da métrica número de linhas de código (LOC - Lines of Code). 2. Complexidade estrutural da classe é alta: A presença de estruturas de fluxo condicional pode sugerir a utilização de consultas dinâmicas que serão geradas de acordo com regras de negócio. Incluir consultas dinâmicas pode prejudicar a manutenção de todo o processamento em lotes, pois a cada execução, um conjunto de dados diferente pode estar sendo processado, e consequentemente mais estruturas condicionais serão exigidas para atender os diferentes conjuntos de dados, aumentando a complexidade de toda a aplicação batch. Para calcular a complexidade estrutural será utilizada a soma estatística da complexidade ciclomática de todos os métodos da classe (WMC - Weighted Method Count). 3. Possui métodos com estruturas de aninhamento profundo: Semelhante a observação do item anterior, ocorrência de estruturas de controle de fluxo com um aninhamento elevado evidenciam a aplicação de lógica complexa no processo de leitura, diminuindo o grau de legibilidade e manutenção do código. Para medir o grau de aninhamento será utilizada a métrica MAX NESTING. 4. Métodos utilizam muitos operadores SQL: A ocorrência deinstruções SQL complexas pode sugerir a transferência de regras de negócio do código da aplicação para a consulta. Em alguns casos, a correspondência entre as instruções de código Java e SQL não é direta e intuitiva, acabando por adicionar uma carga de complexidade maior comparada com a versão correspondente em código Java. Para calcular o grau Capítulo 4. Design Smells em Aplicações com Spring Batch Framework 35 de complexidade das instruções de consulta, será computado o total de operadores SQL utilizados. Refatoração: Duas estratégias de refatoração são sugeridas. A primeira consiste na criação de um novo Step para cada versão da instrução de consulta gerada. A segunda, transferir a complexidade estrutural de criação da consulta para filtros de verificação nos Item Processors. A primeira estratégia, vista na figura 12, é mais interessante, pois irá gerar Steps com leitores mais simples sem a necessidade de transferir a complexidade estrutural para os Item Processors. Figura 12 – Estratégia de refatoração para o Brain Reader Apesar de gerar classes mais simples, a estratégia de refatoração da figura 12 eleva a complexidade do projeto, pois adiciona novos fluxos de processamento e cria novas classes. 4.1.3 Brain Processor (Processador Complexo) Definição: Os Item Processors concentram toda a lógica de processamento das aplicações batches, e toda inteligência de negócio aplicada aos dados deve ser implementada nesses componentes. Apesar de figurarem como um centro de inteligência da aplicação, essas classes devem manter o controle da complexidade balanceado, evitando centralizar muita inteligência de negócio e obter muita responsabilidade. Um Item Processor afetado pelo Brain Processor se apresenta como uma classe extensa, com baixa coesão ou complexidade estrutural alta. Impacto: O tamanho extenso e a presença de métodos complexos prejudicam a compreensão do código implementado, somando-se o acúmulo de responsabilidades que degradam a coesão e consequentemente o grau de manutenibilidade da classe. Capítulo 4. Design Smells em Aplicações com Spring Batch Framework 36 Estratégia de detecção: A estratégia de detecção do Brain Processor toma por base a desarmonia de identidade Brain Class proposta por Lanza e Marinescu (2007) e o Bad Smell Large Class proposto por Fowler e Beck (1999). A ideia principal é encontrar classes que destoam das demais em relação ao tamanho, complexidade estrutural e coesão. A figura 13 exibe a estratégia de detecção de um Brain Processor . Figura 13 – Estratégia de detecção para o Brain Processor 1. Classes excessivamente longas: Semelhante ao Brain Reader , a métrica utilizada para calcular o tamanho de uma classe será o número de linhas de código (LOC - Lines of Code). 2. Complexidade estrutural alta: Para calcular a complexidade estrutural de um Item Processor será utilizada a soma das complexidades ciclomáticas dos métodos (WMC - Weighted Method Count). 3. Estruturas com aninhamento profundo: O grau de aninhamento das estruturas de controle será dado pela métrica MAX NESTING, selecionando as classes que possuírem pelo menos um método com aninhamento maior que a média calculada para os Item Processors da aplicação. 4. Classes com baixa coesão: Classes coesas possuem membros com uma relação forte, o que facilita a manutenção, pois fica evidente qual funcionalidade está sendo entregue com maioria dos seus componentes trabalhando em conjunto para entrega dessa funcionalidade. Esse comportamento auxilia na compreensão do código e permite um grau de reusabilidade mais elevado. Classes com baixa coesão são difíceis de entender e reutilizar, porque muitas funcionalidades são oferecidas e não existe uma forte relação entre seus componentes. Para medir o grau de coesão de uma classe Capítulo 4. Design Smells em Aplicações com Spring Batch Framework 37 será utilizada a métrica LCOM (Lack Of Cohesion), que calcula o número relativo de pares de métodos que acessam ao menos um atributo em comum da classe. Refatoração: A estratégia de refatoração para um Brain Processor consiste na de- composição de responsabilidade. A primeira ação será verificar se o Step com processamento complexo pode ser decomposto em Steps mais simples, simplificando o processamento individual. Caso não seja possível a decomposição dos Steps, a arquitetura do Spring Batch disponibiliza um mecanismo de composição de Item Processors, onde o Item Processor principal será uma composição de Item Processors mais simples que serão executados em uma ordem pré-determinada. Esse mecanismo permite distribuir a complexidade do componente inicial para componentes mais simples e coesos. A figura 14 exibe um diagrama de classes com a aplicação dessa refatoração. Deve-se observar que essa estratégia simplifica as classes de processamento, mas adiciona mais complexidade ao processo com o aumento do número de classes. Figura 14 – Estratégia de refatoração para o Brain Processor 4.1.4 Brain Writer (Escritor Complexo) Definição: Os Item Writers são responsáveis pela persistência das informações processadas. O conteúdo recebido por um Item Writer deve estar processado para que apenas o armazenamento em um repositório de dados seja necessário. Um Item Writer afetado pelo Brain Writer se apresenta como uma classe extensa, com complexidade estrutural elevada ou instruções de manipulação de repositório de dados extensas e complexas. Impacto: Assim como nos Smells anteriores a complexidade é o principal agravante em um Brain Writer . Métodos de escrita ou instruções de armazenamento longas e complexas afetam diretamente o grau de dificuldade de manutenção da aplicação. Capítulo 4. Design Smells em Aplicações com Spring Batch Framework 38 Estratégia de detecção: Semelhante ao Brain Reader , a estratégia de detecção utilizada será baseada na extensão e complexidade estrutural da classe e das instruções de armazenamento de dados SQL. A estratégia para detecção do Brain Writer pode ser vista na figura 15. Figura 15 – Estratégia de detecção para o Brain Writer 1. Classes extensas: A medição do tamanho das classes será realizada por meio da métrica número de linhas de código (LOC - Lines of Code). 2. Complexidade estrutural da classe é alta: Para o cálculo da complexidade estrutural dos métodos será utilizada a soma das complexidades ciclomáticas (WMC - Weighted Method Count). 3. Classe possui métodos com estruturas muito aninhadas: O grau de aninha- mento será adquirido pela métrica MAX NESTING. 4. Métodos utilizam muitos operadores SQL: Para calcular o grau de complexi- dade das instruções de armazenamento, será computado o total de operadores SQL utilizados. Refatoração: A refatoração de um Brain Writer deve ser iniciada verificando-se o principal fator responsável pelo aumento da complexidade. Caso seja observada a existência de lógica de negócio entre as instruções de armazenamento, será necessário a transferência dessa lógica para os Item Processors, que são os reais responsáveis pelo processamento das informações. Ou, se o método de armazenamento realiza a escrita dos dados em mais de uma fonte de dados ou tabela de banco de dados, o Spring Batch disponibiliza um mecanismo de composição de Item Writers, que semelhante aos Item Processors permite Capítulo 4. Design Smells em Aplicações com Spring Batch Framework 39 compor escritores para que sejam executados em uma ordem pré-determinada, distribuindo a complexidade estrutural da classe original em classes menores, com índices mais baixos de complexidade estrutural e mais coesas, conforme observado no diagrama da figura 16. Figura 16 – Estratégia de refatoração para o Brain Writer Semelhante a proposta de refatoração do Brain Processor , a refatoração do Brain Writer pode elevar o grau de complexidade do projeto com a adição de novas classes de escrita. Ou aumentar a complexidade estrutural de seu Item Processor correspondente, ao se transferir a lógica de negócio, podendo em casos mais extremos induzir a criação de um Brain Processor . 4.1.5
Compartilhar