Helio Costa - hlegius : Rua sem saída: não consigo criar meu próximo teste - Prelúdio
28 de Julho de 2014, 7:35 - sem comentários aindaVocê resolveu tentar a fazer test-first. Conseguiu fazer seu primeiro teste passar. As coisas estavam fluindo bem até quando você chegou em um ponto em que não consegue escrever o próximo teste. A ideia está na sua cabeça, pronta para ser jogada em execução, mas travou no processo de escrita da especificação executável (seu teste). E agora?
Neste momento, você que está ainda se adaptando a nova forma de pensar, acaba chegando em uma rua sem saída. O segredo aqui é não desistir e sair falando que o @dhh é um gênio da computação, um visionário e que TDD is dead mesmo. Calma lá, rapá!
Para lidar com este problema crítico, temos que antes analisar nosso (seu) cenário. Para tanto, vamos listar alguns sintomas que poderão nos levar a causa e depois a solução:
Ao tentar escrever o teste, eu:
- Não consigo imaginar em qual objeto ficará a feature - e/ou se ele precisará de outros objetos existente para funcionar.
- Preciso mockar um objeto do qual é criado dentro da classe que vou usar como auxiliar.
- Percebi que meu setup (before no RSpec) tem mais que 5 linhas.
- Estou querendo testar um método privado.
- Não consigo isolar a feature que vou criar. Os objetos que irão interagir com ela são complexos para mockar.
- Não consigo verificar se um evento/callback do framework que estou usando foi chamado.
- Tenho um mock que retorna um outro objeto que precisa também de ser configurado com mock. Parece um mock-de-mock.
- Vou precisar instanciar vários objetos nesta nova feature.
- Estou criando o código de produção e meu método alvo do teste está imenso ou/e cheio de chamadas à métodos privados da própria classe.
- Demorei tanto pensando numa solução que acabou desistindo e criando o código sem teste. O código de produção funciona (você o testou manualmente), porém ainda não sabe como escreverá (e se) o teste que o validará.
Prelúdio
Para começar, precisamos carregar os pré-requisitos em nossa mente para conseguir seguir em frente. Eles são leituras importantes que contêm conceitos, dicas e definições de assuntos que precisamos lembrar de bate-pronto para lidar com o grande problema acima.
- Three rules of TDD: Red, Green, Refactor. Sem pressa. Pensar 10 minutos pode render 1h de bate cabeça e desespero com prazos.
- Baby steps: nos seus primeiros 6 meses, recomendo que faça sempre baby steps para evitar os problemas acima.
- God Class ou God Method - você não está abstraindo as coisas como deveria. Você pode e deve cogitar criar POROs (Plain Old Ruby Objects) que irão auxiliar seus demais objetos dentro do pacote/domínio da aplicação.
- Tell, Don't Ask evite perguntar algo para o objeto colaborador para baseado no resultado, fazer algo. Se precisa fazer, solicite que o próprio faça uma vez que ele tem o valor/estado que é pré-requisito.
- Injeção de Dependência: o Ruby inteiro é baseado nisso. É algo natural e que você deve manter em seus códigos. Poderá resolver problemas de mocking e overmocking, por exemplo.
-
Crie tipos! Seu software é financeiro? Inspire-se nos nomes reais ou que seu cliente fala. Se na reunião ele diz que o cliente irá transferir dinheiro da conta pessoal para um outro cliente, experimente criar
Money
,Transfer
,Account
,Customer
. Ubiquitous Language FTW! - SRP. The same old Single Responsibility Principle. Ok, você já ouviu isso incontáveis vezes. Mas pare para pensar naquele objeto com um método público e 10 privados. Pensou? Agora leia a dica acima de sobre criar tipos. Entendeu o que eu quis dizer?
- Você entendeu quais os objetivos de mockar, certo?
Continuará
Vou comentar em detalhes cada um dos 10 problemas ao criar o próximo teste nos próximos posts. Vou utilizar diagramas, exemplos de código e tudo mais que for necessário em cada caso. O prelúdio obviamente contém spoilers sobre o que utilizaremos para resolver os problemas e continuar on track no test-first. Então se você estiver disposto, pense com calma e veja se consegue sair da rua sem saída antes do post que falará sobre seu problema em detalhes.
Para começar, ouça o Ruby Rogues #158 chamado Confessions e o Thoughtbot #79: The Gentle Wise One. Se você codifica em Ruby, não deixe de ler e ver o meu post sobre Arquitetura, Rails e o ecossistema Ruby, onde contém um bom start sobre as raizes de alguns dos 10 problemas ao fazer seu próximo teste passar.
To be continued.
Magnun Leno : Aberto a contribuições
21 de Julho de 2014, 9:40 - sem comentários aindaDesde que me envolvi com o Software Livre e o mundo Open Source, acabei adotando essa filosofia e aplicando seus princípios em muitos aspectos da minha vida, e este site é só uma dessas consequências.
Apesar deste site servir para manter o conhecimento que adquiro aberto e acessível para a comunidade, eu nunca tinha bolado uma boa forma de tornar o site 100% livre, isto é, aberto para outras pessoas e disponibilizado seu conteúdo sem restrições. Se você não tiver paciência para ler e quiser logo saber como contribuir, clique aqui.
Aberto a contribuições é um artigo original de Mind Bending
Helio Costa - hlegius : Refatoração de código
21 de Julho de 2014, 7:35 - sem comentários aindaNão precisa acompanhar o "mundo dos testes" para saber o que significa refatorar. Aliás, quem nunca ouviu algum co-worker ou você mesmo tenha feito uma refatoração de um código.
Primeiro, vamos deixar bem claro o que é refatoração. Vamos lá. Você tem até o próximo paragrafo para pensar na sua definição de refatoração de código.
Pronto? Aqui vamos nós!
A milagrosa refatoração de código
Primeiramente é importante explanar de que há dois tipos de refatoração: a) refatoração, terceira etapa do Test-Driven Development (Red, Green, Refactor); b) refatoração de um código de produção já existente. Neste momento vou tratar apenas do item b).
A necessidade de uma refatoração dá-se inicialmente por uma decisão de um (ou mais) programadores sob um determinado trecho de código, por concluir de que aquilo não está construído de uma maneira aceitável. Disto, o cabra deve lembrar de que refatorar quer dizer: não mudar o comportamento da parte a ser refatorada. Apesar de óbvio, essa primeira premissa é a mais violada ao refatorar algo, pois junto da refatoração o programador resolve fazer umas coisinhas a mais (inserir novas features, por exemplo).
Não precisa ir muito longe para provar de que isso não funciona bem, não é mesmo? Ao refatorar você pode quebrar coisas. E, para evitar que essa quebra não vá parar em produção (ou parar o env de produção), você precisa de respostas rápidas a quaisquer mudanças que faça no código, por menores que sejam. (Test-First aqui, alguém?).
Item número dois: evite com todas as forças ficar criando tarefas de refatoração no projeto. A refatoração deve vir com um propósito. Prever o futuro não é um propósito. Não há necessidade de refatorar algo que está em produção há tempos só pelo prazer de refatorar um trecho de código. (você pode fazer isso em casa, para estudar, claro!) Pois você já deveria ter feito isto no terceiro passo do TDD: (Red, Green, Refactor). Se não o fez, espere até que venha precisar trabalhar com aquele código novamente para implementar uma nova feature, daí, divida essa feature em duas etapas: refatorar o código envolvido na nova tarefa e fazer a nova tarefa. Lembre-se: dois passos. Refatorar e somente depois, implementar.
O (semi)deus da refatoração
Lembra que falei que a palavra refatoração você já devia ter ouvido em algum ambiente antes? Sempre ao pegar um código é um costume a gente não entender o que aquilo faz (e por que faz). Por não entender, a gente vai e diz: ah, isso aqui precisa de uma refatoração. Será mesmo?
Esse tipo de atitude pode colocar em xeque os benefícios da refatoração e pior: quebrar algo em produção desnecessariamente, pura e simplesmente porque você sendo novo naquele projeto/equipe não entendeu o código - o que é normal em todo início. Com isso, você faz feio com a equipe e pode destruir todo um processo de amostragem e explicação sobre benefícios de uma refatoração planejada.
É importante que você vá com calma e espere até ter uma certeza mais clara das coisas.
Refatoração nem sempre é a melhor saída
Outro ponto a favor de evitar sair refatorando sem saber quem nem porquê é ter o controle analítico de analisar o cenário em questão e verificar se a refatoração de código solucionaria o problema. Já vi casos em que o código em si não estava ruim, estava aceitável, o verdadeiro problema era um design mal pensando e neste caso, a refatoração não ajudaria em nada. Você precisaria ir além nas decisões.
É preferível manter um código espaguete por mais um tempo do que perder a (única) chance de mostrar os benefícios. No podcast de número 157 do Ruby Rogues, Rebecca Wirfs-Brock afirmou outro ponto importante:
You’re sort of arguing that refactoring is not necessarily always the best way to clean up a design. Sometimes, you might want to start over.
Às vezes realmente vale mais a pena fazer um git reset
ou um git stash
(como disse o Avdi Grimm brincando com ela) mental e partir a fazer uma outra solução do zero. Já tive que fazer isto inúmeras vezes ao longo do tempo. Um grande aliado nesse processo são os Testes de Unidade com Test-First, pois eles dão uma resposta muito rápida sobre seu progresso (ou estagnada) de raciocínio.
Hoje a conclusão, dar-se-á em forma de resumão!
Resumão:
- Respostas rápidas ao refatorar. Teste de unidade é a única forma de conseguir isto rapida e isoladamente.
- Refatorar. Depois de pronto, volte para implementar o que ia fazer no começo. Não faça os dois juntos por mais que Goku desça da núvem para te pedir isto.
- Refatorar ao entrar num projeto: it's a trap!
- Às vezes é melhor um
git reset
mental e partir para outra solução. - Estar apoiado em teste de unidade e test-first trará a confiança necessária para tomar a decisão de refatorar.
- Esforce-se para não tornar a refatoração uma task do seu projeto. Ela deve ser junto de uma task de implementação. Refatorar precisa de propósito.
- Red, Green, Refactor (TDD) != Refatorar código de produção.
Helio Costa - hlegius : O Teste mudo
14 de Julho de 2014, 7:30 - sem comentários aindaJá defendi aqui nos posts o Test-First inúmeras vezes. Hoje, vou na linha oposta: quando o teste torna-se totalmente dispensável.
Imagine você entrando numa equipe para auxiliar a resolver uma lista de bugs existentes. Você faz algumas perguntas e obtém como respostas:
- Os bugs em questão existem há tempos. Foram "consertados", porém "reapareceram";
- O projeto tem seus 145 testes que rodam em 3 minutos;
- Nenhum teste falha.
Primeira ação sua é obviamente dar uma olhada no /specs
do projeto, pois as condições que ocasionam os bugs podem não estarem cobertas nos testes. Simples, você pensa. Só criar teste cases e pronto.
Criando o caso de falha
Seguindo o princípio da engenharia reversa, você deveria criar o teste que simula o bug. Ao abrir o código de teste, porém, você encontra um setup
de 25 linhas, criando o chamado Persistent Fixtures do xUnit Patterns.
Todos os testes são de integração. Pelo menos, como diz o DHH, o teste de integração garante que seu código funciona.
Será ?
Você segue adiante. Vê duplicação de código de teste. Mas isso obviamente não importa, pois ele precisa apenas verificar que o código funciona. Você olha pelo código, procurando o melhor "lugar" para encaixar teus novos casos de teste até que se depara com nada menos do que o teste que está verificando aquela funcionabilidade esperada. E ele é Green.
O teste mudo
Ele não diz nada. Ele testa uma action
da Controller
e de brinde, passa pela funcionabilidade quebrada. Por ser um integration-all-in-one-full-stack teste, você não tem muito o que mudar, pois é basicamente um Input numa URL e a análise de um retorno. Neste cenário, você não tem o que mudar, pois o código de integração não garante que aquele bug apareça e seu teste finalmente falhe. Sua opção é tentar criar um Teste de Unidade.
One size fits all
Você percebe que o código de domínio totalmente ligado ao framework que você utiliza. Percebe que não poderá fazer um teste de unidade sem carregar junto nada menos do que 8 dependências. Mockar 8 coisas ? This is madness!
Como o framework é arquitetural, você está refém das convenções fornecidas por ele. Neste caso, você não tem muito o que fazer a não ser lamentar.
Fallback em debugging
Você desiste dos testes e decide que precisa resolver. Solução ? Partir para ferramentas de debugging. Com debug, você precisa entender variáveis e intra-código totalmente desnecessário para aquela tarefa porém, obrigatória no debugging uma vez que você precisa entender o fluxo (stack) da aplicação.
Depois de algumas boas horas, você percebe que o bug era na verdade uma infestação, pois havia mais de um lugar totalmente diferente que exercitava o código e criava o bug. Em miúdos: três telas utilizando duas regras totalmente diferentes para chegar a mesma solução. Lembre-se: Test-Driven development é desnecessário.
Concluindo
Você resolve o bug após várias horas. Faz teste manual e verifica que tudo está perfeito, inclusive seus testes continuam green, mostrando que aquela suite é totalmente dispensável e que teste sem propósito deveriar estar morto.
Essa pode ser uma história totalmente folclórica ou não.
Arch Linux Brasil : MariaDB 10.0 entra no [extra]
13 de Julho de 2014, 20:00 - sem comentários aindaLeandro Inácio escreveu:
Uma nova major release do MariaDB será movida para o [extra] em breve. A mudança no esquema de versionamento foi feita para distinguir claramente as funcionalidades fornecidas a partir do MySQL 5.6. A partir de agora, não será possível mudar facilmente entre as várias versões da implementação do MySQL fornecida no repositório oficial.
Devido a grande mudança no MariaDB 10.0, é recomendado (embora, não necessário) fazer um dump das tabelas antes de atualizar e depois recarregar o arquivo do dump.
Após a atualização para nova versão não esqueça de reiniciar o mysqld.service
e executar mysql_upgrade
para checar os possíveis erros do banco de dados.
Adicionalmente a engine de armazenamento TokuDB foi desabilitada por repetidas falhas no empacotamento. Sinto muito por qualquer inconveniente causado.
Para informações mais detalhadas nas mudanças e no procedimento de atualização, por favor veja a base de conhecimento do MariaDB e o manual do MySQL.
URL da notícia: https://www.archlinux.org/news/mariadb-100-enters-extra/
Magnun Leno : Argumentos e Parâmetros em C
11 de Julho de 2014, 8:22 - sem comentários aindaOs parâmetros e argumentos são aquelas opções que usamos quando executamos um programa na linha de comando, como df -h ou ls -la --color. Tratar esses parâmetros e argumentos faz com que nossos programas estejam em compliance com o sistema operacional.
A implementação dos parâmetros e argumentos da linha de comando é um assunto complexo e requer dedicação. Abaixo explico de maneira prática como implementá-los através de funções GNU. No entanto, vou explicar também um pouco desse padrão da linha de comando, dos parâmetros e dos argumentos, pois é imprescindível saber como eles funcionam para uma correta implementação.
Argumentos e Parâmetros em C é um artigo original de Mind Bending
Arch Linux Brasil : Manutenção nos serviços
7 de Julho de 2014, 20:00 - sem comentários aindaLeandro Inácio escreveu:
Gostaria de informar que estamos passando por manutenção nos serviços do Arch Linux Brasil, caso algum serviço encontre-se indisponível, não se preocupe que estamos trabalhando para melhorar a infraestrutura do projeto.
Blog do Gio : SMPlayer!
7 de Julho de 2014, 15:13 - sem comentários aindaO SMPlayer é um dos melhores players de vídeo que já utilizei!
Esse pequeno post tem como objetivo mostrar como fazer a instalação do SM de forma completa aqui no Arch, acredito que o mesmo deve estar disponível não só no Arch mas na grande maioria das distribuições tem até pra Windows!
Vamos fazer a instalação no Arch, logo:
# pacman -S smplayer smplayer-themes smplayer-skins
Uma característica/configuração muito legal do SM é que “se começar a ver um filme e tiver que parar… não se preocupe, pois quando o abrir novamente ele continuará do ponto onde o deixou e com as mesmas definições: áudio, faixa, legendas, volume…” e isso é excelente!
Então instale, teste e divirta-se!
Helio Costa - hlegius : Test-Driven Development é desnecessário!
7 de Julho de 2014, 7:35 - sem comentários aindaHá alguns dias atrás ouvi a seguinte afirmativa:
Acredito que testes de unidade são importantes; Não vejo necessidade porém, em fazer TDD.
Será?
Separando as coisas: Teste de Unidade
Teste de unidade, como comentei anteriormente, tem como objetivo garantir que uma parte da regra de negócio funcione como foi solicitada/descrita pelo interessado pelo software. O teste deve abranger apenas um cenário, seja ele feliz (do caminho feliz); ou falho. Todo e qualquer input que se faça necessário deverá ser introduzido com o auxílio de Mocks ou/e Stubs, fazendo assim com que o teste seja o mais independente possível do restante das classes que colaboram/interagem com aquele trecho na vida real (código de produção).
Uma maneira de verificar se seu código de teste está bem escrito é atentar-se para a anatomia do teste de unidade: deverá ter um trecho para input dos dados necessário ao teste; execução do código que está sob teste; e por fim, analisar os resultados obtidos.
Fazer o teste depois do código de produção poderá no início trazer confiabilidade do que se está fazendo. Ao crescer a aplicação porém, é provável que você perca o controle da suite e o resultado é preocupante: um bolo de testes acoplados e sem garantias sob o código de produção. Nessa hora você cairá um beco sem saída e culpará injustamente "essa falácia de testar software".
Podemos afirmar também que fazer teste de unidade para mostrar para o chefe não é uma boa ideia, pois o parabéns que você obterá com ele hoje, poderá se transformar no maior vilão, quando você perder o controle estrutural do seu código.
Separando as coisas: Test-Driven Development
Tem seu cerne em: Red, Green, Refactor. Em miúdos:
- Escreva o teste que irá exercitar uma parte isolada do seu código (leia acima sobre isso).
- Escreva o código (de produção) que irá fazer o teste ficar verde (passar).
- Verifique se seu código de produção (e o de teste) podem ter melhora, tanto na escrita quando na qualidade e best practices da linguagem.
Repita esse processo até começar a colher os resultados do TDD. Depois que estiver mais acostumado (coisa de algumas semanas), você poderá se adaptar melhor. Lembre-se: Baby Steps são importantes nesta fase: faça uma coisa de cada vez. Não escreva 20 linhas de código sem ir verificando com seu teste o que está acontecendo. Não tenha pressa. Você está aprendendo uma nova forma de ver o mundo.
Outro dia, mexendo num código da galera aqui, encontrei um método que possuia 37 variáveis temporárias; 7 loops; 11 ifs/else; 5 comentários de uma linha.
É nítido que o programador não sabia mais onde colocar as coisas. Ele perdeu o controle do código de uma forma tão intensa, que ele precisou fazer 3 loops com a mesma Collection, para fazer coisas diferentes com ela.
Nem é preciso entrar no detalhe de Single Responsibility Principle; Dont Repeat Yourself. Ele não sabia aonde colocar cada coisa. Ponto.
É nisso que o TDD auxilia. Ele está ali como um guarda, pronto para levantar uma bandeira assim que você começa a se perder. Ele sinaliza através dos testes a necessidade de repensar a solução, reorganizar o código para a nova feature, para fazer o flush mental.
Test-Driven Development é sobre onde colocar seu código e não sobre Verificação e Validação.
Enquanto você não ter essa visão, continuará a sofrer com debugging, duplicação à e-nésima (duplicação da duplicação n vezes) e o renomado Bug Ioiô: bug que é resolvido e depois aparece novamente.
O ponto de encontro
Teste de Unidade + Design Orientado a Objetos: Test-Driven Development Design.
Concluíndo
Não, você não é o Jiraya da programação. Pouco importa se você tem toda a ideia na sua cabeça, aposto com você de que, se ao invés de primeiro fazer o código de produção fizer o teste, aquela sua toda ideia inicial terá sido apenas um rascunho da versão que criará guiada pelos testes.
A dica final é: não seja afobado. Ao começar fazer testes de unidades, faça do modo clássico: Red, Green, Refactor.
Tem uma definição bacana sobre Test-Driven Development? Mande um tweet com a hashtag #deftdd ou me mencione. Vou retuitar todas as criativas ;)
Helio Costa - hlegius :
7 de Julho de 2014, 5:22 - sem comentários ainda
Dropbox - 5xx
ErrorSomething went wrong. Don't worry, your files are still safe and the Dropboxers have been notified. Check out our Help Center and forums for help, or head back to home. |