A importância da qualidade interna

A primeira vez que percebi o quanto a qualidade interna é importante, foi quando li o livro Scrum e XP direto das Trincheiras. Nele o Henrik Kniberg destaca que a qualidade interna do sistema é mais importante que a qualidade externa, tanto que ela é de responsabilidade da equipe e nunca (quase nunca) negocíavel com os clientes. E realmente é difícil discordar, uma vez que a qualidade interna irá acabar refletindo na qualidade externa do sistema, tanto que segundo o próprio Henrik: “[…] um sistema com baixa qualidade interna raramente terá uma qualidade externa alta.”

Mas qual a diferença entre qualidade interna e externa?

Em suma, qualidade interna é o sistema visto da perspectiva técnica, enquanto a qualidade externa é a visão do sistema, da perspectiva funcional.

Uma analogia seria a de uma montagem de um computador, você pode montar um computador com peças de vários fabricantes, e para o usuário pouco importará se a placa mãe é uma Asus, ou uma PCChips. O que o usuário verá será a qualidade externa, se o gabinete tem um design atraente se o computador não trava, essas coisas. Ele pouco irá importar se a memória RAM é Kingston ou não. O que importa na perspectiva funcional é realmente o funcionamento do computador e não como ele foi montado.

O que ocorre muito, é que há uma forte tendência no desenvolvimento do sistema ser guiado pelo “funcionou”, sendo que o “funcionou” pode ser um estado ainda crú da implementação da funcionalidade.

Monalisa

Citei a Monalisa no post anterior, desta vez ela será útil para nós, para entender como o processo de desenvolvimento de um software, é muito mais próximo do processo de pintura de um quadro, do que de um processo de construção civil.

Pesquisando na Internet encontrei informações de que a Monalisa foi pintada entre 1503-1514. Nesse período de mais de 10 anos, boa parte do tempo investido no quadro, foi em alterações técnicas, a base sempre foi permanecida.

Em outras palavras, podemos dizer que Leonardo Da Vinci levou 11 anos para finalizar o seu projeto, e boa parte do tempo, foi investido na manutenção do quadro, realizando refatorações e correções de bugs.

Uma característica que suponho que seja comum no processo de pintura de um quadro, principalmente quando ele é uma demanda, é a mudança constante. E mudança é uma das poucas certezas que temos no desenvolvimento de software, afinal um bom software está “sempre” em constante evolução/melhoria e quanto mais fácil for inserir mudanças no software, melhor será.

Mudar software é mais difícil do que mudar hardware

Vamos fazer uma breve viagem no tempo, o ano é 1946 e você está de frente ao ENIAC (foto abaixo). Se você perguntar para a pessoa na foto: o que é mais fácil mudar, o hardware ou o software? Ele com certeza, irá responder que é o hardware, e ainda irá achar a sua pergunta estúpida.

Agora voltando a 2010. O que é mais difícil, mudar o software ou o hardware?

Não há dúvidas que o software, não é? Hoje obter harware é MUITO fácil e barato, comparado a 1946. E com as VPSs da vida, ficou fácil obter hardware e uma ótima infraestrutura, você nem precisa sair de casa para ter o seu servidor rodando.

Monalisa, ENIAC, computação em nuvem e qualidade interna

Onde eu quero chegar com tudo isso?

Acredito que ficou claro que um dos grandes desafios para se desenvolver um software é conseguir mudar ele com o menor esforço necessário, mantendo o seu bom funcionamento. Costumo até dizer, que desenvolver software é fácil, comparado a manter o software.

Mas eu estou errado, pois desenvolver o software deveria ser mais difícil do que manter ele. Porém, seja por motivos externos (mudança frequente/drásticas de funcionalidades pelo cliente) e/ou motivos internos (pouca cobertura de testes, design fraco, falhas de comunicação, etc), manter o software acabou se tornando um tarefa mais difícil, do que a criação dele.

Voltando ao exemplo da Monalisa, vimos que Leonardo Da Vinci passou boa parte do tempo fazendo correções e melhorias no quadro, porém a sua essência foi mantida. Supunho que ele tenha feito um bom “design”, que permitiu inserir as correções e melhorias sem ter enfrentado maiores problemas.

O caso do ENIAC é interessante, pois mostra como as coisas mudaram MUITO do início da computação até hoje. Naquela época, e por um bom tempo, o hardware era o mais valorizado. Já hoje o software passou a ser o mais valorizado. E se antes os softwares eram escritos em cartões perfurados e pouquíssimas pessoas eram capazes de desenvolver software, hoje escrevemos software em linguagens quase naturais e conseguimos aprender a “desenvolver” por meio da Internet e de graça.

E a qualidade interna é peça fundamental para podermos conseguir alterar o código de forma “indolor”. E essa é apenas uma das vantagens que desenvolver software com uma boa qualidade interna traz. E vamos concentrar nela no próximo tópico.

Qualidade Interna

Qualidade interna também poderia ser traduzida em “fazer a coisa da forma certa”. Porém, essa tradução é muito simples e faz parecer que obter qualidade interna é fácil. Afinal seria só saber como fazer a “coisa” da forma certa, não é mesmo?

No entanto, há várias formas de fazer da forma certa no mundo do desenvolvimento de software. Por isso, uma das tarefas do desenvolvedor é fazer escolhas, e serão essas escolhas que irão influenciar diretamente a qualidade interna do software.

Os retornos com o investimento em qualidade interna ocorrem a médio e longo prazo, por causa disso, muitos acabam fazendo as escolhas “certas” a curto prazo, mas esquecem de avaliar o impacto que elas terão a médio e longo prazo.

E uma vez que escolhemos o caminho mais fácil, por exemplo adicionar mais um if, para atender uma alteração que o cliente pediu, ao invés, de extrair o comportamento para outro método, a tendência é acabar sempre escolhendo o caminho mais fácil.

Esse hábito, acaba sendo passado para os outros é acaba virando uma “cultura”. E aí, o caminho fácil será sempre tomado, e a possibilidade de tomar outras direções poderá nem passar pela cabeça mais. Sendo que essas direções diferentes, muitas vezes não representam um caminho difícil (ex.: escrever testes unitários), mas a mudança em si, é a parte difícil.

Desta forma, a qualidade interna acaba sendo colocada de escanteio. Porém, ao longo do desenvolvimento irão aparecer os sinais de que ela está muito baixa. Por exemplo: lançar uma nova versão demora cada vez mais tempo.

Como Obter Qualidade Interna

Algumas ações podem ajudar a desenvolvermos um software com uma boa qualidade interna:

  • Refatoração: alterar o código sem alterar o seu comportamento, focando na melhoria do código para favorecer a manutenibilidade dele;
  • Conhecer e utilizar boas práticas: princípios como o SOLID, ajudam a resolver os problemas com menos ruído e com soluções que favorecem a manutenção do software;
  • Comunicação: uma boa comunicação é essencial para o desenvolvimento do software, tanto externa (cliente), como interna (equipe). Muitos bugs acabam sendo inseridos e códigos duplicados, simplesmente porque houve falha na comunicação;
  • Estressar as soluções: geralmente, costumamos implementar a primeira solução que nos vem na cabeça, porém esquecemos que a primeira solução costuma não ser a melhor, por isso é importante pensar em outras formas de solucionar o mesmo problema e/ou conversar com alguém sobre;
  • Aprendizado contínuo: é importante estar sempre nos aperfeiçoando, se você for olhar algo que fez há 6 meses atrás e achou que não tem nada a ser melhorado, é sinal que você não aprendeu muito nos últimos 6 meses;
  • Saber quando parar: saber o momento de parar de ficar refatorando o código, é tão importante quanto saber quando é preciso melhorar ele, objetive a perfeição, mas não fique cego por ela;
  • Valorize o seu tempo: a vida é muito curta para ficar gastando tempo tentando entender aquele método com mais de 30 linhas que você escreveu há 3 meses atrás, ou ficar corrigindo bugs que poderiam ter sido encontrados antes com testes. Só nestes momentos, que você realmente percebe, o quanto a qualidade interna é importante;
  • Testes: por último e não menos importante, escreva testes. Além deles auxiliarem você a pensar melhor sobre as funcionalidades (se você usar TDD), eles irão te dá a tranquilidade necessária para refatorar o código. Afinal, refatorar sem testes, é algo muito difícil e arriscado, e isso incentiva a não refatoração e por consequência a uma baixa qualidade interna, portanto, escrever testes é fundamental para obter uma boa qualidade interna.

Conclusão

Enquanto a qualidade externa é a percepção do cliente para o software, a interna é a percepção dos desenvolvedores em relação a ele.

Devemos nos preocupar em manter uma boa qualidade interna, pois ela é essencial para a manutenção do software, e em cenários onde há entrega contínua do software (ex.: SaaS), a qualidade interna acabará sendo uma diferença competitiva. Afinal, uma das únicas certezas que temos no desenvolvimento de software, é que haverá mudanças, portanto, conseguindo reagir à tempo a elas, é fundamental para conseguir atender as demandas.

Os testes mais uma vez, representam um papel importante, pois é através deles que teremos a segurança necessária para refatorar o nosso código, implementar as alterações e novas funcionalidades.

Como anda a qualidade interna dos projetos que você está participando? A equipe tem consciência da sua importância?

Fique por dentro das novidades, assine o feed do QualidadeBR.

6º Encontro do Guru-SP – Eu fui!

Em pleno sabadão, num dia lindo acordo antes das 07:00, e não é para ir para a praia ou coisa do tipo, e sim para ir ao 6º Encontro do Guru-SP. 😀

Mas que “diacho” de encontro é esse Fabrício? Você foi consultar um guru espiritual?

Guru Ram Das, o 4º Guru da religião Sikh

Não, não (rsrs). O Guru-SP é esse daqui:

GURU SP

Hmmm… agora entendi. Mas o que você foi fazer num encontro de usuários de Ruby? Você programa em Ruby?

Não (mas depois de hoje fiquei com mais vontade ainda de aprender).

Um dos motivos para ter ido ao encontro foi o tema “Testes Automatizados” dele. Não tem jeito, colocar a palavra “teste” no tema de um evento, é mais efetivo do que falar que vai ter coffee break, para me fazer participar.

rsrs… que atitude nerd, perder um dia lindo desse, para ir num evento só por causa que vai falar sobre testes.

Que isso, olha o preconceito. Não é todo dia que você tem a oportunidade de participar de um evento sobre testes, onde que ia falar não atua na área de Teste de Software ou QA, e sim o pessoal do “lado negro da força” (“brincadeira minha, não é falando mal!”).

Interessante mesmo! Quem organizou o evento?

O 6º Encontro do Guro-SP foi organizado pelo Rafael Rosa, com o apoio da GoNow (local do encontro), Voice Technology (empresa na qual trabalho), O’Reilly e Ruby Inside Brasil, além é claro do Grupo de Usuário Ruby de SP.

E como foi o formato do encontro?

Foi no formato de mesa redonda (muito bom!), o pessoal da mesa ia falando sobre vários temas, que foram votados antes pelo pessoal que participou do encontro. Os debatedores foram:

  • Anderson Leite
  • Cássio Marques
  • Diego Carrion (não pode comparecer)
  • Fabio Kung (não pode comparecer)
  • Jorge Diz (o Jorge será o palestrante do 6º Encontro Mensal da ALATS-SP, a ser realizado nessa quarta-feira)
  • Ricardo Yasuda
  • Thiago Scalone

E o encontro foi dividido em duas partes, a primeira estimado das 10:00 ao 12:00 e a segunda das 12:30 às 15:00.

Da hora, a primeira parte como foi?

Ela começou com quase uma hora de atraso, com o Rafael Rosa falando sobre o encontro e como seria feito esse. Logo após, o pessoal já começou a “descer a lenha” falando sobre “Por que testar”, e pude perceber que a galera é bem comprometida como a realização dos testes, eles levam a sério mesmo e entendem as razões de porque testar.

Os debatedores também contaram experiências que tiveram fazendo BDD com o Cucumber e realizando testes de interface com o Selenium, por exemplo. Esse foi um ponto muito positivo do evento, ficou claro que os debatedores fazem o que eles falam, e puderam compartilhar experiências bem interessantes com o público. E a interação do público foi muito boa também, várias pessoas contaram os cenários que vivem, e também algumas dificuldades que tem em realizar os testes:

  • Tempo: projetos com prazos para ontem. Na minha opinião, realizar testes, principalmente na fase de desenvolvimento é uma prática que gera efeitos não tão bons a curto prazo, mas que a médio e longo prazo, se mostra essencial! Porém, como vivemos numa geração imediatista, muitas vezes as pessoas tem dificuldade em entender isso.
  • Complexidade: a criação de testes em sistemas complexos é um desafio maior ainda, às vezes pode ser mais difícil do que a própria implementação.
  • Sistemas legados: se dá uma manutenção em um sistema legado já é uma missão de embrulhar o estômago, imagine só criar testes para ele. Uma solução legal, comentada pelo pessoal e colocada em prática é realizar testes em nível de sistema, utilizando o Selenium por exemplo.

O Jorge Diz lembrou que a área de Teste de Software, costuma vir no reboque quando se usa metodologias frágeis (tradicionais). Mas usando metodologias ágeis o Teste de Software é incentivado, as novas técnicas já trazem na sua essência o pensamento de testar. Aliás, um exemplo disso é o uso de programação em par, onde uma pessoa já está revisando o código (lembrando que revisar é uma forma de testar).

Sobre o uso de BDD e TDD, o Anderson Leite disse que antes de partir para o uso delas, as pessoas precisam primeiro adquirir o hábito e prática de testar, só depois que já tiverem maduras podem começar a usar o BDD e TDD.

O Cássio Marques contou um pouco da sua experiência com linguagens de comparação, comparando no quesito de facilidade de testar. E disse que escrever testes em C e C++ é bem difícil, em Java também é meio enrolado. Já em Ruby é bem mais fácil. Podemos dizer que Ruby tem uma melhor “testabilidade”, que as outras, ou seja, se você é desenvolvedor Ruby e não testa, então você tem uma desculpa a menos para usar. 🙂

Um ponto importante discutido foi que se você testa, você não pode se dar ao luxo de deixar de testar uma funcionalidade, pois poderá resultar na velha história da janela quebrada.

Para terminar a primeira parte, houve uma demonstração do uso do Cucumber pelo Anderson. A minha primeira impressão foi que pareceu mágica o que ele fez (rsrs), ele escreveu os testes usando TDD e gerou o código usando o Scaffold de um cadastro de participante que tinha os campos nome e e-mail. Achei bem legal a demonstração, o Cucumber é uma ferramenta muito legal, nela você cria o teste como se estivesse criando uma caso de teste, segue abaixo um exemplo:

Exemplo de teste feito para o Cucumber

O Cucumber utiliza por default o Webrat, porém também é possível realizar o teste usando o Selenium RC, basta passar como parâmetro. O interessante do uso do Webrat é que diferente do Selenium, ele simula o navegador, rodando em background, ou seja, é muito mais rápido que o Selenium RC, porém tem a limitação de não conseguir testar javascript.

E depois do “rango”,  a segunda parte foi no mesmo nível que a primeira?

Depois do excelente coffee break, o Jorge Diz passou vários slides explicando a teoria de testes, abordando desde as escolas de teste até sobre os tipos de dublês. Essa parte fugiu um pouco do formato de debate, mas logo o Rafael Rosa retomou o formato, estimulando uma discussão sobre mocks e o perigo de “engessar muito” utilizando eles.

Do debate sobre mocks, o pessoal chegou a seguintes conclusões:

  • Se você está “mockando” muito, pode ser um sinal que a sua classe está fazendo mais do que ela deveria fazer. Então REFATORE;
  • Sempre tente modularizar ao máximo a sua aplicação, nada de ter uma classe “sistema”;
  • Os dublês em geral, devem ser usados sempre para resolver uma dependência.

Um assunto interessante abordado na apresentação do Jorge, foi como deve ser a pirâmide dos testes, de acordo com o nível:

TestingPyramidMas o que ocorre, geralmente, sem essa cultura de que desenvolvedor também testar, é uma inversão dessa pirâmide, ou seja, não há quase nenhum teste de unidade e integrado realizado, e muitos testes de sistema feitos pelo pessoal de Teste de Software.

E ainda houve mais duas práticas, uma com o Thiago Scalone mostrando o Selenium IDE e o RC. E depois mais uma com o Anderson apresentando o RSpec (o JUnit do Ruby)

E o que você achou? Pelo jeito deve ter sido ótimo, afinal além de falar de testes deve coffee break na faixa.

Excelente encontro! Comprovou que é mito essa história que desenvolvedor não testa, eles testam sim, e até melhor do que muito testador que tem por aí. E Ruby é uma linguagem que oferece uma “testabilidade” incrível, as ferramentas que existem são muito boas, e ajudam desde o teste de nível unitário até o teste de nível de aceite. E essa brincadeira que faço sobre “lado negro da força”, em breve ficará sem sentido, pois os testes estão se tornando cada vez mais uma tarefa inerente ao desenvolvimento.

Para encerrar o post, parabéns a todos que participaram, e principalmente, ao Rafael Rosa, pela excelente organização!

Para saber mais sobre o 6ºEncontro acesse a wiki do Guru-SP:

http://guru-sp.com/index.php/Sexto_Encontro

E para saber sobre os próximos encontros acompanhe o Ruby Inside Brasil:

http://www.rubyinside.com.br/

Fique por dentro das novidades, assine o feed do QualidadeBR.

guru espiritual

Para que testar?

Antes de trabalhar com Teste de Software, eu nem sabia que existia essa área, e acredito que mesmo com o crescimento que a nossa área teve nos últimos anos, ainda há muitas pessoas que não devem ter conhecimento que uma das áreas necessária para o desenvolvimento de um software é a de Teste de Software. E falo isso, principalmente pensando nos jovens que estão se formando nas faculdades, pois eu mesmo não tive uma matéria sobre Teste de Software na faculdade e muito menos praticava TDD nas muitas aulas que tive de programação, passando desde Pascal até Java. E olha que não faz tanto assim que me formei, para ser mais preciso irá completar 1 ano no final de dezembro desse ano.

Vários outros amigos meus, que estudaram em outras faculdades não tiveram tal matéria na grade do curso. Costumo até brincar com o pessoal falando que na faculdade eu só aprendi o que é teste de caixa branca e caixa preta, e foi isso mesmo. Não me disseram que existia uma área que poderia ser responsável pelos testes, quando é necessário testar, como testar, como escrever um caso de teste, como realizar o planejamento, quais técnicas posso usar, e tantas outras dúvidas que tive quando iniciei na área.

E com certeza, essa pergunta “Para que testar?” pode gerar muitas respostas diferentes, dependendo do ponto de vista e do conhecimento da pessoa. E uma das formas de responder essa pergunta, eu usei aqui nesta apresentação. Mas desta vez vou usar uma outra abordagem para falar sobre o assunto, trazendo algumas questões que ajudam a explicar a razão pela qual é necessário testar um software.

Se o software compilou ele está funcionando, então pronto!?

Esse pode ser o pensamento de muitas pessoas, principalmente, daqueles estudantes que nunca ouviram falar em Teste de Software. A compilação de um programa até pode ser vista como a realização de um teste de caixa branca, afinal o compilador irá verificar se não há nenhum erro no código, por exemplo sintaxe, que impeça dele ser compilado.

Mas a compilação por si só não garante que o software esteja funcionando.

Como assim?

No mundo dos projetos de desenvolvimento de software há o famoso escopo, que especifica o que o sistema deverá fazer e o que o mesmo não deverá. E é esse documento que será o referencial do cliente quanto ao seu sistema, se ao entregar o software, algum item do escopo não tiver sido implementado, “coisas horríveis irão acontecer”.

E um dos objetivos do Teste de Software é justamente verificar se tudo que está especificado no escopo foi implementado. Tanto que ele é um dos documentos usados pelo Analista de Teste para poder originar os casos de testes, que serão executados pelos testadores.

O que aconteceria se um software não fosse testado?

Como diria um professor meu “coisas horríveis irão acontecer”. Afinal, a primeira pessoa que irá testar o seu sistema serão os clientes e usuários, e caso eles encontrem alguma inconformidade no seu sistema, o que é bem provável pensando num software que não foi testado, eles não ficaram nem um pouco satisfeitos e o preço pela inconformidade poderá ser muito alto, principalmente nos casos em que há multas contratuais.

Além disso, sistemas que não são testados em fase de desenvolvimento, costumam passar uma boa parte da sua vida pela equipe de manutenção e de suporte. Ou seja, o retrabalho gerado por um software não testado é muito alto!

Todos os softwares são testados?

Todos os softwares deveriam ser testados, mas na realidade poucos são os softwares que são testados de forma efetiva. E um dos motivos principais para que haja necessidade de ser testar algo (em qualquer realidade) é o fato que somos seres humanos, ou seja, estamos sujeito ao erro. Afinal errar é humano!

Há muitas desculpas que fazem com que um software não seja testado, dentre as principais estão:

  • Excesso de confiança dos desenvolvedores;
  • Falta de tempo para o Teste de Software;
  • Não há a cultura de realizar testes;
  • Não há pessoas capacitadas para executar os testes;
  • Desconhecimento da importância do Teste de Software;
  • Os custos com os testes não foram colocados no custo do projeto;
  • Etc.

O que é esse tal de TDD?

Comentei no começo do post sobre TDD, uma tendência muito forte no desenvolvimento do software é que já realidade em várias empresas no Brasil e no mundo. TDD é o acrônimo para Test Driven Development, que em bom português é Desenvolvimento Orientado a Testes.

A idéia é bem simples: antes de partir para o desenvolvimento da funcionalidade você irá escrever testes para ela. Isso mesmo, antes de desenvolver a funcionalidade, você irá desenvolver testes que verifiquem e validem a funcionalidade que será desenvolvida.

Daí você pode está se perguntando, mas como eu farei isso? Há alguma ferramenta que facilite esse trabalho?

Há sim, os chamados frameworks/arcabouços xUnit. Eles permitem que você desenvolva testes, chamados de testes unitários, para as diferentes unidades do seu sistema, como por exemplo funções e classes. Além disso, uma grande vantagem desses frameworks é que eles permitem que você execute os testes de forma automática.

Lembra que eu falei que quando você compila você está apenas verificando se o código que você escreveu é compilável, pois então, usando por exemplo o JUnit, um framework para Java, é possível fazer com que ao compilar o seu código os testes que você criou também sejam executados. Ou seja, você também está testando o seu software e ainda de forma automatizada! 🙂

Muitos entusiastas no TDD dizem que os testes automatizados acabam tornando-se uma documentação viva do sistema, e eles estão corretos. Num cenário com testes automatizados, sempre que for necessário realizar uma mudança, ela ser feita com tranquilidade, pois você poderá verificar se a mudança implementada não quebra nada no seu código ou não está de acordo com a documentação, apenas tendo o trabalho de apertar o botão “play” para execução dos testes criados anteriormente.

Mas lógico que para que o TDD possa trazer bons resultados os testes tem que ser bem desenvolvidos, de nada adianta criar um teste que não testa nada. E não pense que usando TDD, você não precisará realizar mais nenhum teste, pois você só está executando os testes unitários, há ainda os testes de integração, sistema e aceitação. 🙂

Conclusão

Testar um software deve ser uma tarefa comum, durante o desenvolvimento do software. Pois é uma forma de aumentar a qualidade do software, a credibilidade da empresa com os seus clientes e maximizar o lucro da empresa. Além é claro, de ser uma das práticas de empresas profissionais, que objetivam entregar uma solução que resolva os problemas dos seus clientes e não uma solução que gere mais problemas para eles.

Além disso, testar não é uma tarefa que deve ser feita só no final do desenvolvimento, até porque, podemos testar antes mesmo de desenvolver. Portanto, devemos buscar usar e conhecer as melhores práticas no nosso trabalho, dentre as quais testar é uma prática essencial. 😉

Fique por dentro das novidades, assine o feed do QualidadeBR.