1 /20
MÉTRICAS E QUALIDADE DE SOFTWARE
Firmino dos Santos Filho,
Brasil
[email protected]
Abstract
Pelo fato da qualidade não possuir uma única dimensão, atributo, ou característica, a
noção de qualidade normalmente é capturada em um modelo que descreve as
características compostas e as relações entre elas. Para definir um modelo de qualidade,
deve haver uma clara distinção entre atributos internos e externos. Qualidade pode ser
medida de diversas formas — métricas e critérios devem ser estabelecidos para
satisfazer as necessidades do projeto de software. Este artigo discute como aplicar
métricas de software para melhorar a qualidade e a confiabilidade de produtos de
software, baseado nas melhores práticas de desenvolvimento de software, práticas
comercialmente aprovadas.
Índice
Abstract.....................................................................................................................................1
1.
Definições...........................................................................................................................2
2.
Melhores Práticas de Software ........................................................................................3
3.
Erros, Falhas e Avarias ....................................................................................................6
3.1.
Análise da Terminologia sob a ótica da língua Portuguesa.......................................6
3.2.
Erros, Falhas(Faults) e Avarias(Failures)...................................................................7
4.
Confiabilidade como um Atributo da Qualidade...........................................................8
5.
Melhoria do Processo de software com CMM ...............................................................9
6.
Métricas de Software para Qualidade. .........................................................................10
6.1.
Métricas de Qualidade para Requisitos de Software...............................................11
6.1.1.
Use Case (Casos de Uso) .........................................................................................11
6.1.2.
Métricas para os Requisitos....................................................................................12
6.2.
Qualidade do Código e do Projeto, Métricas de Confiabilidade.............................12
6.2.1.
6.2.1.1.
Métricas de Código..................................................................................................13
Tamanho...............................................................................................................13
6.2.1.1.1. Número de classes ................................................................................................13
6.2.1.1.2. Número de linhas executáveis.............................................................................14
6.2.1.2.
Volatilidade ..........................................................................................................14
6.2.1.2.1. Breakage ...............................................................................................................14
6.2.1.3.
Complexidade.......................................................................................................14
6.2.1.3.1. Tamanho dos métodos .........................................................................................14
6.2.1.3.2. Número de declarações executáveis por método...............................................14
6.2.1.3.3. Número de métodos por classe ...........................................................................14
2 /20
6.2.1.3.4. Número de if-then-else, while, for, try and switch aninhados..........................14
6.2.1.3.5. Número de Caminhos Estáticos..........................................................................15
6.2.1.3.6. Resposta de uma Classe (RFC)...........................................................................15
6.2.1.3.7. Complexidade Ciclomática de métodos .............................................................15
6.2.1.3.8. Profundidade da estrutura de herança ..............................................................16
6.2.1.4.
Acoplamento.........................................................................................................16
6.2.1.4.1. Número de filhos ..................................................................................................16
6.2.1.4.2. Acoplamento entre objetos (fan-out da classe)..................................................16
6.2.1.5.
Coesão ...................................................................................................................17
6.2.1.5.1. Número de filhos ..................................................................................................17
6.2.1.5.2. Falta de coesão em Métodos (LCOM)................................................................17
6.2.1.6.
Legibilidade ..........................................................................................................17
6.2.1.6.1. Número de linhas de comentário por número de declarações ou instruções do
programa 17
6.2.1.6.2. Razão Comentários / Código ..............................................................................17
6.3.
Qualidade do teste e Métricas de Confiabilidade....................................................17
6.3.1.
Casos de Teste..........................................................................................................18
6.3.2.
Propósito dos Casos de Teste..................................................................................18
6.3.3.
Métricas de Teste.....................................................................................................19
7.
Referencias ......................................................................................................................19
1. Definições
Na norma ISO 9126, qualidade de software é definido como: "A totalidade de recursos
e características de um produto de software que afeta sua habilidade para satisfazer as
necessidades definidas ou implícitas". Decorre que a qualidade é decomposta em seis
fatores:
• Funcionalidade
• Confiabilidade
• Eficiência
• Facilidade de Uso
• Facilidade de Manutenção
• Portabilidade
IEEE 610.12-1990 define confiabilidade como “A habilidade de um sistema ou
componente executar as funções exigidas nas condições declaradas por um período de
tempo especificado.”
IEEE 982.1-1988 define Gerenciamento de Confiabilidade de Software como “O
processo de otimização da confiabilidade de software por um programa que enfatiza
prevenção de erro de software, detecção e remoção de falhas, e o uso de medidas para
maximizar a confiabilidade levando em conta fatores restritivos do projeto tais como
recursos, cronograma e desempenho.”
3 /20
Isto posto, a confiabilidade do produto de software entregue é relacionado a qualidade
de todos os processos e produtos do desenvolvimento de software; a documentação dos
requisitos, o processo de desenvolvimento, o código, planos de teste, e o teste do
software.
A presença de um bem definido e bem administrado processo é um discriminador
fundamental entre hiper-produtivos projetos e projetos malsucedidos. Para melhorar a
qualidade do software, o processo de desenvolvimento de software deve ser
compreendido, definido, medido, e continuamente melhorado.
A definição de processo de desenvolvimento de software definida pela SEI: "Um
processo de software é uma série de atividades, métodos, práticas e transformações que
as pessoas usam para desenvolver e manter produtos de software.”
Em sistemas de software de grande porte, a obtenção de qualidades tais como
desempenho, segurança, suscetibilidade à modificações, funcionalidade, confiabilidade,
eficiência, facilidade de uso, facilidade de manutenção e portabilidade não só é
dependente de práticas de a nível de código mas também de todo o processo de
desenvolvimento de software.
2. Melhores Práticas de Software
Um processo de desenvolvimento de software é uma série de atividades necessárias para
transformar os requisitos do usuário em um sistema de software. Um processo efetivo
provê diretrizes para o desenvolvimento eficiente de software com qualidade. Um
processo bem definido permitirá resolver o paradoxo de software, maior qualidade com
rápida disponibilização para o mercado. O processo adequado captura e apresenta as
melhores práticas que o estado atual da arte permite:
• Desenvolvimento Iterativo
! Desenvolvimento Iterativo é a técnica que é usada para entregar a funcionalidade de
um sistema em uma série sucessiva de liberações de modo a realizar crescentemente o
sistema desejado. Os riscos mais críticos devem ser focados nas fases iniciais do projeto
de modo a aumentar previsibilidade a evitar descarte e retrabalho [1].
•
Gerenciamento de Requisitos (Requirements Management, RM)
•
Arquiteturas baseadas em componentes
! RM é definido como uma abordagem sistemática para extrair, organizar e documentar
os requisitos do sistema e um processo que estabelece e mantém um acordo entre o
cliente e os projetistas, de modo a controlar as mudanças de requisitos do sistema.
! O gerenciamento de requisitos envolve a tradução dos pedidos dos clientes em uma
série de necessidades fundamentais dos clientes e características de sistema. Estes por
sua vez são detalhados em especificações funcionais e não funcionais. Estes requisitos
mais específicos são os requisitos de software [2].
! Uma valiosa ferramenta pode ser usada para detalhar requisitos funcionais: Use Case
(Casos de Uso). Um Caso de Uso descreve uma sucessão de ações, executada pelo
sistema, que resulta um valor para o usuário. Casos de Uso servem como uma
representação UML para os requisitos do sistema.
! Quando é dito que um processo é dirigido a Casos de Uso (Use-case driven) significa
que o processo de desenvolvimento segue um fluxo – segue uma série de fluxos de
trabalho que derivam dos casos de uso. Casos de Uso são especificados, casos de uso
são projetados, e no final casos de uso são a fonte a partir do qual o projetista de teste
constrói os casos de teste (test cases).
! Um componente pode ser definido como uma parte substituível de um sistema que
cumpre uma função clara no contexto de uma arquitetura bem definida. Um
4 /20
componente adapta-se e provê a realização física de uma série de interfaces e
comportamentos.
! Arquitetura baseada em componentes é a base para a reutilização, reutilização de
componentes e reutilização de arquiteturas; permite o uso de componentes
comercialmente disponíveis e a expansão do software existente incrementalmente [3].
•
Foco na Arquitetura
•
Modelagem Visual (UML) e Métodos Orientados a Objetos
•
Trabalho de equipe
•
Ferramentas de apoio
•
Verificação continua da qualidade
! Extensas análises dos requisitos, do projeto, implementação e atividades de avaliação
são executadas antes da implementação completa esteja em foco. O foco inicial do
projeto de implementar e testar a arquitetura deve preceder o desenvolvimento em larga
escala e teste de todos os componentes.
! Em sistemas de software de grande porte, a obtenção dos requisitos de qualidade não só
depende de práticas de a nível de código, mas também de toda a arquitetura do
software. Assim, está entre os principais interesses do desenvolvedor, determinar, na
ocasião em que a arquitetura de sistema de software for especificada, se o sistema terá
as qualidades desejadas.
! UML (Unified Modeling Language) é a terceira geração de linguagem de modelos
visuais que define as construções e relações de sistemas complexos.
! A UML é a linguagem sucessora da análise orientada a objetos e métodos de projeto.
! A UML é uma linguagem padronizada para modelagem de software – uma linguagem
que permite a visualização, especificação, construção e documentação dos artefatos de
sistemas intensivos de software.
! A linguagem UML permite a comunicação clara e precisa entre os diversos membros do
time de desenvolvimento. A linguagem UML permite ao desenvolvedor a visualização
do produto de seu trabalho em diagramas padronizados. Provendo anotações
formalizadas para capturar e visualizar as abstrações de software, o principal impacto da
tecnologia orientada a objetos está na redução do tamanho total do que precisa ser
desenvolvido.
! Um projeto de software bem sucedido sucesso precisa ter equilíbrio entre um sólido
talento e pessoas altamente qualificadas nas posições chaves. Trabalho de equipe é
muito mais importante que a soma dos indivíduos.
! Todas as pessoas em organizações de desenvolvimento de software têm que ter uma
meta comum: entregar um produto de alta qualidade no prazo e dentro do orçamento
previsto.
! As ferramentas e ambiente usados no processo de desenvolvimento de software têm um
efeito linear na produtividade do processo. Durante cada ciclo de desenvolvimento de
software as ferramentas provêem apoio de automatização crucial, de modo a permitir o
desenvolvimento dos artefatos de engenharia de software através de mudanças graduais
e controladas. Ferramentas e ambientes de desenvolvimento devem ser vistos como
componentes primário para a automatização do processo e melhoria continua.
! Existe uma propriedade famosa no desenvolvimento de software: é muito mais barato
corrigir defeitos durante o desenvolvimento que os corrigir depois do desenvolvimento.
! Nos ciclos de vida iniciais as métricas devem ter uma forte contribuição para a
avaliação da qualidade, quando esforços para melhorar a qualidade de software são
muito mais efetivos. A coleta das métricas deve ser automatizada e não intrusiva, ou
seja não deve interferir com as atividades dos desenvolvedores.
! A avaliação do software deve ser uma coleta de tópicos não usuais (geralmente
chamado de métricas de software), que possui uma ampla gama de modelos para
predizer a qualidade do projeto de software.
5 /20
! Deve-se utilizar as métricas e indicadores de software para medir o progresso e a
qualidade de cada artefato produzido durante o processo de desenvolvimento de
software.
! Você não pode desenvolver um produto de software com qualidade ou melhorar o
processo sem ter como medir (medir no sentido de avaliar sua qualidade e estágio de
desenvolvimento) este software. As medições obtidas do software devem ser analisadas
de modo a identificar pontos fracos do processo definido e prover uma forma de se
obter uma melhoria do processo utilizado.
! Métricas de software são usadas afim de monitorar e avaliar os seguintes aspectos do
projeto:
" Progresso em termos de tamanho e complexidade.
" Estabilidade em termos de taxa de mudança na implementação, tamanho ou
complexidade.
" Modularidade em termos da extensão da mudança.
" Qualidade em termos do número e tipo de erros.
" Maturidade em termos da freqüência de erros.
" Recursos em termos de recursos despendidos contra os planejados.
! A visão matemática das métricas pode ser achada nas referências [5] e [7].
•
Gerenciamento da configuração de software (SCM, Software configuration
management)
! SCM é uma disciplina da engenharia de software que inclui as ferramentas e técnicas
(processos ou metodologia) utilizadas pelas empresas para gerenciar as mudanças de
seus ativos de software.
! IEEE 828-1998 diz sobre SCM:
" SCM constitui uma boa prática de engenharia para todos os projetos de software,
independentemente da fase do desenvolvimento, ou se for protótipo rápido, ou
manutenção em andamento. Aumenta a confiança e qualidade do software pelas
seguintes razões:
# Prove estrutura para identificação e controle da documentação, código,
interfaces, e bancos de dados para apoiar todas as fases do ciclo de vida.
# Apoiando uma metodologia escolhida para desenvolvimento / manutenção que
se ajuste aos requisitos, normas, políticas, organização e filosofia de
gerenciamento.
# Produz gerenciamento e informação de produto relativo ao estado da versão
do produto de software utilizado como referencia, controle de mudanças,
testes, liberações, auditorias, etc.
•
Padrões para Codificação (Coding Standards)
! A eliminação de todos os erros está, pelo menos em ambientes industriais atuais, bem
além da capacidade tecnológica de software disponível. Não obstante a experiência
sugere que a densidade de erros de códigos liberados possam ser reduzidos pela metade
através da utilização de processos internos de verificação apoiados por ferramentas
analíticas adequadas. Isto não requer mudanças de paradigmas ou idiomas. É necessário
a determinação na adoção de técnicas comprovadas.
! De todas as formas de controle de qualidade de software, a inspeção de código é sem
dúvida a mais efetiva. Quando apoiado por boas ferramentas, o custo unitário típico de
identificação de um erro estático é até duas vezes menor que o custo da identificação
através de métodos dinâmicos. Para realizar o trabalho de inspeção você precisa de um
padrão de codificação (coding standard) definindo requisitos que o código a ser
inspecionado deve satisfazer. [12]
! Um padrão de codificação são regras que governam o uso de uma linguagem de
programação. Complementa o padrão da linguagem definindo características de uso
aceitável e o inaceitável. Características de uso inaceitável conduzem ao erro ou a má
interpretação. Características de uso aceitável evitam situações dúbias ou problemáticas.
Isto não garante que seu código esteja livre de erros, porque sempre se pode alcançar
6 /20
uma implementação imaculada da coisa errada. Um padrão de codificação ajuda a que
você:
" evite uso de características indefinidas,
" evite uso de características não especificadas,
" evite uso de características definidas pela implementação,
" se proteja contra erros de compilação,
" se proteja contra erros comuns de programação,
" limite a complexidade de seu programa (Veja item 6),
" estabeleça uma base objetiva para revisão de seu código.
! Evitando usos indefinidos, não especificados e definidos pela implementação,
efetivamente você limita o uso da linguagem de programação a um subconjunto que é
inequivocamente definido. Isto evita os pontos fracos linguagem. Este processo não é a
prova de falhas mas o ajudará a prevenir erros. Se você examinar relatórios de erros
gerados pelo compilador, não só o seu próprio, mas também de outros desenvolvedores,
para a mesma linguagem, você obterá uma idéia razoável dos tipos de coisas que podem
ser mal implementadas. Você pode evitar essas características da linguagem ou pelo
menos sujeitar seu o uso a uma clara e razoável justificação.
•
Teste Automatizado
! ”Teste Automatizado” está automatizando o processo manual de teste ainda hoje em
uso.
! O propósito real das ferramentas de teste automatizadas são automatizar os testes de
regressão. Isto significa que você tem que ter ou tem que desenvolver casos de teste
detalhados que sejam reproduzíveis, e este conjunto de testes sejam executados toda
vez que haja uma mudança no programa de modo a assegurar que esta mudança não
produza conseqüências não intencionais.
As melhores práticas são um conjunto de técnicas aprovadas comercialmente para o
desenvolvimento de software que, quando usadas de modo combinado, golpeiem as
causas básicas dos problemas de desenvolvimento de software.
3. Erros, Falhas e Avarias
3.1. Análise da Terminologia sob a ótica da língua Portuguesa
A escolha de uma terminologia que exprima na nossa língua conceitos originariamente
definidos em Inglês é uma tarefa delicada e difícil.
Vamos analisar a opção pela trilogia falha => erro => avaria para designar
respectivamente "fault", “error" e "failure". Sendo a tradução de "error" por erro
perfeitamente pacifica, toda a polemica se resume a atribuição de termos Portugueses
para "fault" e "failure". A palavra “falha” é talvez a mais adequada para ambos os
casos, dado não haver na língua portuguesa termos que traduzam com clareza a
diferenciação semântica que existe entre os termos "fault" e "failure" assumidos no
sentido técnico. De fato, existem em Português diversos termos com significado
semelhante tais como "falta", "avaria", "defeito", sendo possível encontrar argumentos
para eleger qualquer destes termos como a melhor tradução quer de "fault" quer de
"failure".
O termo "falha" é normalmente utilizado no sentido de “causa de um evento”. Logo
"falha" é o termo português mais adequado para "fault".
Um outro argumento a favor da tradução de "fault" por "falha", prende-se com o fato de
na área científica o conceito vinculado pelo termo "fault" ser usado com mais
freqüência e num conjunto de expressões mais diversificado do que o termo "failure".
Assim, havendo uma interdependência na tradução das duas palavras anglo-saxonicas,
7 /20
deve-se reservar a melhor tradução para o termo utilizado com mais freqüência ou seja,
para "fault" .
Por outro lado, parece-nos que "avaria" traduz em bom português o termo anglosaxonico "failure", ainda que este termo esteja associado a perturbações físicas de um
sistema e, normalmente, de caracter permanente.
3.2. Erros, Falhas(Faults) e Avarias(Failures)
Nenhum desenvolvedor de software produz um software perfeito na primeira
implementação. Assim, é importante o desenvolvedor medir aspectos de qualidade do
software. A terminologia utilizada na investigação e análise deve ser precisa, enquanto
nos permitindo entender as causas como também os efeitos da avaliação da qualidade e
esforços de aperfeiçoamento.
De acordo com a norma IEEE std 729 define-se a seguinte terminologia:
• Uma falha (fault) acontece quando um erro humano resultar em um resultado
indesejado em algum produto de software. Quer dizer, a falha é a codificação do
erro humano. Por exemplo, um desenvolvedor poderia entender mal um requisito da
interface de usuário, e como conseqüência criar um projeto que inclua o engano. A
falha de projeto também pode resultar num código incorreto, como também
instruções incorretas no manual de usuário. Assim, um único erro pode resultar em
uma ou mais falhas, e uma falha pode residir em quaisquer dos produtos do
desenvolvimento.
• Por outro lado, uma avaria (failure) é o desvio de um sistema de seu
comportamento exigido. Avarias podem ser descobertas antes ou depois da entrega
do sistema, como também elas podem acontecer durante os testes ou durante a
operação do sistema. É importante notar que estamos comparando o comportamento
real do sistema com o comportamento exigido, em lugar de comparar com o
comportamento especificado, porque falhas na especificação dos requisitos podem
resultar em avarias também.
De certo modo, pode-se pensar em falhas e avarias como visões interna e externa do
sistema. Falhas representam problemas que o desenvolvedor vê, enquanto avarias são
problemas que o usuário vê. Nem toda falha corresponde a uma avaria, porque as
condições em que uma falha resulta numa avaria de sistema pode nunca ocorrer. Este
caso é facilmente visualizado se você considerar um código contendo uma falha que
nunca é executado, ou este código não é executado o suficiente para incrementar um
contador que ultrapasse limites inaceitáveis.
Durante o teste e a operação, observamos o comportamento do sistema. Quando um
comportamento indesejável ou inesperado acontece, nós reportamos este fato como uma
avaria. A confiabilidade de um sistema de software está definida em termos de avarias
observadas durante a operação, ao invés de número de falhas; normalmente, podemos
deduzir pouco sobre confiabilidade a partir somente das informações de falhas. Assim, a
distinção entre avarias e falhas é muito importante. Sistemas com muitos falhas podem
ser muito confiáveis, porque as condições que ativam as falhas podem ser muito raras.
Para muitas organizações, erros freqüentemente significam falhas. Também há
uma noção distinta de "processar erro", que pode ser pensado como um estado do
sistema que resultou da ativação de uma falha mas antes da ocorrência de uma avaria
[4]. Esta noção particular de erro é altamente pertinente a software tolerante a falhas
8 /20
(que está preocupado em como prevenir avarias na presença de erros de
processamento) [5],
• Anomalias normalmente representam uma classe de defeitos que são improváveis de
causar avarias (desde que considerados isoladamente), mas eventualmente podem
causar avarias indiretamente. Neste caso, uma anomalia é um desvio do correto,
mas não é necessariamente errado. Por exemplo, desvio do padrão aceitável da boa
prática de programação (como uso de nomes de variáveis sem significado) é
considerado freqüentemente como anomalia.
• Defeito normalmente é utilizado para se referenciar coletivamente a falhas e
avarias. Porém, às vezes um defeito é uma classe particular de falha.
• Bugs refere-se a falhas que acontecem no código.
• Crashes são um tipo especial de falha onde o sistema deixa de funcionar.
Até que a terminologia seja a mesma para todos, é importante sejam definidas regras
claras, de forma que todos as compreendam, quem deve suprir, coletar, analisar, e usar
os dados. Freqüentemente, diferenças de significado são aceitáveis, contanto que estes
dados possam ser transladados de uma estrutura para a outra.
Sistema
Codificação do Erro Humano
Erro Humano
falha
avaria
4. Confiabilidade como um Atributo da Qualidade
Há muitos modelos diferentes para qualidade de software, mas em quase todos modelos,
confiabilidade é um dos critérios, atributo ou característica que estão incorporadas. ISO
9126 std define seis características de qualidade, uma dos quais é confiabilidade.
Considerando que confiabilidade é um atributo da qualidade, pode se concluir que a
confiabilidade de software depende de um software com muita qualidade. A construção
de um software confiável depende da aplicação de atributos de qualidade a cada fase do
ciclo de vida de desenvolvimento com a ênfase na prevenção de erros, especialmente
nas fases preliminares do ciclo de vida. Métricas são necessárias a cada fase do
desenvolvimento para medir atributos da qualidade. IEEE Std 982.2-1988 inclui o
diagrama da Figura 1, indicando a relação da confiabilidade com as diferentes fases do
ciclo de vida. [8]
9 /20
CONCEITOS
• Necessidades/
Objetivos do
usuário
–funcionalidade
–desempenho
–completo
–consistência
• Padrões de
Documentação REQUISITOS
• Integridade das mudanças
• Aderência as necessidades
• Cobertura dos Testes de
• Arquitetura
regressão
• Ambiente Operacional
• Facilidade de aprendizado,
• Completo
CONFIABILI
facilidade de uso.
• Facilidade de uso
-DADE DE
PROJETO
INSTAÇÃO &
SOFTWARE
• Complexidade
VERIFICAÇÃO
• Modularidade
• Realidade operacional
• Interfaces
• Cobertura da
• Expansibilidade
configuração
• Cronologia,
• Interfaces
TESTE
IMPLEMENTADimensão
– SW / SW
• Cobertura das ÇÃO
• Completo
– SW / HW
Funcionalidades • Complexidade
• Cobertura dos
• Interfaces
Tópicos
• Completo
• Interface dos
• Padrões de
componentes
Desenvolvimento
• Medidas de
• Facilidade de
Desempenho
manutenção
FIM DE VIDA
• Facilidade de
transferência,
conversão,
migração.
• Verificação
em paralelo.
OPERAÇÃO &
MANUTENÇÃO
Figura 1: Fatores de Qualidade que afetam a Confiabilidade
Focando na prevenção de erros para melhoria da confiabilidade, precisamos identificar e
medir os atributos da qualidade aplicável as diferentes fases do ciclo de vida.
Precisamos especificamente focar o fluxo de trabalho (workflow) – requisitos, análise,
projeto, implementação, e teste – que ocorrem nas diversas iterações.
5. Melhoria do Processo de software com CMM
Um processo de desenvolvimento de software bem administrado pode ser visto como
processo iterativo de troca de informações e permite que organizações de
desenvolvimento de software tenham uma clara visão e um bom entendimento da
informação disponível, provendo fundamentos para a análise e administração do
processo de software baseado em fatos concretos e não em vagas suposições.
Para resistir a pressão da competição, economia de recursos, e para melhorar a
qualidade do software produzido, uma organização de desenvolvimento de software
precisa perceber a necessidade de implementar e administrar um processo de
desenvolvimento de software eficiente e efetivo. [13]
O Modelo de Maturidade de Capacidade (Capability Maturity Model (CMM)),
desenvolvido pela Software Engineering Institute (SEI), é a estrutura básica conceitual
que representa o processo de gerenciamento do desenvolvimento de software. O CMM
contêm cinco níveis de maturidade ou fases. Estes cinco níveis de maturidade definem
uma escala original para medir a maturidade do processo de software de uma
organização e para avaliar a capacidade do processo de software. Cada nível de
maturidade indica o nível de capacidade de processo:
10 /20
•
Nível 1, inicial: O processo de software é caracterizado como ad hoc, caótico, e
heróico. Poucos processos estão definidos ou seguidos, e o sucesso do projeto
depende do esforço individual. Não há nenhum gerenciamento formal sobre o
desenvolvimento de software.
•
Nível 2, reproduzível: Este nível provê uma introdução formal, ao processo
documentado. São estabelecidos processos básicos de gerenciamento para controlar
custo, cronograma e funcionalidade. A necessária disciplina do processo está a
caminho de repetir sucessos de projetos anteriores com aplicações semelhantes. A
elevação do Nível 1 para o Nível 2 significa que a organização estabeleceu controle
sobre o gerenciamento de projeto, estabeleceu um grupo de processo de engenharia
de software (SEPG), e formalmente introduziu métodos e técnicas de engenharia de
software.
•
Nível 3, definido: Este nível provê os fundamentos para o processo de melhoria
contínua estabelecendo as funções do gerenciamento do processo necessárias para
controlar os parâmetros do processo. O processo de software para as atividades de
gerenciamento e engenharia estão documentados, padronizados, e integrados em um
processo de software padronizado para toda a organização. Todos os projetos usam
uma versão sob medida (subset adequado ao projeto) do processo de software
padrão da organização para desenvolver e manter software.
•
Nível 4, gerenciado: Medidas detalhadas do processo de software e da qualidade do
produto são coletadas. O processo de software e de produtos são quantitativamente
compreendidos e controlados.
•
Nível 5, otimizado: O processo de melhoria contínua é possível através da avaliação
quantitativa do processo e a partir da introdução de idéias e tecnologias inovadoras.
6. Métricas de Software para Qualidade.
Devem ser usadas métricas de software para melhorar a qualidade e a confiabilidade
através da identificação de áreas da especificação de requisitos do software e do código
que potencialmente podem causar erros.
Medidas oferecem visibilidade de como os processos, produtos, recursos, métodos, e
tecnologias de desenvolvimento de software se relacionam entre si. Medidas podem nos
ajudar a responder perguntas sobre a efetividade de técnicas ou ferramentas, sobre a
produtividade de atividades de desenvolvimento e a qualidade dos produtos.
Modelos de qualidade normalmente envolvem formas de avaliação do produto, e sua
meta fundamental é prever a qualidade do produto.
Os produtos de um Processo de Desenvolvimento de Software são os artefatos,
incluindo o software, documentos e modelos. As métricas recomendadas são listadas
aqui com os modelos para os quais se aplicam.
11 /20
Três fases do ciclo de vida serão abordadas onde técnicas de prevenção de erro e
métricas de software podem ser aplicadas com grande impacto sobre a qualidade e a
confiabilidade: requisitos, codificação e teste.
6.1. Métricas de Qualidade para Requisitos de Software
Os requisitos especificam a funcionalidade que deve ser incluída no software final. É
crítico que os requisitos sejam escritos em linguagem clara e precisa de modo a facilitar
o entendimento entre o desenvolvedor e o cliente. Usando os atributos de qualidade para
a confiabilidade mostrado na Figura 1, para software de alta confiabilidade, os
requisitos devem ser estruturados, completos, e de fácil aplicação.
Há três formatos primários para estrutura de especificação de requisitos, definidos por
IEEE, DOD e NASA. [7,8,9]. Estes definem o que deve conter a especificação dos
requisitos além dos próprios requisitos. O uso consistente de um formato como estes,
assegura que informações críticas, como o ambiente operacional, não sejam omitidas.
Requisitos completos são estáveis e incluem todas as informações possíveis,
especificado com detalhes adequados de modo a permitir que o projeto e a
implementação evoluam. Especificações de requisitos não deveriam conter frases tal
qual ASD (a ser definido) ou ASA (a ser adicionado) pois a generalidade destas frases
provocam um impacto negativo no projeto, e causam uma arquitetura incoerente.
Para aumentar de a facilidade de uso dos requisitos, eles são escritos normalmente na
língua corrente (português no Brasil) [ao invés de um estilo de escrita especializado (por
exemplo, anotação Z)] que pode facilmente produzir terminologia ambígua. Para
desenvolver software confiável nas fases subsequentes a fase de requisitos, os requisitos
não devem conter termos ambíguos, ou conter qualquer terminologia que possa ser
interpretado como um requisito opcional. Requisitos ambíguos são estes que podem ter
significados múltiplos ou que parecem deixar ao desenvolvedor a decisão se deve ou
não implementar um requisito.
A importância de documentar requisitos corretamente foi uma das razões para que a
indústria de software produzisse um número significante de ferramentas de auxilio à
criação e gerenciamento de documentos da especificação de requisitos e dos itens
especificados individualmente. Entretanto poucas destas ferramentas ajudam na
avaliação da qualidade do documento de requisitos ou dos itens especificados
individualmente.
6.1.1. Use Case (Casos de Uso)
Uma boa ferramenta para capturar requisitos e coloca-los no contexto é o modelamento
de Casos de Uso (Use Cases).
Casos de Uso são um modo para organizar requisitos da perspectiva do usuário. Todas
os requisitos para um usuário realizar uma tarefa particular são reunidos em um único
caso de uso. O modelo de use-case é a coleção de todos os casos de uso individuais.
Vantagens do modelamento de casos de uso incluem:
• Casos de uso mostram porque o sistema é necessário. Casos de uso mostram que
metas os usuários podem realizar usando o sistema.
• Requisitos de sistema são definidos no contexto. Cada requisito é parte de uma
sucessão lógica de ações de modo a realizar uma meta do usuário.
12 /20
•
•
Casos de uso são facilmente compreensíveis. O modelo expressa requisitos da
perspectiva do usuário e na linguagem própria do usuário. O modelo nos mostra
como os usuários imaginam o sistema e o que o sistema deve fazer.
O modelo é um meio para comunicar os requisitos entre os clientes e o
desenvolvedor, de modo a garantir que o sistema que construímos é o que deseja o
cliente.
6.1.2. Métricas para os Requisitos
Característica
Tamanho
Esforço
Volatilidade
Qualidade
Rastreabilidade
Completo
Métricas
• Número totais de requisitos
• Número de Casos de Uso
• Unidades de homens-hora (na elaboração, mudança e
reparo, separadamente).
• Número de defeitos e pedidos de mudança (aberto, fechado)
• Defeitos–número de defeitos, por severidade, abre, fechado
• Requisito para UC
• Modelo de UC para o projeto
• Projeto – Cenários realizados no modelo de projeto /
número totais de cenários
• Implementação – Cenários realizados no modelo de
implementação / número totais de cenários.
• Teste – Cenários realizados no modelo de teste (casos de
cases) / número totais de cenários.
• Número de Caso de Uso completados (revisados e sob o
gerenciamento da configuração e sem defeitos a serem
resolvidos) / casos de uso identificados (ou número
estimado de casos de uso)
6.2. Qualidade do Código e do Projeto, Métricas de Confiabilidade
Métricas tem que contribuir para a avaliação da qualidade nas fases iniciais do ciclo de
vida, quando esforços para melhorar a qualidade de software são efetivos. A coleta das
métricas deve ser automatizada e não intrusivo, isto é, não deve interferir com as
atividades dos desenvolvedor.
A definição de um procedimento de métricas para códigos orienta os projetos de
software e tem como finalidade monitorar e avaliar os seguintes aspectos do projeto:
• Progresso em termos de tamanho e complexidade.
• Estabilidade em termos de taxa de mudança na implementação, tamanho, ou
complexidade.
• Modularidade em termos da extensão de mudança
• Qualidade em termos do número e tipo de erros.
• Maturidade em termos da freqüência dos erros.
• Recursos em termos do valor gasto com o projeto contra o gasto planejado.
Um modelo de qualidade tem que definir os atributos a serem medidos, atributos
internos e externos:
13 /20
•
Atributos internos - Medimos e analisamos atributos internos porque eles podem
prognosticar atributos externos. Os atributos internos estão freqüentemente
disponíveis para medida no inicio do ciclo de vida, considerando que atributos
externos só são mensuráveis quando o produto estiver completo (ou quase assim), e
segundo, atributos internos são freqüentemente mais fáceis de medir que atributos
externos:
Características a serem medidas
Característica
Tamanho
Esforço
Volatilidade
Qualidade
Completo
•
Métricas
• Número de classes
• Número de linhas executáveis
• Horas homem.
• Número de defeitos e pedidos de mudança (aberto, fechado)
• “Breakage” (veja 6.2.1.2.1) para cada correção ou mudança devido a melhoramento.
Complexidade
• Tamanho de métodos
• Número de declarações executáveis por método
• Número de métodos por classe
• Número de declarações if-then-else, while, for, try e switch
aninhados.
• Contagem estática de caminhos
• Resposta para uma Classe (RFC)
• Complexidade Ciclomática dos métodos
• Profundidade da estrutura de herança de classes
Acoplamento
• Número de objetos filhos.
• Acoplamento entre objetos (classe fan-out).
Coesão
• Número de objetos filhos.
• Falta de coesão nos métodos (LCOM).
Defeitos
• Número de defeitos, por severidade, aberto, fechado.
Legibilidade
• Número de linhas de comentário por número de declarações do
programa.
• Razão comentário / linha de código.
• Número de unidades de classes testadas / número de classes no modelo de projeto
• Número de classes integradas / número de classes no modelo de projeto
• Rastreabilidade da implementação (no modelo de Casos de Uso).
• Rastreabilidade do modelo de Teste.
• Tempo da integração ativa e de teste do sistema.
Atributos externos - esses que só podem ser medidos considerando-se como o
produto se relaciona a seu ambiente:
o Facilidade de uso
o Facilidade de manutenção
o Medidas de qualidade baseadas nos defeitos.
6.2.1. Métricas de Código
6.2.1.1. Tamanho
6.2.1.1.1. Número de classes
Número de classes é um dos modos para se medir Tamanho. Esta medida pode ser
usada para verificação do plano da iteração e da quantidade de retrabalho por iteração.
14 /20
6.2.1.1.2. Número de linhas executáveis
Tamanho é usado para se avaliar a facilidade de compreensão do código por
desenvolvedores e mantenedores. Expressões executáveis é a contagem do número de
linhas executáveis indiferentemente do embora número de linhas físicas de código, por
exemplo,
if (temp < 0)
{
//
temp = 0; //Este exemplo tem uma sentença executável.
}
6.2.1.2. Volatilidade
6.2.1.2.1. Breakage
“Breakage” é a tendência do software em apresentar defeitos em muitos lugares toda
vez que é mudado. Freqüentemente a quebra (“Breakage”) acontece em áreas que não
têm nenhuma relação conceitual com a área que foi mudada. Tais erros enchem os
corações dos gerentes de maus pressentimentos. Toda vez que eles autorizam uma
correção, eles temem que o software quebre de algum modo inesperado. A medida que a
fragilidade se intensifica, a probabilidade da ocorrência de “Breakage” aumenta com o
tempo, se aproximando assintoticamente. Tal software é impossível de se manter. Toda
correção piora a situação, introduzindo mais problemas do que os que são resolvidos.
6.2.1.3. Complexidade
6.2.1.3.1. Tamanho dos métodos
É muito recomendado evitar funções longas (mais do que 100 linhas), porque funções
longas têm muitas desvantagens:
• Se uma função for muito longa, pode ser difícil sua compreensão. Geralmente, pode
se dizer que uma função não deveria ser mais longa que duas páginas, visto que isto
é quanto se pode compreender de uma única vez.
•
Funções complexas são difíceis de se testar. Se uma função consiste em 15
declarações “if” aninhados, então há 215 (ou 32768) diferentes ramos para se testar
em uma única função.
6.2.1.3.2. Número de declarações executáveis por método
O número de máximo de declarações por método deve ser menor que 10, porque
métodos com muitos declarações são difíceis de se entender.
6.2.1.3.3. Número de métodos por classe
É altamente recomendado definir o número de máximo de métodos por classe em 20,
porque é importante ter uma implementação clara e muitos métodos aumentam a
complexidade e obscurecem a compreensão.
6.2.1.3.4. Número de if-then-else, while, for, try and switch
aninhados
O número de máximo de declarações if-then-else, while, for, try and switch aninhados
por classe devem ser menor que 4, porque se um número maior de declarações
aninhadas são usadas, mais difícil se torna manter um claro entendimento.
15 /20
6.2.1.3.5. Número de Caminhos Estáticos
O número de caminhos estáticos de um método, isto é, o limite máximo de todos os
possíveis caminhos de um método, deve ser menor que 20, porque o número de
caminhas estáticos está diretamente relacionado a facilidade de teste do software.
6.2.1.3.6. Resposta de uma Classe (RFC)
O número de máximo de métodos que podem ser invocados em resposta a uma
mensagem deve ser 20. A RFC é a contagem de todos os métodos que podem ser
invocados em resposta a uma mensagem de um objeto de uma classe ou por algum
método da classe. Isto inclui todos os métodos acessíveis dentro da hierarquia da classe.
Esta métrica foca na combinação da complexidade de uma classe através do número de
métodos e a quantidade de comunicação com outras classes. Quanto maior for o número
de métodos de uma classe que podem ser invocados através de mensagens, maior a
complexidade da classe. Se um grande número de métodos podem ser invocados em
resposta a uma mensagem, o teste e depuração da classe se torna complexo porque irá
requerer um conhecimento mais detalhado da mesma por parte de quem efetua os testes.
A elaboração de uma lista com os piores casos possíveis de respostas ajudará na
distribuição apropriada do tempo de teste.
6.2.1.3.7. Complexidade Ciclomática de métodos
Complexidade Ciclomática é a métrica mais amplamente utilizada, membro da classe de
métricas estáticas de software. Introduzida por Thomas McCabe em 1976, mede o
número caminhos linearmente independentes de um módulo de programa. Esta medida
provê um único número ordinal que pode ser comparado à complexidade de outros
programas. A Complexidade Ciclomática é freqüentemente referenciada simplesmente
como complexidade do programa, ou como complexidade de McCabe. Pretende ser
independente da linguagem e do formato da linguagem [15].
A complexidade ciclomática de um módulo de software é calculada a partir de um
gráfico conectado do módulo:
Complexidade Ciclomática (CC) = E - N + p
Onde
E = o número de extremidades do gráfico
N = o número de nós do gráfico
p = o número de componentes conectados
Estudos mostram uma correlação entre a complexidade Ciclomática de um programa e
sua freqüência de erro. Uma baixa complexidade Ciclomática contribui para a facilidade
de compreensão de um programa e indica que este é acessível a modificações com
risco menor que um programa mais complexo. A complexidade Ciclomática de um
módulo também é um forte indicador de sua facilidade de teste.
Complexidade
Ciclomática
1-10
11-20
21-50
maior que 50
Complexidade Ciclomática
Avaliação de Risco
Programa simples, sem muito risco.
Complexo, risco moderado.
Complexo, Programa de alto risco.
Programa quase impossível de ser testado.
(altíssimo risco)
16 /20
Exemplo:
6.2.1.3.8. Profundidade da estrutura de herança
Representa o número de derivações da mais afastada classe de base (origem) até esta
classe. Um valor elevado desta métrica pode indicar que a classe depende de
funcionalidade acumulada, que potencialmente dificulta a compreensão da classe.
Quanto mais em baixo uma classe está dentro da hierarquia, maior o número de
métodos que provável herdará, o que torna muito mais complexo predizer seu
if
x>4
no
while
Do
y=2
yes
then
do this
until
z=3
seqüência:
1-2+2=1
if / then:
3-3+2=2
while loop:
3-3+2=2
until loop:
3-3+2=2
comportamento. Estruturas com ramos mais longos (profundos) ocasionam uma maior
complexidade de projeto, visto que mais métodos e classes estão envolvidos, mas temos
também um maior potencial para reuso de métodos herdados. Maior profundidade de
Herança indica um compromisso entre um incremento na complexidade e um
incremento em reuso. Evite profundidade da estrutura de herança maior que 5.
6.2.1.4. Acoplamento
6.2.1.4.1. Número de filhos
O maior o número de filhos (classes derivadas), maior o reuso, visto que herança é uma
forma de reuso. Maior o número de filhos, maior a probabilidade de uma abstração
imprópria da classe de mãe. Se uma classe tiver um grande número de filhos, pode ser
um caso de abuso de subclasse. Se uma classe tiver um grande número de filhos, pode
requerer mais tempo para teste dos métodos daquela classe. Evite número de filhos
maior que 5.
6.2.1.4.2. Acoplamento entre objetos (fan-out da classe)
É definido como o número de classes com os quais uma classe está acoplada. Duas
classes estão acopladas quando métodos declarados em uma classe usa métodos ou
instancias de variáveis da outra classe [6]. Acoplamento excessivo entre classes de
objetos é prejudicial ao projeto modular e impede o reuso. Quanto mais independente
uma classe é, mais fácil é reutiliza-la em outra aplicação. Para melhorar a modularidade
e promover o encapsulamento, acoplamento entre classes devem ser mínimos. Quanto
maior o número de acoplamentos, maior a sensibilidade à mudanças em outras partes do
projeto, e como conseqüência a manutenção se torna mais difícil. Forte acoplamento
torna um sistema mais complexo visto que uma classe é de difícil compreensão,
17 /20
mudança e correção por si só, se estiver relacionado com outras classes. O projeto de
sistemas com o menor acoplamento possível entre classes pode reduzir a complexidade.
Isto melhora a modularidade e promove o encapsulamento. Evite número de outras
classes com as quais uma classe está acoplada maior que 10.
6.2.1.5. Coesão
6.2.1.5.1. Número de filhos
Veja item 6.2.1.4.1.
6.2.1.5.2. Falta de coesão em Métodos (LCOM)
A falta de coesão mede a dessemelhança de métodos em uma classe por instancias de
variáveis ou atributos.
Um módulo altamente coeso deve estar isolado; alta coesão indica boa subdivisão de
classes. Falta de coesão ou baixa coesão aumenta a complexidade e aumenta a
probabilidade de erros durante o processo de desenvolvimento. Coesão alta indica
simplicidade e alta grau de reuso. Classes com baixa coesão provavelmente poderiam
ser subdivididas em duas ou mais subclasses com maior coesão. Quando os objetos tem
poucos métodos em comum, há muita falta de coesão. Isto implica que um nível de
abstração adicional é necessária – objetos semelhantes precisam ser agrupados criando
classes derivadas para estes.
6.2.1.6. Legibilidade
6.2.1.6.1. Número de linhas de comentário por número de
declarações ou instruções do programa
O código de fonte deve ser suficientemente documentado. Por arquivo, pelo menos,
uma linha de comentário é necessária para cada duas declarações de programa.
Software que não é bem documentado pode ser de difícil compreensão. Especialmente
exceções que acontecem no software e que podem ser facilmente mal compreendidas.
6.2.1.6.2. Razão Comentários / Código
A razão comentários por código é definido como o número de caracteres visíveis em
comentários dividido pelo número de caracteres visíveis fora dos comentários.
Delimitadores de comentários são ignorados. Espaços em branco em “strings” são
tratados como caracteres visíveis. Um valor alto desta métrica pode indicar que há
muitos comentários–um atributo que pode tornar um módulo difícil de se ler. Um valor
pequeno pode indicar que não há o bastante. É recomendado ter uma razão comentário
por código entre 0,5 e 1,5.
6.3. Qualidade do teste e Métricas de Confiabilidade
Métricas de teste devem ter dois critérios para avaliar a confiabilidade de modo
abrangente. O primeiro critério é a avaliação do plano de teste, de modo a assegurar que
o sistema contenha a funcionalidade especificada nos requisitos (rastreabilidade do
teste). Esta atividade deve reduzir o número de erros devido a falta de funcionalidade
esperada.
O segundo critério, que freqüentemente está associado com a confiabilidade, é a
avaliação do número de erros no código e taxa de erros achados/corrigidos.
18 /20
Para assegurar que o sistema contenha a funcionalidade especificada, planos de teste
contendo múltiplos casos de teste são escritos; cada caso de teste é baseado em um
estado do sistema e testa algumas funções baseadas num grupo de requisitos. O objetivo
de um programa efetivo de verificação é assegurar que todo requisito seja testado, o que
implica que se o sistema passa no teste, a funcionalidade requerida está no sistema a ser
entregue.
6.3.1. Casos de Teste
Considerando-se todos os casos de teste, cada requisito deve ser testado pelo menos
uma vez, e alguns requisitos serão testados várias vezes porque eles estão envolvidos
em múltiplos estados do sistema, em vários cenários e de modos diferentes. Mas como
sempre, o tempo e os recursos financeiros disponíveis são questões importantes;
enquanto cada requisito dever ser abrangentemente testado, tempo e orçamento
limitados sempre são restrições para se escrever e executar os casos de teste. É
importante assegurar que cada requisito seja adequadamente, mas não excessivamente,
testado. Em alguns casos, os requisitos podem se agrupados usando como critério que
os mesmos sejam críticos para o sucesso do projeto; estes devem ser extensivamente
testados. Em outros casos, podem ser identificados requisitos não críticos; se um
problema acontece, a funcionalidade destes não afeta o sucesso do projeto enquanto se
obtém um teste bem sucedido.
6.3.2. Propósito dos Casos de Teste
•
•
•
•
•
Identificar e descrever as condições de teste a serem utilizados.
• Estender os Casos de Uso adicionando respostas do sistema
• Criar instancias de Casos de Uso (fluxo básico / fluxo alternativo)
Identificar os dados específicos necessário ao teste.
• Estender o Caso de Uso com vetores de teste (valores).
• Estender as pré e pós condições com condições reais do sistema .
Identificar os resultados esperados do teste.
• Criar critérios de Aprovação/Falha.
Se o objetivo do teste for o sistema completo, o caso de teste corresponderá a
uma execução completa de um caso de uso.
Se o objetivo do teste for um subsistema, o caso de teste corresponderá à
parte do caso de uso que corresponde ao subsistema.
19 /20
6.3.3. Métricas de Teste
Característica Métricas
$%Número de Casos de Teste, Procedimentos de Teste,
Tamanho
“Scripts” de Teste.
$%Número
Esforço
de horas-homem (despendido com a
produção, modificação e correção, separadamente) para a
produção dos casos de teste.
Volatilidade $%Número defeitos e requisições de mudanças (aberto,
fechado) – comparado com o modelo de teste.
$%Defeitos – número de defeitos por grau de severidade,
Qualidade
abertos, fechados (estes defeitos são identificados a partir
do modelo de teste, não defeitos identificados pelo time
de teste no software)
$%Número de casos de teste implementados / número de
Completo
casos de teste estimados.
$%Rastreabilidade do teste (no modelo de Casos de Uso)
$%Rastreabilidade do teste (nos Atributos dos Requisitos)
$%Cobertura do código
Rastreabilidade $%Número de Casos de Teste reportados como bem
sucedidos no Resumo de Avaliação do Teste / Número
de casos de teste.
7. Referencias
[1] Jacobson, Ivar, Grady Booch and James Rumbaugh, "The Unified Software
Development Process," Addison-Wesley, 1999.
[2] Leffingwell, Dean, "Managing Software Requirements," Addison-Wesley, 2000.
[3] Royce, Walker, "Software Project Management," Addison-Wesley, 1998.
[4] Laprie, J.C., "Dependability: Basic Concepts and Terminology," Springer-Verlag,
1992.
[5] Fenton, Norman E., "Software Metrics," PWS, 1997.
[6] Douglas, Bruce Powel, "Real Time UML," Addison Wesley, 1998.
[7] Whitmire, Scott A., "Object Oriented Design Measurement", John Wiley & Sons,
1997.
[8] IEEE Standard 982.2-1987, "Guide for the Use of Standard Dictionary of Measures
to Produce Reliable Software".
[9] Rosenberg, Dr. Linda H., Ted Hammer and Jack Shaw, "Software Metrics and
Reliability," 9th International Symposium, November, 1998, Germany.
20 /20
[10] Basili, Victor R., Lionel C. Briand and Walcélio L. Melo, "A Validation of ObjectOriented Design Metrics as Quality Indicators", IEEE Transactions on Software
Engineering, Vol. 22, nº 10, October, 1996.
[11] Martin, Robert C., "Design Principles and Design Patterns", Object Mentor, 2000.
[12] "Why Coding Standards?", PR:QA White paper Series: WP5.1, Programming
Research Ltd., http://www.prqa.co.uk, 1998.
[13] Raynus, Joseph, "Software Process Improvement with CMM", Artech House,
1998.
[14] Rosenberg, Dr. Linda H., "Applying and Interpreting Object oriented Metrics",
Software Technology Conference, Utah, April 1998.
[15] McCabe, Thomas J. & Watson, Arthur H. "Software Complexity.”, Crosstalk,
Journal of Defense Software Engineering 7, 12 (December 1994): 5-9.
Download

métricas e qualidade de software