Mostrando postagens com marcador teste. Mostrar todas as postagens
Mostrando postagens com marcador teste. Mostrar todas as postagens

quarta-feira, 29 de agosto de 2012

Avaliando a Qualidade de Software

Recentemente participei de algumas consultorias internas na Dextra e externas em clientes com o objetivo de validar arquiteturas e designs de software, tentando apoiar as equipes de desenvolvimento na evolução dos sistemas que estão sendo desenvolvidos. Este, no entanto, não é um trabalho que pode ser realizado sem que alguns conceitos sejam devidamente esclarecidos. Sempre que julgamos alguma coisa levamos em consideração, obviamente, sensações e sentimentos que não controlamos. Por isso precisamos entender este fenômeno humano tentando compreender quais são os conceitos mais essenciais que estão por trás daquilo que molda a nossa percepção à cerca do que estamos analisando. Esta percepção, após alguma reflexão, é o que quero relatar neste post.

Antes de continuar, vamos esclarecer algumas coisas:

Arquitetura = Design = Código-fonte

Como Guilherme Silveira esclarece em How to stop writing next years unsustainable piece of code, a arquitetura e o design de um sistema computacional só existem através de seu código-fonte. Ou seja, o código é a única fonte confiável para a análise da qualidade de um software.

Documentação
A documentação é um instrumento de comunicação que, a meu ver, é muito pouco eficiente (e, em geral, é pouco utilizado efetivamente por desenvolvedores e demais envolvidos no desenvolvimento). Por isso, nunca considerei a documentação do software na análise de sua qualidade. E assim como a arquitetura e o design a documentação não faz sentido se o código-fonte não implementar o que nela está escrito. Portanto, a fonte primária continua sendo o código-fonte.

O que é um bom software?

Ainda antes de identificarmos quais fatores precisamos analisar para avaliarmos um sistema computacional, é preciso alinhar o conceito de "bom software". Colocando sob a perspectiva do cliente, um "bom software" é aquele que evolui de forma rápida e segura, potencializando o ROI (Return Of Investment), ou seja, o retorno do investimento realizado em seu desenvolvimento. Vale ressaltar que o cliente nunca está preocupado com qualidade. Normalmente a qualidade é um item delegado para a equipe de desenvolvimento. Isto não significa que o cliente não queira um "bom software", mas apenas que ele não se preocupa com os detalhes que permitem a criação de um "bom software".

Existem alguns casos em que um "bom software" para o cliente não requer boas práticas de engenharia de software e, nestes casos, avaliar seu código-fonte não será efetivo. Por exemplo, o código-fonte de um software de uma campanha de marketing que durará duas semanas. Apesar de conhecer este exemplo, eu nunca vi um sistema que não precise de manutenção. Que possa ser, simplesmente, "jogado fora".

Existe ainda uma forma de medir a qualidade do software usando o ROI. Já que um "bom software" potencializa o ROI, por que não usar esta métrica para medir a qualidade do software. Esta, me parece, a melhor das alternativas. No entanto, existe um problema complexo de ser resolvido. O ROI está relacionado com mais algumas variáveis além da qualidade do software (mercado, concorrência, gestão interna, outros softwares, etc). A não ser através de um estudo matemático destas co-variáveis é muito difícil medir o quanto cada variável influencia no ROI e, portanto, é difícil tirar uma métrica da qualidade do software pela medida do ROI. Normalmente um ROI baixo é o motivador para a realização da análise da qualidade de um software, mas nem sempre indica um software ruim.

Como saber se um software é bom?

Partindo da premissa do que é um "bom software", precisamos compreender o que nos leva (desenvolvedores) a acreditar que um software é bom. Para isso, é preciso se colocar na posição de um desenvolvedor que, sem nenhum conhecimento prévio sobre o sistema em avaliação, tem que realizar alterações funcionais de diferentes níveis de complexidade neste sistema. É importante ressaltar que estas alterações devem ser realizadas de forma segura, ou seja, é preciso que seja contabilizado nesta análise o tempo para a realização de testes das funcionalidades afetadas pelas supostas alterações.

Nesta situação, existem essencialmente três fatores que podem ser facilmente avaliados para a qualificação do código-fonte de um sistema computacional:

Testabilidade
Quanto mais fácil e rápido é testar um software, mais rapidamente e de forma mais segura alterações podem ser realizadas nele. Testabilidade, em termos técnicos, tem a ver com desacoplamento, com gestão de dependências, com separação de camadas, com mecanismos de integração, etc. A pergunta a ser respondida é: Quão fácil e rápido é testar o software antes e depois da alteração realizada? Esta pergunta deve levar em perspectiva os testes de regressão sobre todas as funcionalidades potencialmente afetadas pela alteração em questão.

Aderência ao Negócio
Se, mesmo desconhecendo o código-fonte e o negócio envolvidos, ao conversar com um usuário (não com um desenvolvedor) sobre uma nova funcionalidade, eu puder rapidamente e de forma segura encontrar no código-fonte o local apropriado para realizar a alteração desejada, terei a percepção de que o código e o negócio são coerentes. Os termos usados pelos usuários estão representados no software, assim como as relações, conceitos, etc. Tecnicamente, esta questão reforça características como reutilização de software, organização de módulos / componentes, orientação a objetos, etc. A pergunta a ser respondida é: Eu consigo encontrar rápida e seguramente no código-fonte o local onde uma alteração deve ser feita após uma conversa com o solicitante de uma nova funcionalidade?

Adaptabilidade
Um sistema é adaptável se é possível alterar a arquitetura de uma parte deste software sem a necessidade de reimplementar um volume muito maior de funcionalidades do que o estritamente necessário. Tecnicamente, esta questão reforça questões como componentização e protocolos de integração. A pergunta a ser respondida é: Eu consigo alterar a arquitetura de uma funcionalidade para ganhar, por exemplo, escalabilidade, sem ter que alterar a arquitetura de todo o sistema ou de uma grande parte dele?

Esta é uma abordagem simples, prática e abrangente para a avaliação da qualidade do código-fonte de uma aplicação. O que acham? Existem outras variáveis a serem consideradas?

terça-feira, 23 de agosto de 2011

Software Bem Testado

Muito tem sido escrito sobre testes automáticos e testabilidade de software nos dias atuais. O rápido avanço tecnológico tem facilitado o desenvolvimento de testes unitários, de integração e funcionais. No entanto, o uso efetivo de testes automatizados não tem se mostrado constante nos sistemas. Na Dextra temos feito um grande esforço no sentido de usar metodologias e tecnologias de desenvolvimento que possibilitem a criação de testes automatizados em seus diversos níveis e temos entregado software com grande qualidade de testes automáticos. Mas, para isso, partimos da seguinte definição do que é “software bem testado”:

Pode-se dizer que um sistema é bem testado quando:

  • O sistema não acusa falhas em suas funcionalidades mais críticas ou quando as acusa a correção é simples e não causa impacto nas demais funcionalidades do sistema;
  • O sistema suporta novas funcionalidades ou evoluções de funcionalidades existentes sem que as funcionalidades já existentes e não alteradas sejam afetadas de forma não controlada;

Esse objetivo é ambicioso pois deve garantir que:

  1. Poucas falhas sejam encontradas, pelo menos em funcionalidades críticas;
  2. A correção das falhas seja rápida;
  3. Alterações no software não causem impacto nas demais partes do sistema, ou o impacto seja apontado por testes automatizados;
  4. Esta característica deve ser mantida durante todo o ciclo de vida do sistema, ou seja, evoluções precisam ser refletidas nos testes;

Para alcançar estes objetivos, é necessário adotar duas diferentes e complementares abordagens: Arquitetura e Processo. Uma arquitetura bem definida pode garantir que um sistema seja testável, mas não garante que ele seja efetivamente testado. Apesar do advento de novas metodologias de desenvolvimento ágil, o desenvolvedor júnior (que é o mais abundante no mercado atualmente) não cria testes voluntariamente e nem cria testes bem feitos. É neste ponto que entra um processo de desenvolvimento que garanta a codificação de testes em uma cobertura racional do sistema com o envolvimento garantido de desenvolvedores experientes na sua elaboração e revisão. Neste sentido, infelizmente, a maioria dos processos baseados em metodologias tradicionais tem falhado. E tem falhado principalmente ao definir uma porcentagem mínima de cobertura de testes, em geral denominado “taxa de cobertura”. Infelizmente este número não tem significado algum que nos permita deduzir se um software é ou não bem testado. Seguem abaixo cinco razões para evitar este tipo de solução:
  1. A taxa de cobertura não diz que o sistema funciona de acordo com o especificado, diz somente que as regras implementadas no sistema funcionam para um conjunto de testes qualquer. Ou seja, não dá nenhuma medida de quanto o software atende aos seus requisitos. Isso é relevante, pois, afinal, não seria esse o principal objetivo dos testes?
  2. A taxa de cobertura, a não ser que seja 100%, não garante que os pontos mais críticos foram cobertos pelos testes. Mas, não são exatamente estes pontos que deveriam ser testados? Em geral, o uso desta taxa em um valor qualquer diferente de 100%, por exemplo, 70%, tem o efeito exatamente contrário do desejado, fazendo com que as partes menos críticas sejam testadas (pois são mais fáceis de testar) até que a taxa seja alcançada, fazendo com que os 30% restantes e não testados sejam, muito provavelmente, as partes que mais deveriam ser testadas.
  3. A taxa de cobertura próxima a 100% multiplica quase que irracionalmente a quantidade de testes no sistema. Mesmo sem garantir nada com relação à aderência aos requisitos, esta quantidade extensiva de testes aumenta significativamente os custos do projeto e de manutenção futura do software desenvolvido.
  4. Uma baixa taxa de cobertura não garante que o software é mal testado. As partes mais críticas podem ter sido testadas à exaustão verificando os comportamentos definidos nos requisitos do sistema. Como vimos antes, ter muitos testes não é necessariamente bom, mesmo que estes testes sejam bem feitos, pois o custo de manutenção cresce bastante com o número de testes a serem mantidos.
  5. E o pior, a taxa de cobertura, por ser uma medida quantitativa, pode dar uma falsa segurança aos gestores de projeto e mantenedores de processo fazendo com que medidas efetivas para melhoria da qualidade dos testes não sejam tomadas.

Basicamente o erro está em acreditar que a cobertura do código-fonte é importante, mas não é. O importante é que existam testes onde há maior probabilidade de falha. Testes de código que nunca falham não são verdadeiramente úteis. No entanto, testar somente o que vai falhar parece paradoxalmente complexo. Testar tudo poderia ser uma abordagem para testar sempre o que vai falhar, porém esta abordagem é dispendiosa e tem efeitos colaterais indesejados. Para resolver este problema, um processo deveria, pelo menos:
  • Definir que para todo erro notificado no sistema (em qualquer fase do desenvolvimento) seja escrito um teste automático que reproduza o erro em questão em um ambiente simulado. Desta forma, existirão mais testes onde houver mais erros;
  • Definir quais partes do sistema deverão ser melhor testadas e atribuir a responsabilidade de revisão de código nestas partes para o arquiteto, projetista ou desenvolvedores mais experientes;
  • Definir que nem todos os testes elaborados durante o desenvolvimento são necessários após a finalização do desenvolvimento. O importante não é a quantidade de testes, mas a sua relevância;

Bom, em um processo que possibilite a realização destas atividades, possuir a taxa de cobertura pode não agregar muito valor, mas não retira valor do que foi realizado. O que temos visto nos projetos da Dextra é que, através destas simples diretivas, uma alta taxa de cobertura acaba sendo atingida e com grande qualidade.