LUCAS FLACH DA ROCHA
APLICAÇÃO DA INTEGRAÇÃO CONTÍNUA NO DESENVOLVIMENTO DE SOFTWARE
Florianópolis 2014.
APLICAÇÃO DA INTEGRAÇÃO CONTÍNUA NO DESENVOLVIMENTO DE SOFTWARE
Trabalho de Conclusão de Curso apresentado ao Curso de Graduação em Sistemas de Informações da Universidade do Sul de Santa Catarina, como requisito parcial à obtenção do título de Bacharel em Sistemas de Informação.
Orientador: Jean Carlo Rossa Hauck, Doutor
Florianópolis 2014.
Durante todo o projeto dessa monografia muitos problemas e dúvidas surgiram e foram sanadas no andamento de cada etapa. Alem desses problemas, muitas vezes a parte psicológica não andava bem na medida em que os prazos se aproximavam e a pressão sob as entregas aumentava. Neste sentido, faz-se necessário um agradecimento a todas as pessoas que contribuíram com o projeto diretamente ou indiretamente.
O primeiro agradecimento vai ao doutor Jean Hauck, professor e orientador dessa monografia. Muito obrigado pela ajuda e as orientações necessárias nesse projeto, no qual ficamos envolvidos no período de um ano, pelos emails respondidos rapidamente e pelos encontros quinzenais feitos durante todo o período.
Outra professora responsável pela finalização desse projeto é a doutora Maria Inês. Professora que ministrou as duas disciplinas responsáveis pelo trabalho de conclusão. Obrigado por suas correções e ajuda com as normas ABNT e por muitas vezes ajudando na elaboração de um texto melhor.
Preciso também agradecer a mulher que está sempre do meu lado e incentiva muito o meu dia a dia. Minha namorada e futura mulher Morgana Catuci. Obrigado por sempre estar ao meu lado e me ajudar muito, tanto na parte psicológica quanto na conclusão de um texto mais claro. Você fez parte indiretamente desse projeto e merece muito o meu agradecimento.
Finalizando, não poderia deixar de agradecer minha mãe Maria Helena Flach. Sem ela eu não estaria aqui concluindo o 3º grau, nem mesmo teria ingressado em uma faculdade. No inicio você pagou minha faculdade e eu tenho a consciência que se não fosse você, eu não estaria aqui. Mãe, muito obrigado por todo o esforço que você fez e faz por mim. Este trabalho também é em sua homenagem.
Com projetos cada vez mais complexos e abrangendo mais funcionalidades, cada tempo ganho em uma determinada etapa do ciclo de vida de desenvolvimento de software, torna-se muito importante. Com o uso da integração contínua, um projeto de software tende a ter mais qualidade do inicio ao fim do seu ciclo de vida, isso porque, a integração contínua faz com que se inicie uma nova construção do projeto sempre que algum artefato tenha alguma alteração ou uma nova versão. Utilizando uma pesquisa exploratória foi possível construir um processo de integração contínua com êxito. Primeiramente utilizou-se o Maven como ferramenta de build automatizado e execução dos testes, passando pelo Git como ferramenta de auxilio ao controle de versões e finalizando com o Jenkins auxiliando todo o processo de integração contínua. Após as etapas de construções dos testes automatizados, da configuração do repositório do projeto, da utilização do Maven para o build automatizado e controle de dependências e da configuração de um servidor de integração contínua junto de uma ferramenta para auxiliar do processo de integração contínua, todos os objetivos foram alcançados. Nesse sentido, foi criado um processo de integração contínua eficaz e de fácil controle. Sempre que alguma mudança é feita no projeto, inicia-se uma nova construção e todos os testes são executados, tudo isso de forma automática. Se algum erro ocorrer, já é possível rastrear o mesmo e efetuar a correção, visando sempre o software em estado funcional em todo o seu ciclo de vida.
Palavras-chave: Integração Contínua. Jenkins. Gerência de Configuração. Qualidade de Software. Construção de Software Automatizado. Testes Automatizados.
Figura 1 - Workflow de qualidade de processo ... 21
Figura 2 - Ilustração de validação e verificação ... 24
Figura 3 - Imagem com a definição de Baseline e Branches... 36
Figura 4 - Processo de Integração Contínua ... 46
Figura 5 - Casos de Uso do Software Selecionado ... 62
Figura 6 - Requisitos não funcionais ... 63
Figura 7 - Requisitos Funcionais ... 64
Figura 8 - Desenho do processo de integração contínua do projeto ... 65
Figura 9 - Pilha de bibliotecas, frameworks e ferramentas ... 68
Figura 10 - Relação dos casos de testes com os casos de uso. ... 69
Figura 11 - Estrutura de diretórios de dependências do Maven. ... 73
Figura 12 - Arquitetura do JUnit. ... 74
Figura 13 - Estrutura do projeto localizado no servidor remoto GitHub... 77
Figura 14 - Tela base de configuração da Integração Contínua no Jenkins. ... 78
Figura 15 - Criação de variável de ambiente do Maven. ... 86
Figura 16 - Comando criação de projeto web com Maven. ... 87
Figura 17 - Comando de importação do projeto para o eclipsce. ... 88
Figura 18 - Exemlo de dependência do projeto. ... 88
Figura 19 - Criação de variável que direciona para o repositório do Maven. ... 89
Figura 20 - Estrutura final do projeto junto com o classpath. ... 89
Figura 21 - Um dos testes automatizados desenvolvidos. ... 90
Figura 22 - Fluxo padrão de atualização de arquivos no Git. ... 91
Figura 23 – Local de onde retirar url para configuração de repositório remoto no GitHub. .... 92
Figura 24 - Comando push do git para enviar commit ao repositório remoto do projeto. ... 92
Figura 25 - Plugins selecionados para instalação. ... 93
Figura 26 - Mapeamento de softwares na configuração do Jenkins. ... 94
Figura 27- Tela de criação de um projeto no Jenkins. ... 95
Figura 28 - Tela configuração do projeto no Jenkins. ... 96
Figura 29 - Histórico de build do Jenkins. ... 97
Figura 30 - Detalhamento das mudanças entre uma construção e outra. ... 98
Figura 31 - Resultados dos teste executados pelo Jenkins. ... 98
Figura 32 - Estatísticas de construções do projeto no Jenkins. ... 99
Figura 33 - Cronograma do Projeto em forma de gráfico de Gantt ... 105
Quadro 1 - Relação dos requisitos com atendimento do processo ... 65
Quadro 2 - Relação de requisitos de ferramentas com o seu atendimento ... 68
Quadro 3 - Casos de teste e seus cenários. ... 70
Quadro 4 - API resumida dos métodos de teste do JUnit. ... 74
Quadro 5 - Comandos básicos do git. ... 75
Quadro 6 - Ferramentas e Frameworks instalados. ... 79
Quadro 7 - Relação de problemas e soluções encontradas. ... 83
1.1 PROBLEMATICA ...12 1.2 OBJETIVOS...13 1.2.1 Objetivo Geral ...13 1.2.2 Objetivos Específicos ...13 1.3 Justificativa ...14 1.4 Estrutura do Trabalho ...14 2 REVISÃO BIBLIOGRÁFICA ... 16 2.1 QUALIDADE DE SOFTWARE ...16 2.1.1 Qualidade de Processo ...20 2.1.2 Qualidade de Produto ...22 2.1.3 Verificação e Validação ...23 2.1.4 Testes de Software...25 2.1.4.1 Testes Automatizados ... 28 2.1.4.1.1 Testes Unitários ...29 2.2 GERENCIAMENTO DE CONFIGURAÇÃO ...31 2.2.1 Gerenciamento de Versões ...34 2.2.2 Construção do sistema ...38 2.2.3 Controle de Mudança ...39 2.2.4 Auditoria de Configuração ...41 2.3 INTEGRAÇÃO CONTÍNUA ...42
2.3.1 Praticas da integração Contínua ...48
2.3.1.1 Repositório do Projeto ... 48
2.3.1.2 Ckeck-ins Regulares ... 49
2.3.1.3 Automatização de Build ... 49
2.3.1.4 Construção Auto Testável ... 50
2.3.1.5 Atualização de Repositório Principal ... 50
2.3.1.6 Não Deixe o Processo de Construção Lento ... 51
2.3.1.7 Todos devem ver o que está acontecendo ... 52
2.3.2 Barreiras da Integração Contínua ...52
2.4 CONSIDERAÇÕES FINAIS ...53 3 MÉTODO... 54 3.1 TIPO DE PESQUISA ...54 3.1.1 Natureza ...54 3.1.2 Abordagem ...55 3.1.3 Objetivos ...55 3.1.4 Procedimentos Técnicos ...56 3.2 ATIVIDADES DE PESQUISA ...57 3.3 DELIMITAÇÕES ...58 4 MODELAGEM DA SOLUÇÃO ... 59 4.1 PROPOSTA DA SOLUÇÃO ...59
4.2 APRESENTAÇÃO DO SOFTWARE SELECIONADO ...61
4.3 DETALHAMENTO DA SOLUÇÃO ...65
4.4 DETALHAMENTO DOS CASOS DE TESTE ...69
5 DESENVOLVIMENTO ... 72
5.1 FERRAMENTAS E TECNOLOGIAS ...72
5.2 HISTÓRICO DO DESENVOLVIMENTO ...78
5.2.1 Descrição do Processo ...79
5.2.1.1 Build automatizado e controle de dependências ... 79
5.2.2 Problemas e Soluções ...83
5.2.3 Detalhando o processo (Guia) ...85
5.3 APRESENTAÇÃO DA INTEGRAÇÃO CONTÍNUA ...93
6 CONCLUSÕES E TRABALHO FUTUROS ... 100
6.1 CONCLUSÕES ...100
6.2 TRABALHOS FUTUROS ...102
REFERÊNCIAS ... 103
APÊNDICE A – CRONOGRAMA DO PROJETO ... 105
1 INTRODUÇÃO
Com a evolução do mercado computacional e com os softwares cada vez mais complexos e com muitos módulos e inclusive comunicações com outros aplicativos, a gerência de configuração se torna cada vez mais importante.
Segundo Pressman (2011), a gerência de configuração é aplicada através de toda a gestão de qualidade, auxiliando a identificar as alterações, controlar as alterações e assegurar que as alterações realizadas estão corretas e informar outros interessados sobre as alterações, quando necessário.
Tendo em vista que as mudanças em um software são inevitáveis na medida em que ele é construído. E estas mudanças aumentam o nível de confusão entre os membros de uma equipe de software que estão trabalhando em um projeto. Essas confusões surgem quando as mudanças não são analisadas antes de serem feitas, não são registradas antes de serem implementadas, não são relatadas àqueles que precisam saber ou não são controladas de uma maneira que melhore a qualidade e reduza os erros. (PRESSMAN, 2011).
A gerência de configuração está altamente ligada ao processo de melhoria da qualidade e com a importância da redução de erros. “É muito fácil acontecer de uma sequência de alterações não controladas transformar um bom software em um caos. Como consequência, a qualidade do software é prejudicada e a entrega atrasa”. (PRESSMAN, 2011, p. 514).
Com uma gerência de configuração bem montada, é possível definir as principais atividades na geração de uma versão de software. Essas atividades podem ser mais complexas, dependendo do workflow de cada empresa, mas todas necessitam ter as etapas básicas, que são: Mecanismo de controle de versões, construção do projeto (compilação) e testes. (FARLEY e HUMBLE, 2014).
Esses testes podem estar introduzidos na versão (testes unitários automatizados) e/ou podem ser feitos por profissionais responsáveis pela garantia da qualidade de software. A qualidade final de um software não é uma vantagem apenas para o software em si, ela traz também muitos benefícios para as equipes. “Pode-se fazer certo da primeira vez ou então fazer tudo de novo”.( PRESSMAN 2011, p. 358).
Os testes automatizados focalizam os testes na menor unidade de um projeto de software, o componente ou o módulo de um software. Esses testes fazem com que caminhos de controle importantes sejam testados para descobrir erros dentro dos limites do componente
ou do módulo. As complexidades relativas aos testes e aos erros que eles revelam são limitados pelo escopo estabelecidos para os testes unitários automatizados. Esses testes englobam a lógica interna de processamento e as estruturas de dados dentro dos limites de um componente. (PRESSMAN, 2011).
Portanto, os testes automatizados tem um papel muito importante para um projeto de software. Torna-se possível rastrear erros de uma forma rápida e sistemática. Esses erros já podem ser corrigidos e testados novamente, deixando uma versão de software com mais qualidade já no ponto de partida.
Apesar dos testes automatizados apresentarem uma melhoria significativa em uma versão de software, eles não garantem a qualidade completa. Torna-se necessária a utilização de outras estratégias de teste de software para aumentar a qualidade final de uma versão de software. “Você pode executar testes diariamente, sempre que uma parte do sistema seja construída. Essa abordagem, embora menos atraente, pode ser muito eficaz”. (PRESSMAN 2011, p. 407).
A integração contínua se encaixa muito bem com esse conceito de execução de testes diariamente. Segundo Farley e Humble (2014), a integração contínua é um processo que é feito em continuidade ao processo de desenvolvimento de software. O processo de integração contínua visa que um software deve estar sempre funcional em todo o seu desenvolvimento. Isso ocorre por que sempre que uma mudança é feita inicia-se o processo de compilação e um conjunto de testes abrangentes é executada.
Com isso, a integração contínua pode ser incluída como um dos processos da gerência de configuração. Esse processo tem como objetivo unir as tarefas necessárias para a geração de uma versão de software (check-out,, compilação, construção) em uma ou mais ferramentas. Não necessariamente essas tarefas devem estar vinculadas a uma ferramenta, elas podem ser executadas manualmente, mas o uso de ferramentas ajuda bastante. Os pré-requisitos básicos para a configuração de uma ferramenta para integração contínua são: Controle de Versões, Construções automatizadas (Compilação) e o acordo da equipe. (FARLEY e HUMBLE, 2014).
Sem esses pré-requisitos bem definidos, possivelmente o processo de integração contínua pode falhar em um dos pontos. Ou pode se tornar demorado e/ou complicado. (FARLEY e HUMBLE, 2014).
O acordo da equipe sobre o processo de integração contínua se torna muito importante, porque é ela quem vai ajudar a construir esse processo, rastreando rotinas que podem ser incluídas no processo, removidas do processo ou até mesmo alteradas. É de
extrema importância que a equipe veja que a integração contínua traz muitos benefícios para todos e que, com ele bem definido, suas versões serão disponibilizadas de forma mais rápida e com uma qualidade melhor. (FARLEY e HUMBLE, 2014).
No início, a equipe pode ter um pouco de dificuldade ou até mesmo não aceitar as mudanças que podem ocorrer no processo de desenvolvimento de software. A equipe pode não ter a disciplina necessária para esse trabalho. (FARLEY e HUMBLE, 2014). O processo de integração contínua tem alguns pré-requisitos que podem parecer complexos e cansativos no início, mas eles existem para garantir uma versão de software com mais qualidade e mais agilidade. Além disso, com ele se torna possível rastrear exatamente a mudança que ocasionou uma falha no software.
Torna-se necessário ter uma gerência de configuração definida dentro do processo de desenvolvimento de software, uma rotina de testes automatizados definida e implementados para o início de um processo de integração contínua.
A integração contínua faz com que mudanças benéficas para um projeto de software ocorram e ainda melhorem as gerações de versões de software, tornado-as mais fáceis de serem executadas e as deixando com uma maior qualidade, além de tirar a dependência de pessoas e substituí-las pela dependência de uma ou mais ferramentas. (FARLEY e HUMBLE, 2014).
1.1 PROBLEMATICA
Frequentemente, observam-se empresas tendo sérios problemas na hora de disponibilizar novas versões de seus softwares. “Se você não controlar as alterações, elas controlarão você”. (PRESSMAN, 2011, p. 514). Esses problemas vão desde a má implementação de um código, passam pelos testes que, muitas vezes, não rastreiam eventuais erros e, muitas vezes, chegam até o controle do que exatamente foi feito em uma determinada versão de software. E, em muitos casos, esses problemas só são rastreados nas últimas validações de um determinado software.
Esses problemas, muitas vezes, são ocasionados por falta de testes unitários, falta de controle sobre o que realmente está sendo introduzido nessa nova versão ou pela forte
dependência de certos profissionais (Gerente de Configuração, Desenvolvedores), entre outros.
As tarefas de gerações de novas versões de software são centralizadas e, geralmente, automatizadas em função do processo de integração contínua. Utilizando esse processo, a etapa não fica tão dependente de pessoas e, sim, de uma ou mais ferramentas. (FARLEY e HUMBLE, 2014).
Dentro da forte dependência de certas pessoas, como realizar a integração contínua, integrando todas as etapas de geração de uma nova versão de software?
1.2 OBJETIVOS
A seguir, são apresentados os objetivos deste trabalho.
1.2.1 Objetivo Geral
O objetivo principal deste trabalho consiste em aplicar a gerência de configuração, contemplando a integração contínua com testes automatizados em um sistema já desenvolvido.
1.2.2 Objetivos Específicos
Para que o objetivo seja atingido e o processo de integração contínua tenha sucesso em sua implementação, é necessário que os seguintes objetivos específicos sejam alcançados:
colocar os artefatos do projeto sob gerência de configuração; desenvolver testes unitários automatizados do software; implantar um servidor de integração contínua;
coletar resultados da integração contínua; construir um build automatizado.
1.3 Justificativa
Nos últimos tempos, a integração contínua vem se tornando um tema muito discutido por todos os envolvidos no desenvolvimento de software. Esse tema tende a trazer benefícios para todos que o utilizam. (FARLEY e HUMBLE, 2014).
Os mesmos autores afirmam que o processo de integração contínua é muito atual e poucas pessoas o dominam de forma ampla. Quem se aperfeiçoar, sobre o assunto, poderá ter um diferencial muito importante, com isso, estar melhor preparado para o mercado de trabalho.
O objetivo da utilização desse processo visa à diminuição dos problemas mencionados anteriormente na hora de uma nova liberação de versão de software. Muitas vezes, essas dificuldades consomem tempo em uma etapa que poderia ser rápida. Além disso, muitos desses processos são muito dependentes de profissionais especializados.
Com a integração contínua, esse processo começa a ser suportado por ferramentas e não mais dependente das pessoas envolvidas no projeto.
1.4 Estrutura do Trabalho
Capítulo 1 – No capítulo um, foi apresentada a introdução, os objetivos e a justificativa do trabalho.
Capítulo 2 - Revisão da literatura que trata dos assuntos de integração contínua e Gerência de Configuração.
Capítulo 3 - Trata do Método do trabalho.
Capítulo 4 – O capítulo 4 apresenta toda a modelagem da solução bem como a modelagem do software selecionando, apresentando também as tecnologias utilizadas.
Capítulo 5 – No capítulo 5 as tecnologias utilizadas são mais especificadas junto da explicação de como todo o processo de integração contínua foi desenvolvido, mostrando inclusive as principais dificuldades.
2 REVISÃO BIBLIOGRÁFICA
Neste capítulo de revisão bibliográfica, serão abordados os assuntos como: Qualidade de software, gerência de configuração e integração continua. Todos esses temas estão baseados na literatura. Dentre esses temas, o foco principal serão os pontos necessários para a construção de um processo de integração contínua correto, seguindo os conceitos dos autores usados como referência.
2.1 QUALIDADE DE SOFTWARE
Os problemas com a qualidade de software já são antigos, eles foram inicialmente percebidos com maior intensidade na década de 1960 com o desenvolvimento do primeiro grande projeto de software e continuaram a incomodar a engenharia de software ao longo do século XX, levando a percepção de que o software entregue era lento e pouco confiável, difícil de manter e de reusar. (SOMMERVILLE, 2011).
Na década de 1990, as principais empresas do mundo observaram que grandes quantidades de recursos estavam sendo desperdiçadas por ano em softwares que não apresentavam as características e as funcionalidades prometidas. O problema ainda era pior, tanto governo quanto empresas ficavam cada vez mais preocupados pela forte dependência do software e que uma falha grave poderia bloquear importantes infraestruturas, aumentando os custos de determinados serviços. (PRESSMAN, 2011).
Em resposta a essas insatisfações, passaram a ser adotadas técnicas formais de qualidade de software. Essas técnicas foram desenvolvidas a partir dos métodos usados da indústria manufatureira. Com isso, o gerenciamento de qualidade de software, em conjunto com novos testes de software e com novas tecnologias, aumentou significativamente o nível da qualidade de software. (SOMMERVILLE, 2011).
Atualmente, a qualidade de software ainda é um problema no cotidiano de empresas que desenvolvem software, mas a quem culpar? Normalmente, os clientes culpam os desenvolvedores, argumentando que práticas descuidadas levam a um software de baixa
qualidade. Os desenvolvedores argumentam que as datas de entrega são muito apertadas e a constante mudança nos requisitos levam a entrega de um software antes deles estarem completamente validados. Segundo Pressman (2011), os dois tem razão e é este o maior dos problemas.
Conforme Sommerville (2011, p. 456):
Algumas pessoas pensam que a qualidade de software por meio de processos prescritivos, baseados em padrões organizacionais e procedimentos de qualidade associados que verificam que esses padrões serão seguidos pela equipe de desenvolvimento de software. Seu argumento é que os padrões incorporam as boas práticas de engenharia de software e que segui-las levará a produtos de alta qualidade.
Além disso, Pressman (2011, p. 359) afirma que:
Qualidade de projeto refere-se às características que os projetistas especificam para um produto. A qualidade dos matérias, as tolerâncias e as especificações de desempenho, todos são fatores que contribuem para a qualidade de um projeto. Quanto mais matérias de alta qualidade forem usados, tolerâncias mais rígidas e níveis de desempenho maiores forem especificados, a qualidade de projeto de um produto aumentará se o produto for fabricado de acordo com essas especificações.
A norma NBR 13596, publicada em agosto de 1996, define que qualidade é a totalidade das características de uma entidade, que lhe confere a capacidade de satisfazer as necessidades explicitas e implícitas. (ABNT, 1996). Essas necessidades explícitas podem ser definidas como as condições e os objetivos propostos pelas pessoas que produzem um determinado software, sendo então fatores relacionados à qualidade de desenvolvimento do produto e são percebidos só pelas pessoas encarregadas pelo desenvolvimento do produto. (MOLINARI, 2003).
Já, as necessidades implícitas são subjetivas aos usuários, em muitos casos, são chamadas também de fatores externos e podem ser percebidas por desenvolvedores e/ou usuários. As necessidades implícitas devem permitir que usuários atinjam metas com efetividade, produtividade, satisfação e segurança em um contexto especificado pelos usuários. (MOLINARI, 2003).
A qualidade de software não é um ponto fácil de atingir, pode ser muito difícil concluir se um sistema de software cumpre ou não suas especificações. Essas dificuldades levam a três causas. (SOMMERVILLE, 2011).
1. É difícil escrever especificações de software completas e precisas. Em muitos casos, clientes e desenvolvedores podem interpretar requisitos de formas diferentes e pode ser muito difícil chegar a um consenso se o software cumpre ou não suas especificações.
2. Normalmente, as especificações de negócio integram requisitos de várias classes stakeholderes. “Esses requisitos são, inevitavelmente, um compromisso e podem não incluir os requisitos de todos os grupos de stakeholderes“. (SOMMERVILLE, 2011, p. 457). Esses stakeholderes excluídos podem interpretar o sistema como um sistema de baixa qualidade, mesmo que ele tenha todos os requisitos acordados.
3. Torna-se impossível classificar determinadas características de qualidade diretamente (exemplo, manutenibilidade), assim, elas não podem ser especificadas de forma não ambígua.
Muitos desenvolvedores de software, com um pouco mais de experiência, sabem que softwares com alta qualidade são um objetivo importante. Mas como definir a qualidade de software? (PRESSMAN, 2011).
A avaliação de qualidade de um software é um processo normalmente subjetivo, em que uma equipe responsável pelo gerenciamento de qualidade precisa usar seu julgamento para decidir se foi alcançado um nível de qualidade aceitável. Isso é necessário para saber se um software é adequado para sua finalidade ou não. (SOMMERVILLE, 2011).
Em um sentido mais geral, a qualidade de software pode ser definida como: “uma gestão de qualidade efetiva aplicada de modo a criar um produto útil que forneça valor mensurável para aqueles que o produzem e para aqueles que o utilizam”. (PRESSMAN, 2011, p.360).
Segundo Pressman, a qualidade de software está ligada a três pontos importantes, que são (PRESSMAN, 2011):
1. uma gestão de qualidade efetiva gera a infraestrutura que dá auxílio a qualquer tentativa de construir um produto de software de alta qualidade. “Os aspectos administrativos do processo criam mecanismos de controle e equilíbrio de poderes que ajudam a evitar o caos no projeto – um fator chave para uma qualidade inadequada”. (PRESSMAN, 2011, p.360). Além disso, as atividades de gerenciamento de mudanças e as revisões técnicas têm muito a ver com a qualidade;
2. um produto com boa qualidade deve fornecer o conteúdo, as funções e os recursos finais que o usuário deseja. Além disso, e não menos importante, não deve fornecer erros e deve fornecer confiabilidade. Outro ponto muito importante é que esse produto satisfaça um conjunto de requisitos implícitos (exemplo, facilidade de uso) que se espera de todos os softwares de alta qualidade;
3. ao agregar valor tanto para o fabricante quanto para o usuário de um produto de software, esse software de qualidade traz benefícios para todos, tanto para empresa de software quanto para os usuários finais. A empresa fabricante do software ganha valor no mercado. Pelo fato de ter um software de alta qualidade, além disso, ela tem menos custos com manutenção, suporte a clientes e menos correções de erros. Esses fatores contribuem para que os engenheiros de software possam se focar na criação de novas aplicações e fiquem menos tempo em manutenções. A comunidade de usuários também ganha valor agregado, ajudando a agilizar algum processo de negócio. O resultado final, segundo Pressman (2011, p. 360), é:
(1) maior receita gerada pelo produto de software, (2) maior rentabilidade quando uma aplicação suporta um processo de negócio, e/ou (3) maior disponibilidade de informações cruciais para o negócio.
Nesse sentido, segundo Sommerville (2011, p. 457), o processo de qualidade deve sempre responder as perguntas sobre as características do sistema para buscar uma maior qualidade de software:
1. Durante o processo de desenvolvimento, os padrões de programação e documentação foram seguidos?
2. O software foi devidamente testado?
3. O software é suficientemente confiável para ser colocado em uso? 4. O desempenho do software é aceitável para uso normal?
5. O software é útil?
6. O software é bem estruturado e compreensível?
Seguindo essas seis perguntas, é possível entender que a qualidade de software não está somente ligada ao software. Ela também está ligada ao processo de desenvolvimento,
partindo dos pré-requisitos de um software até sua entrega, participando de todo o ciclo de vida de um projeto de desenvolvimento de um software. (MOLINARI, 2003).
Por essa razão, é necessário ter um conjunto de fatores de qualidade. Esses fatores podem ser classificados em duas grandes categorias: Fatores medidos diretamente e fatores medidos indiretamente. Um exemplo do direto pode ser possíveis defeitos revelados nos testes, já dos indiretos, a usabilidade e a facilidade de manutenção podem ser um exemplo. Para os dois fatores devem ocorrer medições, fazendo uma comparação com o software e algum dado para uma indicação de qualidade. (PRESSMAN, 2011).
Nesse sentido, a qualidade de um software está diretamente relacionada à qualidade do processo de desenvolvimento de um software. Bons processos levam a um software de melhor qualidade, junto com o gerenciamento e a melhoria de qualidade de processo, os softwares tendem a ter menos defeitos. Mas, em alguns casos, a criatividade no processo de software e a padronização de processos podem inibir a criatividade, o que pode gerar um software com menos qualidade. (SOMMERVILLE, 2011).
2.1.1 Qualidade de Processo
O início de um processo de qualidade começa pela escolha de ferramentas e métodos utilizados para validações voltados para uma determinada empresa. Depois dos padrões serem selecionados, processos específicos de projeto devem ser definidos para monitorar o uso de padrões e validar se eles foram seguidos. (SOMMERVILLE, 2011).
A qualidade de processo faz com que tarefas, antes realizadas somente em algumas situações, comecem a ser seguidas, estimulando um padrão, deixando um processo de desenvolvimento de software mais legível e mais claro para todos os envolvidos. Esses padrões são importantes por três motivos, que são: capturar a sabedoria, fornecer um framework para a definição de qualidade para uma organização e “ajudar a continuidade do trabalho realizado por uma pessoa, quando retomado e iniciado por outra”. (SOMMERVILLE, 2011, p. 459). A figura 2 representa um workflow da qualidade de processo.
Figura 1 - Workflow de qualidade de processo
Fonte: Sommerville (2011, p. 458).
A sabedoria e o conhecimento são muito valiosos para uma organização. Eles são baseados no conhecimento sobre a prática na melhor ação ou na mais adequada para uma empresa. Em muitos casos, esses conhecimentos são adquiridos na forma de tentativa e erro. (SOMMERVILLE, 2011).
Segundo Pezzé e Young (2008, p. 64), “o processo da qualidade deve ser estruturado visando à completude, à oportunidade e à relação custo-benefício”. A completude visa a que atividades apropriadas sejam planejadas para detectar cada classe e suas possíveis falhas. Oportunidades significa que as falhas são detectadas em tempo hábil, o que, na prática, serve para que possíveis falhas possam ser rastreadas o mais rápido possível. O custo deve ser considerado em relação ao ciclo de vida completo do produto, logo, o fator de muitos retrabalhos pode aumentar muito o ciclo de mudanças. (PEZZÉ e YOUNG, 2008).
Em muitos casos, atividades que normalmente seriam consideradas como pertencentes ao domínio da garantia e da melhoria da qualidade, isto é, atividades cujo principal objetivo é prevenir ou detectar falhas, interagem com outras atividades exercidas pelos membros de uma equipe de desenvolvimento de software. Um exemplo pode ser o projeto da arquitetura de um software, esse sistema tem um enorme impacto nas abordagens de testes de análises e podem mudar os seus custos. (PEZZÉ e YOUNG, 2008).
A garantia de padrões está altamente ligada à qualidade de processo. O IEEE1 e a ISO2 e outras instituições de padronizações produzem uma grande quantidade de padrões para a engenharia de software e os seus respectivos documentos. Esses padrões podem ser adotados por uma organização de engenharia de software ou solicitados pelo cliente ou outros
1 Site oficial da IEE: http://www.ieee.org/index.html 2 Site oficial da ISO: http://www.iso.org/iso/home.html
interessados. O papel do SQA (Software Quality Assurance ou garantia da qualidade de software) é garantir que padrões que tenham sido adotados sejam seguidos e que todos os artefatos e os produtos resultantes estejam de acordo com eles. (PRESSMAN, 2011).
Como existem diferentes tipos de software, tornam-se necessários também diferentes processos de desenvolvimento, portanto os padrões precisam ser adaptáveis. Não tem sentido prescrever um modo particular de trabalho, se ele não é adequado para um projeto ou para uma equipe de projeto. O gerente de projeto e o gerente de qualidade podem evitar problemas com padrões não apropriados com um planejamento de qualidade logo no início do projeto. Eles devem decidir que padrões podem ser seguidos sem alterações, quais devem ser modificados e quais devem ser descartados. Novos padrões também podem ser necessários, em detrimento dos requisitos do cliente e os requisitos do projeto. Todos esses processos contribuem para a qualidade final de um software. A qualidade de processo traz muitos benefícios e aumenta também a qualidade do produto de software. (PRESSMAN, 2011).
2.1.2 Qualidade de Produto
A qualidade de produto de software, na maioria das vezes, não é dada pelo produtor do software ao usuário final. Muitas vezes, o usuário não sabe como exigir essa qualidade ou mesmo não tem a intenção de exigi-la, isso ocorre porque alguns usuários ainda julgam difícil avaliar a qualidade de um software. (INTHURN, 2001).
Quando se fala sobre qualidade de produto, existe uma norma que a classifica e um processo brasileiro escrito. Uma representada pela ISO e outra pela MPS.BR. (INTHURN, 2001).
A ISO 9126 e a MPS.BR 25010 listam um conjunto de características que devem ser avaliadas para garantir que um produto de software tenha qualidade. (INTHURN, 2001).
Segundo Softex (2011, parte 4), essas características são: funcionalidade, confiabilidade, utilizabilidade, eficiência, manutenibilidade e portabilidade. Essas características podem ser definidas da seguinte forma:
Funcionalidade é a existência de um conjunto de funcionalidades que satisfaçam necessidades implícitas e explícitas, bem como suas propriedades específicas. Confiabilidade refere-se à capacidade de um software continuar com seu nível de desempenho sob condições
pré-estabelecidas. Utilizabilidade torna-se necessário ao esforço necessário para a utilização de um software, bem como a classificação desse uso. Eficiência está voltada para o nível de desempenho do software e a quantidade de recursos utilizados. Manutenibilidade refere-se ao esforço utilizado para dar manutenções em um software. E, por ultimo, portabilidade refere-se à facilidade de um software ser transferido de um ambiente para outro. (INTHURN, 2001).
A qualidade de produto não está somente ligada ao software. Entram nessa qualidade também padrões de documentação, como estrutura de documentos de requisitos, documentações de códigos-fontes e padrões de codificação. Todos esses itens contribuem para uma qualidade de produto ainda melhor. (SOMMERVILLE, 2011).
A validação de software visa à avaliação da qualidade do produto ou componente. Essa validação serve como uma confirmação por exame e fornecimento de evidências objetivas, de que os requisitos específicos para um determinado produto são atendidos. (SOFTEX, 2011 parte 4).
Em muitos casos, a validação de software está amplamente ligada à verificação de software, sendo que, muitas vezes, a validação e a verificação são executadas em conjunto, pois, às vezes, é difícil determinar quando uma termina e onde a outra começa. De um modo geral, pode-se dizer que o intuito da verificação é se preocupar em avaliar se o produto está sendo desenvolvido da maneira correta, enquanto a validação tem o intuito de avaliar se o produto está de acordo com o que o cliente solicitou. (SOFTEX, 2011).
2.1.3 Verificação e Validação
Segundo Pezzè e Young (2008, p. 39, 40):
Avaliar o grau em que um sistema de software realmente satisfaz seus requisitos, no sentido de atender às necessidades reais do usuário, é chamado de validação. A verificação é a checagem de uma implementação com as especificações.
É importante salientar que satisfazer requisitos não é a mesma coisa que estar conforme uma especificação de requisitos. Uma especificação pode ser entendida como uma declaração particular sobre um problema, que pode ou não atingir o objetivo esperado.
(PEZZÈ e YOUNG, 2008). O processo de verificação e validação pode ser visualizado na figura 3.
Figura 2 - Ilustração de validação e verificação
Fonte: Pezzè e Young (2008, p.41).
A verificação e a validação englobam uma ampla gama de atividades de SQA (software quality assurance). Entre elas, algumas podem ser: revisões técnicas, auditorias de qualidade de configuração, estudo de viabilidade, monitoramento de desempenho, simulação, revisão de documentação, revisões de bases de dados, análise de algoritmos, testes de desenvolvimento, testes de usabilidade, testes de aceitação, testes de instalação e testes de aceitação. (PRESSMAN, 2011).
As atividades de validação referem-se principalmente à especificação geral do sistema e ao código final. De uma maneira geral, a validação busca diferenças entre as necessidades reais e a especificação do sistema elaborada pela análise com o propósito de garantir que a especificação é uma referência adequada para construir um produto que atinja os objetivos estabelecidos. Com relação ao código final, a validação busca encontrar diferenças entre as demandas reais e o produto final, revelar eventuais falhas no processo de
desenvolvimento do sistema e garantir que o produto vá ao encontro daquilo que o usuário final deseja. (PEZZÈ e YOUNG, 2008).
Além de verificações que comparam dois ou mais artefatos, a verificação se foca na consistência interna e na boa formação do artefato. É possível determinar se uma especificação está mal formatada por ter inconsistência ou ser ambígua, ou porque não satisfaz outra regra de boa formatação imposta. (PEZZÈ e YOUNG, 2008).
A norma internacional ISO/IEC 12207 define que, nas atividades de desenvolvimento, a verificação refere-se ao processo de examinar o resultado de uma atividade para determinar os requisitos estabelecidos para a mesma atividade, enquanto a validação se refere ao processo de examinar um produto para determinar sua conformidade com as necessidades do usuário. Essa norma serve para garantir que a validação seja feita normalmente no final do produto sob condições de operação definidas, podendo também ser necessárias em fases anteriores do processo. (SOFTEX, 2011, parte 4).
Já as atividades de validação são normalmente executadas nas etapas iniciais e finais do processo de desenvolvimento de um produto, iniciando, geralmente, com as validações dos requisitos e finalizando com a validação do produto final no ambiente operacional. Como a validação se preocupa com o atendimento das necessidades do cliente e com os usuários do produto, é sempre recomendável que, quando possível, os usuários sejam envolvidos no processo de validação. (SOFTEX, 2011, parte 4).
Tradicionalmente, o teste de software pode ser considerado como uma parte do processo de validação. Depois que um software é terminado, o sistema é validado e testado para determinar suas funcionalidades e seu desempenho. Em muitos casos, a verificação também é incorporada pelos testes durante o desenvolvimento, sendo uma prática muito comum combinar a verificação com validação no processo de testes. (PEZZÈ e YOUNG, 2008).
2.1.4 Testes de Software
Durante um processo de desenvolvimento de um software, existem muitas atividades que visam à garantia da qualidade do produto. Entretanto, apesar de todas essas
atividades, falhas no produto final ainda podem existir. Nesse sentido, a etapa de testes que representa uma das atividades da garantia da qualidade se torna muito importante para a eliminação e identificação de falhas. (INTHURN, 2001).
Os testes têm como o principal objetivo encontrar erros, e um bom teste pode ser classificado como aquele que tem alta probabilidade de encontrar um erro. (PRESSMAN, 2011), ou, então, os testes podem ser usados para mostrar que um determinado programa faz aquilo a que foi proposto. (SOMMERVILLE, 2011).
Segundo Pressman (2011, p. 428):
Toda vez que um programa é executado, o cliente testa-o! Portanto, você tem que executar o programa antes que ele chegue ao cliente com o objetivo específico de encontrar e remover todos os erros. Para encontrar o maior número possível de erros, devem ser executados testes sistematicamente, e os casos de testes devem ser projetados usando técnicas disciplinadas.
Nesse sentido, não adianta se enganar, pois os erros sempre existiram. O que geralmente é feito é diminuir o risco de um erro ocorrer, e os testes servem para isso mesmo, para diminuir os riscos. Molinari (2003, p. 51) afirma que “quem diz que vai entregar uma aplicação sem “bugs” está mentindo ou tentando enganá-lo. Mais cedo ou mais tarde o “bug” aparece”.
Os testes só são executados quando o código correspondente já está disponível, mas as atividades de testes começam antes, assim que os artefatos necessários para projetar as especificações dos casos de testes estiverem disponíveis. Nesse sentido, os suítes de testes de aceitação e de sistema devem ser gerados anteriormente dos suítes de teste de integração e unitários, mesmo que eles sejam executados em ordem inversa. (PEZZÈ e YOUNG, 2008).
Como já dito, uma forma de realizar a validação é por meio de testes que demonstrem que um produto de software correto está sendo desenvolvido. O teste é o método mais usado para buscar uma maior qualidade em um produto de software. (SOFTEX, 2011).
Entre os principais objetivos dos testes, o de demonstrar ao desenvolvedor e ao cliente que o software atende os requisitos, leva aos testes de validação, em que o objetivo é a confirmação de que o sistema se comporta da maneira esperada, usando um determinado conjunto de casos de testes que refletem o uso esperado do sistema. Já o objetivo de descobrir de como o software se comporta de maneira incorreta levam aos testes de defeitos. Os casos de testes que buscam os defeitos podem ser deliberadamente obscuros, e não há necessidade de refletir com precisão a maneira de que o sistema costuma ser usado. Durante os testes de
validação, é normal encontrar defeitos no software, durante o teste de defeito, alguns testes vão mostrar que o software corresponde aos seus requisitos. (SOMMERVILLE, 2011).
Projetar testes no início tem muitas vantagens. Os testes são especificados independentes de seus códigos, e as especificações correspondentes ao software estão bem claras na cabeça dos analistas e desenvolvedores, facilitando a revisão no projeto de testes. Além disso, os casos de testes podem ajudar a encontrar inconformidades nas especificações. Com isso, as especificações já podem ser corrigidas logo no início, evitando que erros nas especificações se propaguem para estágios posteriores do desenvolvimento. (PEZZÈ e YOUNG, 2008).
Segundo Inthurn (2001, p. 53), “testes bem planejados são capazes de remover em média 60 % dos defeitos de um programa”. Quanto ao custo de alteração nos defeitos, após o desenvolvimento, pode-se afirmar que ele é muito maior do que se esses mesmos defeitos fossem rastreados e removidos em fases anteriores. (INTHURN, 2001).
As técnicas de testes podem ser classificadas basicamente em: funcional, estrutural e baseada em erros. A técnica funcional visa à seleção de casos de testes apoiada nas especificações de software, a técnica estrutural apoia-se principalmente na implementação, mais especificamente no fluxo de controle e nas informações de fluxos de dados. A técnica baseada em erros utiliza as informações de erros frequentes cometidos no desenvolvimento do software para derivar os requisitos de testes. (INTHURN, 2001).
Qualquer produto pode ser testado de duas maneiras: (1) conhecendo a função especificada no qual o produto foi projetado para realizar. (2) conhecendo o funcionamento interno de um produto. Podem ser feitos testes em que o sistema como um todo se encaixa. A primeira forma de teste usa uma visão que é conhecida como teste caixa-preta. Já, a segunda requer uma visão externa e é conhecida como teste caixa-branca. (PRESSMAN, 2011).
Conforme Pressman (2011, p. 431):
O teste caixa-preta faz referência a testes realizados na interface do software. Um teste caixa-preta examina alguns aspectos fundamentais de um sistema, com pouca preocupação em relação à estrutura lógica interna do software. O teste caixa-branca fundamenta-se em um exame rigoroso do detalhe procedimental. Os caminhos lógicos do software e as colaborações entre componentes são testados, exercitando conjuntos específicos de condições e/ou ciclos.
Na pratica, geralmente, o processo de teste envolve uma mistura de testes automatizados e testes manuais. No teste manual, um testador executa o programa com dados de testes e faz uma comparação com os resultados com suas expectativas. Em testes
automatizados, os testes ficam codificados em um programa que é executado sempre que for necessário. (SOMMERVILLE, 2011).
Nesse sentido, o uso de testes automatizados vem aumentando consideravelmente nos últimos anos. Entretanto, os testes nunca conseguiram ser totalmente automatizados, já que testes automáticos só podem avaliar se o software faz aquilo a que é proposto. (SOMMERVILLE, 2011).
2.1.4.1 Testes Automatizados
Muitos consultores especialistas em testes são a favor da automatização de testes. Eles estão em parte certos, porque existem muitos testes que são muito custosos para serem feitos de uma forma não automatizada. Imaginem um diretor de uma grande empresa alocar 50 pessoas para realizar um simples teste de carga em uma aplicação. Essa não é a melhor solução para este tipo de teste, contudo, também, existem testes que são melhores de se fazer de forma manual. (MOLINARI, 2003).
Uma boa forma de automatizar os testes é proceder de maneira incremental, priorizando os próximos passos baseados nas variações de impacto potencial, variações de maturidade, custos e aplicação de uma tecnologia e ajustando o processo dentro de uma organização. (PEZZÈ e YOUNG, 2008).
Os processos de automatização de testes devem ser elaborados com muito cuidado. As ferramentas de automação dos testes, bem como a definição do que será automatizado ou não, deve ter uma análise muito clara e real, porque, dependendo das técnicas definidas, o retorno do investimento pode ser positivo ou negativo. (MOLINARI, 2003).
As dificuldades e o custo que a automação dos testes variam são enormes, desde ferramentas simples de desenvolver até ferramentas que podem ter um enorme valor, mas são quase impossíveis pelo alto investimento. Portanto, devem-se balancear as dificuldades ou o custo da automação juntos com os potenciais benefícios, incluído o custo de treinamento e o custo de integração. (PEZZÈ e YOUNG, 2008).
Ainda que muito prestativos e bem-intencionados, os humanos são lentos e sujeitos a erros quando lidam com tarefas repetitivas. Em contrapartida, tarefas simples e
repetitivas normalmente são mais fáceis de automatizar, enquanto que julgamentos e soluções criativas de determinados problemas ficam fora do domínio da automação de testes. A automatização de partes repetitivas de uma tarefa não apenas reduz os custos de um projeto, mas melhora também a precisão. (PEZZÈ e YOUNG, 2008).
Para valer a pena à implementação de testes automatizados, existem algumas questões que são necessárias para validação se realmente essa é a melhor abordagem para se seguir. Elas são: Teste de regressão e de confirmação, testes de cargas, volumes e capacidade, a geração de testes de componente (unidade). Com todos esses testes, a melhor abordagem é a dos testes automatizados, economizando horas trabalhadas e ganhando mais eficiência. (MOLINARI, 2003).
2.1.4.1.1 Testes Unitários
Os testes unitários focalizam o esforço da verificação na menor unidade de um projeto de software, o componente ou módulo de um software. Trabalhando com as especificações do projeto no nível de componente, caminhos importantes são testados para rastrear erros dentro de do limite do módulo. Com isso, os testes automatizados dão ênfase para a lógica interna de processamento e para as estruturas de dados dentro de um componente, podendo ser conduzidos para diversos componentes. (PRESSMAN, 2011).
Quando os testes de componentes visam, também, a métodos e a objetos, esses testes devem fornecer uma cobertura de todas as características do objeto. Isso significa que os pontos, a seguir, devem ser validados: Testar todas as operações associadas a um objeto, definir e validar todos os atributos associados a um determinando objeto e colocar o objeto em todos os estados possíveis, que significa testar todos os eventos que possam mudar o objeto de estado. (SOMMERVILLE, 2011).
No desenvolvimento de software orientado a objetos, é relevante testar cada unidade, mas elas não precisam ser testadas de uma maneira sequencial. Não é necessário que um teste chegue ao fim, para que outro possa ser iniciado. Em muitos casos, podem ser executados testes unitários para verificação de estruturas internas das classes e no teste de integração, a interface e a troca de mensagens entre as classes. (INTHURN, 2001).
Dentro dos testes unitários, ainda existe um conceito importante de testes que são os testes de fronteiras. Segundo Pressman (2011, p. 408):
Erros frequentemente ocorrem quando o ésimo elemento de um conjunto n-dimensional é processado, quando a i-ésima repetição de um laço com i passadas é chamada, quando o valor máximo ou mínimo permitido é encontrado. Casos de testes que utilizam estrutura de dados, fluxo de controle e valores de dados logo abaixo, iguais, ou logo acima dos máximos e mínimos têm grande possibilidade de descobrir erros.
Sempre que possível, os testes unitários devem ser automatizados. Existem muitos frameworks que automatizam os testes unitários (como JUnit) para escrever e executar os testes de um programa. Com o auxilio desses frameworks, é possível executar todos os testes implementados e, por meio de alguma interface gráfica, avaliar o sucesso ou fracasso dos testes. Com isso, um conjunto inteiro de testes pode ser executado frequentemente em poucos segundos, sendo possível executar os testes cada vez que uma alteração é feita. (SOMMERVILLE, 2011).
Existem três etapas para a utilização dos testes unitários: Uma parte de configuração (entrada e saída de dados), uma fase de chamada (chamadas de métodos e objetos a serem testados) e uma parte de afirmação (em que são validados os resultados dos testes) para saber se o sistema se comportou da maneira correta. (SOMMERVILLE, 2011).
Os testes unitários normalmente são considerados como uma tarefa adicional para etapa de codificação. O início do projeto de testes unitários pode ocorrer antes de começar a codificação ou depois da geração do código fonte de um software, sendo necessário acoplar cada conjunto de testes com o resultado esperado. (PRESSMAN, 2011).
Em alguns casos, o objeto que será testado pode ter dependências com outros objetos que podem não ter sido escritos ou atrasam o processo de testes, quando são usados. Nesses casos, uma decisão se usar mock object pode ser ideal. “Mock object são objetos com a mesma interface que os objetos externos usados para simular sua funcionalidade”. (SOMMERVILLE, 2011, p. 149). Nesse sentido, um mock object pode ser usado para simular um banco de dados, que pode ter alguns itens organizados em um vetor, deixando um acesso rápido às informações sem os overheads de chamada de banco de dados e acesso a disco. (SOMMERVILLE, 2011).
Os testes unitários ficam simplificados quando componentes com alta coesão são projetados. Quanto menos funções um componente tiver, o seu número de casos de teste é reduzido e os erros podem ser mais facilmente previstos e descobertos. (PRESSMAN, 2011).
2.2 GERENCIAMENTO DE CONFIGURAÇÃO
Os sistemas de software geralmente mudam em todas as etapas de seu ciclo de vida. Bugs são descobertos e precisam ser corrigidos, requisitos de sistemas mudam e, com eles, tornam-se necessárias determinadas mudanças em uma nova versão do sistema. São liberadas novas versões de hardware e novas plataformas de sistema e, com isso, tornam-se necessárias certas mudanças para adaptar o sistema, concorrentes agregam novas funcionalidades ao sistema, e você também precisa agregar essas funcionalidades para não perder mercado. Nesse contexto, a maioria dos sistemas pode ser pensada em um conjunto de versões de modelo/produto que compõem um sistema sendo que cada uma delas necessita ser mantida e gerenciada. (SOMMERVILLE, 2011).
Torna-se necessário gerenciar os sistemas em evolução. Sem esse gerenciamento, é fácil perder o controle de quais alterações ou versões de componentes foram introduzidas em cada versão de um sistema. Pode haver várias versões em desenvolvimento e/ou em uso ao mesmo tempo. Se não existir um processo de gerenciamento de configuração claro e efetivo, podem-se ter problemas com desperdício de tempo, atualizando versões erradas e disponibilizá-las para clientes ou até mesmo esquecer onde está armazenado o código de uma versão específica de um sistema ou componente. (SOMMERVILLE, 2011).
A gerência de configuração de software é uma atividade do tipo “guarda-chuva”, aplicada através de toda a gestão de qualidade. Como as alterações ocorrem em qualquer instante do ciclo de vida de um sistema, as atividades de gerenciamento de configuração servem para: identificar as alterações, controlar as alterações, assegurar que as alterações estejam implementadas de forma correta e relatar as alterações a outros interessados. (PRESSMAN, 2011).
Esse gerenciamento é útil para todos os projetos individuais e projetos com uma equipe. Em projetos individuais, é fácil de uma pessoa esquecer quais mudanças foram feitas. Já, em projetos com uma equipe o gerenciamento de configuração, é essencial, pelo fato de vários desenvolvedores trabalharem ao mesmo tempo alterando muitos artefatos do projeto. Com o mercado em evolução, cada vez mais as equipes trabalham em forma distribuída com membros em diferentes locais. O uso de um processo de gerência de configuração garante que equipes tenham acesso a informações sobre os sistemas que estão em desenvolvimento e não interfiram no trabalho umas de outras. (SOMMERVILLE, 2011).
É notório que a gerência de configuração é muito importante quando tentamos resolver alguns problemas baseado na experiência das pessoas. Nesse ponto, podemos parar e refletir se o que estamos fazendo é mesmo a melhor opção a ser tomada. Com um modelo de gerenciamento de configuração definido, é possível se basear no modelo e não na experiência das pessoas. (MOLINARI, 2007).
Na gerência de configuração, existem várias perspectivas dentro de uma organização. (MOLINARI, 2007), como:
perspectiva humana: Muitas pessoas podem ser afetadas diretamente ou indiretamente devido a regras e obrigações dos envolvidos;
perspectiva do produto: A gerência de configuração é exercida em função do produto. Como cada vez mais temos produtos mais complexos e algumas vezes temos subprodutos, pode cada produto ter uma ênfase em uma distribuição ou em outras;
perspectiva do projeto: Como trabalhos de desenvolvimento de um projeto sempre tem manutenção e podem existir mais de um projeto, a gerência de configuração entra no clico de vida dos componentes de software, armazenando os artefatos que foram corrigidos, alterados ou desenvolvidos;
perspectiva de processo: Nessa perspectiva, podem ser usados pontos para a melhoria do processo, unindo informações que antes estavam soltas. Mas é importante resaltar que, para ser aplicada nesse ponto, a melhoria do processo deve ser constante, sempre evoluindo com os novos processos introduzidos dentro de uma equipe.
Dentro da perspectiva do projeto, o gerenciamento de configuração tem quatro atividades principais. Gerenciamento de mudanças, gerenciamento de versões, construção de do sistema e gerenciamento de releses. Nesse sentido, o gerenciamento de mudanças tem como tarefas principais, o acompanhamento de solicitações dos clientes e desenvolvedores por mudanças no software, analisar o impacto de possíveis mudanças e quando exatamente elas devem ser desenvolvidas e os custos das mesmas. (PRESSMAN, 2011).
O gerenciamento de versões serve para manter o acompanhamento de várias versões de componentes de software e assegurar que as mudanças nos componentes não interfiram em outros componentes. (MOLINARI, 2007).
Já, a construção do sistema é um processo de junção de componentes de um software, dados e bibliotecas. E, em seguida, esses artefatos são compilados e uma versão executável de um software é gerada. (SOMMERVILLE, 2011).
Complementado, Sommerville (2011, p.476) explica que o gerenciamento de releses “envolve a preparação de software para o release externo e manter o acompanhamento das versões de sistema que foram liberadas para uso do cliente“.
Os objetivos do gerenciamento de configuração são garantir que sejam seguidos os procedimentos e políticas para criar, alterar e testar o código estabelecido pelo projeto. Além disso, é papel dele tornar acessível todas as informações do projeto, em muitos casos, o gerente de configuração coleta dados estatísticos sobre os componentes do sistema de software, como informações sobre determinados componentes do sistema que estão com algum tipo de problema. (PRESSMAN, 2011).
Em muitas empresas, além de serem incluídos todos os artefatos de um sistema sob o controle da gerência de configuração, também são colocadas sob a gerência de configuração ferramentas de software, tais como: versões específicas de editores, compiladores, browsers e outras ferramentas que podem ser “congeladas” como parte da configuração de software. Como essas ferramentas foram usadas para produzir código-fonte, dados e documentação, elas precisam estar disponíveis, quando alterações forem feitas na configuração de software. Embora pouco provável, é possível que novas versões de ferramentas possam produzir resultados diferentes daqueles atingidos com a versão original. Por essas razões, ferramentas, assim como os softwares que elas ajudam a produzir, podem ser usadas como parte de um processo bem específico da gerência de configuração. (PRESSMAN, 2011).
Como é possível avaliar, o gerenciamento de configuração lida com um grande volume de informações e ferramentas. Dessa forma, muitas ferramentas de gerenciamento de configuração foram desenvolvidas para dar suporte a esses processos. Essas ferramentas vão desde simples até conjuntos mais complexos. As mais simples são ferramentas de suporte a uma tarefa única do gerenciamento de configuração, tal como acompanhamento de bugs. As mais complexas podem ser bem caras e podem ser integradas a todas as atividades de gerenciamento de configuração. (SOMMERVILLE, 2011).
Muitas vezes, o gerenciamento de configuração pode ser considerado parte do gerenciamento de qualidade de software, como a mesma pessoa exercendo as responsabilidades de gerenciamento de qualidade e gerenciamento de configuração. Quando a equipe de desenvolvimento entrega uma versão, essa versão é repassada a equipe de garantia
da qualidade. A equipe de qualidade verifica se a qualidade do sistema é aceitável, se assim for, torna-se um sistema controlado, que faz com que o sistema fique controlado e que todas as mudanças no sistema precisam ser acordadas e registradas antes de serem introduzidas em uma nova versão, sendo também necessário o gerenciamento destas versões. (SOMMERVILLE, 2011).
2.2.1 Gerenciamento de Versões
O gerenciamento de versões é a união de procedimentos e ferramentas para gerenciar diferentes versões dos artefatos criados durante o processo de criação de um software. Um sistema de controle de versões está diretamente ligado com três recursos principais:
Banco de dados do projeto (repositório): responsável em armazenar todos os artefatos de configuração relevantes.
Recurso de gestão de versão: Este recurso é utilizado para armazenar todas as versões de um artefato de configuração. Com ele é possível construir uma versão usando as diferenças das versões anteriores.
Construção: Uma facilidade de construção que permite coletar todos os artefatos de configuração necessários e ajudar a construção de uma versão de software específica. (PRESSMAN, 2011).
Com o gerenciamento, atinge-se a garantia que de que alterações realizadas por diferentes desenvolvedores não interfiram em uma versão ou em outras. Portanto, podemos entender o gerenciamento de versões como um processo de gerenciamento de codelines e baselines. (SOMMERVILLE, 2011).
Uma codeline pode ser definida por uma sequência de versões de código-fonte com versões posteriores na sequência de versões anteriores. Em muitos casos, as codelines são mais usadas para componentes de sistemas, existindo, então, diferentes versões de cada componente de um sistema. (SOMMERVILLE, 2011).
Baseline é um termo usado para a definição de um sistema específico. Em uma baseline, temos a versão específica de cada componente incluída no sistema, junto com
arquivos de configuração, especificações de bibliotecas usadas entre outros artefatos, dependendo do workflow do sistema. As baselines também são muito importantes, porque, muitas vezes, precisamos recriar uma versão específica de um sistema completo, usando-a para corrigir um bug, ocasionando em uma versão específica de um determinado cliente. (SOMMERVILLE, 2011). A figura 3 mostra um exemplo de branch e suas ramificações. Tendo sempre uma versão de um determinado software em três estados. Desenvolvimento, teste e produção.
Figura 3 - Imagem com a definição de Baseline e Branches
Fonte: (Seapine Software, 2012), tradução nossa.
Durante as últimas décadas, foram propostas muitas abordagens automatizadas para o gerenciamento de versões. “A diferença principal entre as abordagens é a sofisticação dos atributos usados para construir versões específicas e variantes de um sistema e os mecanismos do processo de construção”. (PRESSMAN, 2011, p. 523). Para o suporte da gerência de versões, podemos usar sempre as ferramentas de gerenciamento de versões. Essas ferramentas servem para identificar, armazenar e controlar acesso a diferentes versões de componentes de um sistema. (SOMMERVILLE, 2011).
Ainda, segundo Sommerville (2011, p. 483), “Quando foram desenvolvidos os sistemas de gerenciamento de versões, o gerenciamento de armazenamento foi uma de suas funções mais importantes”. Os recursos de gerenciamento de armazenamento em um sistema de controle de versões diminuem o espaço utilizado em um disco rígido. Isso porque, quando uma nova versão é criada, o sistema cria um “delta” (uma lista de diferenças), entre a versão
mais nova e a mais antiga. Normalmente, esses deltas são armazenados como uma lista de linhas alteradas, e, ao aplicadas, uma versão de componente pode ser criada a partir de outro. Eles também ajudam a definir como recriar versões anteriores de sistema. (SOMMERVILLE, 2011).
Para apoiar o desenvolvimento independente sem interferência, os sistemas de gerenciamento de versões usam um espaço de trabalho privado e o conceito de um repositório público. Os desenvolvedores fazem check-out de componentes de um projeto de um repositório público em seu espaço de trabalho privado e, assim, podem mudá-los como acharem melhor, logo que as mudanças forem finalizadas, eles fazem check-in dos componentes para o repositório. O sistema de gerenciamento de versões também dará garantia que, ao registrar uma modificação em um componente, serão atribuídos identificadores de versão diferentes para diferentes versões, as quais são armazenadas separadamente. (SOMMERVILLE, 2011).
Uma consequência do desenvolvimento independente do mesmo componente é que codelines podem ser subdivididas. Ao invés de uma sequência linear de versões que refletem as mudanças para o componente ao longo do tempo, podem haver várias versões independentes. Isto se torna normal no desenvolvimento de sistemas, diferentes desenvolvedores trabalhando independentemente em diferentes versões do código-fonte e fazem mudanças de formas diferentes. (SOMMERVILLE, 2011).
Em alguns momentos, pode ser necessário fundir ramificações de codelines para a criação de novas versões de um componente que inclui todas as mudanças realizadas. Se as mudanças feitas envolverem partes distintas do código-fonte, as versões de componentes poderão ser fundidas automaticamente pelo sistema de gerenciamento de versões, por meio da combinação dos deltas que se aplicam ao código-fonte. Frequentemente, existem sobreposições entre as mudanças feitas, e elas podem interferir umas nas outras. Os desenvolvedores devem, se existem conflitos, modificar as mudanças para que essas se tornem compatíveis. O gerenciamento de versões é muito importante para a construção de sistema, pode ser feito com versões específicas ou com a versão principal. (MOLINARI, 2007).