Arquitetura e Qualidade

Diversas metas técnicas da arquitetura do framework foram discutidas em Metas e Princípios de Arquitetura, tais como alto desempenho e integridade, mas algumas metas que dizem respeito à qualidade da aplicação também são determinantes para o design do framework e das aplicações baseadas no mesmo.

Da mesma forma que os requisitos técnicos de arquitetura, necessidades de negócio do cliente também geram requisitos de qualidade, que muitas vezes passam despercebidos por influenciarem mais fortemente o desenvolvimento do que a própria aplicação em produção.

  1. Verificabilidade - devido à criticidade e a importância da corretude das informações providas na solução, que tipicamente envolve inúmeras regras de negócio, é vital que todas as regras de negócio sejam facilmente verificáveis. Sem essa verificabilidade a confiança do cliente na aplicação fica comprometida, o que tornará o processo de homologação e troca de versão extremamente oneroso.
  2. Extensibilidade - são poucos os casos em existe um conjunto de requisitos definido e estável, em geral o negócio realizado pelo cliente evolui na medida em que novas oportunidades vão surgindo, e o sistema que dá à operecionalização do negócio deve ser capaz de acompanhá-lo. Um sistema que não é capaz de ser extendido para agregar novas funcionalidades não permitirá que o cliente aproveite novas oportunidades, que poderão até mesmo ser perdidas, gerando prejuízo e descontentamento.
  3. Modularidade - grandes aplicações monolíticas são de difícil manutenção, devido à complexidade crescente e replicação de código. O uso de modularização propicia o reaproveitamento saudável de código e a segregação do sistema em partes menores, mais simples e fáceis de desenvolver e manter.
  4. Manutebilidade - a solução deve ser de fácil manutenção, permitindo a identificação rápida de problemas e implementação ágil de correções.

Verificabilidade

A arquitetura foi construída com verificabilidade em mente, permitindo testes completos da aplicação de maneira eficiente e eficaz.

A pode ser empacotada na forma de uma aplicação standalone, que funciona fora de um container JEE, com uma base de dados embarcada e com toda a camada de comunicação web substituída por uma interface adequada a testes das camadas de tecnologia, negócios e mensageria. Esse uso alternativo é possível pois a interface com dependências externas é totalmente mediada pela camada tecnológica, que faz isso de forma a permitir o funcionamento isolado, ou com versões alternativas embarcadas, como o banco de dados H2.

../_images/verificabilidade.png

O diagrama acima representa os empacotamentos alternativos da aplicação, em versão standalone. A versão “Test Runner” toda a camada de Negócio em uma aplicação desktop que consegue executar cenários de testes de aceitação, descritos em linguagem específica de domínio em planilhas pelos próprios analistas de negócio que atuam no desenvolvimento. No início de cada execução a base de dados é reiniciada, e ao final é verificado sucesso ou, no caso de falha, emitido um relatório detalhado de erros.

Também há um empacotamento na forma de aplicação command line, que permite que os cenários de testes de aceitação sejam executados em um servidor de Integração Contínua dedicado no ambiente de desenvolvimento. Os testes podem então ser realizados automaticamente de forma não supervisionada, e relatórios de integridade da aplicação são emitidos diversas vezes por dia, a cada alteração no servidor de controle de versões, com verificação de todos os testes de aceitação já escritos.

Desta forma, a arquitetura contribui de forma decisiva para a verificabilidade das camadas de negócio, tecnologia e mensageria, que correspondem a grande parte da lógica de negócio a ser testada.

Além dos testes de aceitação, a arquitetura permite testes unitários e de integração, que também são utilizados intensamente. Testes de integração são realizados para verificação das camadas Web UI e Web Services. Além destes testes é recomendável complementar sua bateria de testes automatizados com ambiente de deploy contínuo e testes de interface com ferramentas como Selenium.

Quanto a verificações manuais, a grande difusão de rastreabilidade é de grande ajuda, pois é possível verificar o caminho que um processo de negócio percorreu ao longo de diversos módulos da aplicação para validação.

Extensibilidade

A arquitetura da solução contribui para a extensibilidade, podendo ser destacados 3 pontos principais:

  1. Design Patterns - os módulos são construídos sobre uma base tecnológica única construída para ser extensível. É amplamente utilizada a definição de interfaces e registro de implementações, por exemplo para a adição de listeners de eventos, adição de validações e controles extras. O uso de padrões próprios tornam a aplicação facilmente extensível.
  2. Metadados - o uso de scripts e outros metadados para implementação de requisitos muito voláteis permite que diversos pontos de comportamento da solução sejam alterados sem downtime.
  3. Testes automatizados - a própria verificabilidade contribui enormemente par a extensibilidade da solução, pois encurta o ciclo de desenvolvimento. O desenvolvimento de novos requisitos pode ser feito sem receio de quebras significativas em requisitos desenvolvidos anteriormente, pois testes de aceitação automatizados irão detectar rapidamente regressões para que possam ser corrigidas.

Modularidade

O framework disponibiliza diversos módulos facilmente importáveis que provêem diversas funcionalidades, como processamento de arquivos, serviços, execução paralela e distribuída de jobs, etc. A mesma estrutura que permite a criação desses módulos também permite que a própria solução seja dividida em diversos módulos isolados, tornando o desenvolvimento mais simples e fácil de ser testado.

Manutebilidade

A verificabilidade e modularidade colaboram enormemente para facilitar a manutenção da solução, pois a equipe responsável pode ter confiança na correção de erros devido a cenários automatizados que confirmam a sua eficácia e a não regressão do que já estava desenvolvido.

O diagnóstico de um problema precisa, claro, de informações precisas sobre a ocorrência. Por este motivo faz parte dos módulos básicos do Jmine o jmine-tec-log, que registra de forma organizada diversos dados sobre o estado do sistema no momento de erros. Também há suporte à exposição via JMX de dados da aplicação relevantes para monitoramento em ferramentas especializadas como Zabbix. Todas essas informações, em conjunto com o log da aplicação via log4j, geram uma boa quantidade de informações que são de grande valia na resolução de problemas.

Recomenda-se também o uso de boas práticas de programação. A prática de Test Driven Development (TDD), por exemplo, possui grande influência no design do código, que tende a ser escrito de forma menos acoplada e de manutenção mais fácil, além da confiança dada pelos próprios testes unitários desenvolvidos.