Helio Costa - hlegius : Obtendo o primeiro Test Pass
12 de Maio de 2014, 7:35 - sem comentários aindaDepois de ficar maravilhado com as promessas de um mundo melhor código mais harmonioso, manutenível e desacoplado, vem uma curta pergunta que nos leva a nossa primeira Rua sem Saída: como fazer meu primeiro teste (do projeto) passar?
As minhas Ruas sem saída foram: "em um projeto novo, o que testar primeiro?" e, "em um projeto legado como fazer o primeiro teste?"
Vou criar um cenário hipotético, apenas para fins de apoio: você é contratado para fazer uma Extranet de Bike Shop. Os requisitos em alto nível são:
- Área segura para somente funcionários/gestores logarem no sistema
Somente após login, a aplicação liberará acesso às features:
- Cadastro de Marcas e Modelos de bicicleta;
- Cadastro de bicicleta;
- Cadastro de peças de reposição para uma (ou várias) marcas de bicicletas. - Pense nessas peças como peças de um determinado fabricante de carro: você pode comprar a peça "original" com a logo do fabricante do carro na peça ou a "paralela" feita pelo mesma empresa (por ex. Cofap, de amortecedores) mas sem a logomarca de nenhuma fabricante de carro, em um CarShop qualquer de rua.
- Cadastro de peças genéricas (a tal da paralela).
- Listagem de tudo isso que foi pedido.
Para efeitos de exemplos:
Marca: Caloi Modelo: Urbe Peça de reposição: Guidão Flat Peça genérica: Cambio Traseiro Shimano TX 7 Velocidades
A peça genérica em nosso bike shop, em tese servirá para qualquer bicicleta que precisar daquele componente.
Começando: você escolhe a linguagem de programação, um possível bootstrap para subir um Hello Test no navegador e pronto. Está pronto para começar a fazer as coisas. Mas, e agora?
Sabendo por onde começar
A pergunta inicial não deveria ser "Por onde começar?" mas sim, "O que é mais importante no projeto?". Seu cliente/chefe irá ver o projeto de tempos em tempos e você certamente terá dúvidas que só ele saberá responder. Enquanto o projeto não está pronto, o que é dispensável no projeto?
O sistema de autenticação é claro! Incrivelmente com todos que falei ou fiz essa pergunta (incluindo eu mesmo - sim, falo sozinho), o sistema de autenticação é escolhido como primeira coisa a ser feita. Pense bem. Para que raios a autenticação é importante agora? Ela evitará acesso indevido, mas se o software está em processo embrionário, com acesso limitado ao servidor e dados dummies, para que ele serve? Ignore-o por enquanto e foque no core do negócio!
Os pingos nos ís
Nat Price, sugeriu em seu livro criar um Teste de Aceitação e com este, criar seu primeiro Teste Unitário de Unidade. Seguiria criando os testes de unidade fazendo-os passar até que o teste de aceitação passaria também, finalizando assim aquela feature.
Eu já fiz essa abordagem, mas achei ela um tanto verbosa em casos onde o do teste de aceitação é muito parecido com o teste de unidade - até porque um software web é arquitetonicamente diferente de um software de missão crítica ou embarcado, por exemplo.
Atualmente, eu sigo apenas o processo interno, sem Teste de Aceitação ou/e Integração pelo simples fato de ser mais direto e não há nenhum efeito colateral no processo em si.
O Primeiro Green, Like a Boss!
Eu começaria pela Peça. Uma classe para identificar Peças "Originais" e outra para Peças Genéricas ou apenas uma?
O legal é esse tipo de decisão, pode ser adiado com Test-Driven Development. Vamos começar pelo mais fácil: uma classe Peça.
@test
everyGenuinePartBelongsToABicycle()
Assim como em Concessionárias de automóveis, há peças que são relacionadas ao veículo e por mais que sirva em mais de um modelo, a relação Parte-Veículo torna-se indispensável.
Algo assim, pode ser um começo:
class BicyclePartTest {
private subject = new Part();
private bicycle = a_bicycle_mock_object;
@test
public everyGenuinePartBelongsToABicycle() {
subject.setBicycle(bicycle)
assertTrue(subject.isGenuine())
}
}
Ou seja, para Part (Peça da bike) ser Genuína (Original), a peça precisa estar relacionada a uma bike em específico. Esse simples teste já nos guia para nosso próximo:
class BicycleTest {
private subject = new Bicycle();
@test
public willContainGenuineParts() {
subject.addGenuinePart(a_mocked_part)
assertCount(1, subject.getGenuineParts())
}
}
Uma bicicleta deverá ter Peças. Neste caso, Peça Genuína devemos atentar que a relação é uma Composição, ou seja, a Parte(Part) não existe sem o Todo (Bicycle). Já sabemos também que:
class Bicycle {
public void addGenuinePart(Part genuinePart) {
parts.add(genuinePart)
genuinePart.setBicycle(this)
}
}
A relação bi-direcional deverá existir, conforme o teste do BicyclePart sugeriu lá no começo.
Montando a classe Part para que satisfaça o teste do BicyclePart, você já verá o Green na tua tela. Mais do que um, dois pontos verdes.
Eu já consigo ter uma próxima dúvida: em peças genuínas, poderá haver mais de uma peça por bike? Sim, não?
Sim! Pode-se optar por quantificar quantas peças daquela a bike tem e aonde elas ficam:
class BicyclePartTest {
private subject = new Part();
private bicycle = a_bicycle_mock_object;
@test
public genuinePartMustHaveQuantityAndPosition() {
subject.setBicycle(bicycle);
subject.definePositionAndQuantity("front", 2)
subject.definePositionAndQuantity("rear", 2)
assertEquals(4, subject.getRequiredQuantity())
assertEquals(["front", "rear"], subject.getPositions())
}
@test
public everyGenuinePartBelongsToABicycle() { ... }
}
Implementando o código de produção, o teste passará mais uma vez. 3 greens!
E Part não Genuína? Também terá posicionamento e quantidade? Uma porca do Cubo da roda, por exemplo são duas na frente (direita e esquerda) e duas atrás (direita e esquerda). Então:
class BicyclePartTest {
private subject = new Part();
private bicycle = a_bicycle_mock_object;
@test
public partMustHaveQuantityAndPosition() {
subject.definePositionAndQuantity("front", 2)
subject.definePositionAndQuantity("rear", 2)
assertEquals(4, subject.getRequiredQuantity())
assertEquals(["front", "rear"], subject.getPositions())
}
@test
public everyGenuinePartBelongsToABicycle() { ... }
}
Neste caso nem precisei fazer outro teste. Apenas mudei o input e nome do teste anterior. Agora o teste diz que uma Part precisa ter quantidade e posição. Ok, mas e se eu não a definir? Uma vez que é obrigatório (..) uma ideia é mover para o construtor de Part, não? A simples ideia de fazer por steps, nos faz pensar sobre o negócio que estamos criando e consequentemente, criar um código mais legível e coeso (harmonioso, por exemplo).
Mas, mas...
E o Database Schema? A herança do ActiveRecord ou o Repository do DataMapper? Uma coisa que eu faço - até com Rails - é criar POJO's/PORO's/POPO's - Plain Old (Java | Ruby | PHP) Objects. depois que eu tenho uma relação mínima feita, daí sim eu crio as relações, os schemas, etc - pois eu sei que precisarei isolá-los e etc.
A autenticação ficou para uma fase mais madura do projeto. Poderá ser até mais para o fim, quando realmente ela for útil.
Concluíndo
Seguir o de sempre e começar sempre pelo mesmo lugar não é algo justo de ser feito. Talvez você precise de uma Introspecção para rever algumas práticas (..)
Criar software orientado a testes é muito divertido, você precisa tentar, sério!
Challenge
Se você quer tentar, pegue esse simples projeto que citei aqui e tente implementá-lo em com sua linguagem do momento. Se quiser, pode me enviar por Github para te dar umas dicas. Se quiser também, podemos marcar uma conversa para discutirmos o design da aplicação. Será muito valioso para todos participantes. ;)
Magnun Leno : Documentário Revolution OS
7 de Maio de 2014, 11:20 - sem comentários aindaTalvez tenha sido resultado da revisão que realizei no conteúdo do Curso de Filosofia GNU ou de outras pesquisas que tenho feito, mas neste fim de semana me reencontrei com o excelente documentário Revolution OS e acabei re assistindo-o.
Escrito, dirigido, produzido e editado por J. T. S. Moore, Revolution OS conta com grandes hackers e empreendedores como: Richard Stallman, Michael Tiemann, Linus Torvalds, Larry Augustin, Eric S. Raymond, Bruce Perens, Frank Hecker and Brian Behlendorf.
Documentário Revolution OS é um artigo original de Mind Bending
Helio Costa - hlegius : As ruas sem saída em Test-first
5 de Maio de 2014, 8:02 - sem comentários aindaUma vez entendidas as motivações de se fazer Test-first, mudar seu mindset para TDD, muitas coisas ainda restam apontar. Claramente, há um processo sugerido para conseguir se concentrar e tomar como guia quando chegar em becos sem saída trabalhando com Test-first.
Tão sabido quanto ao andar de bicicleta você fatalmente cairá uma hora ou outra, com os testes não é diferente: você irá sim chegar à ruas sem saída. Terá dúvidas, poderá sentir-se no escuro. Não pelo Test Driven Development per se, mas pelo fato de que você está saindo da sua zona de conforto; você está experimentando.
Na minha máquina (não) funciona!
Há pessoas que de tanto chegar à ruas sem saída, acabam assumindo que TDD e toda aquela coisa de design desacoplado são cartas viradas. É fato de que a ciência que envolve a computação é muito recente. Vivemos nosso momento paleolítico e haverão grandes cientístas (e tecnologistas) no futuro mudando a forma como lidamos com tais problemas, mas não podemos simplesmente desistir e dizer: isto não funciona. A ciência não funciona assim. Para poder dizer esta por**** não funciona você precisa dominá-la bem. Precisa apresentar todo um estudo defendendo seu ponto de vista baseado em dados, experimentos e outros estudos. Há artigos e não posts em blog provando a eficiência do Test Driven Development para projetos de software em nosso momento da história da computação. Obviamente se você pretende fazer apenas CRUD utilizando um framework One Size Fits All - que não conterá regra de negócio alguma, o Test-first torna-se desnecessário.
Rua sem saída
Rua sem saída - a.k.a ficar sem ideias ou não saber como prosseguir - não é algo ruim. Quando atingida, nos faz pensar sobre nossas decisões de design e como elas podem melhorar. Geralmente, ruas sem saída vêm acompanhadas de pesquisas, que puxam leituras que podem gerar debates de ideias que resultam em evolução profissional e better code.
Imagine quando começou a pedalar: você não tinha qualquer equilíbrio. Talvez não tenha utilizado rodas de apoio, mas ainda assim, não tinha equilíbrio sob duas rodas. Após várias idas à praça e várias voltas com sua bike, você começou a ganhar equilíbrio. Equilíbrio traz confiança que traz mais experiência, que te faz buscar andar mais longe e consecutivamente, mais quedas. Após crescer e ao começar a pedalar mais longe, você buscará técnicas de respiração para ir mais longe com menos esforço físico. Se guia sua moto, irá pesquisar técnicas de pilotagem e direção defensiva. Com Test-first o processo é exatamente o mesmo, adaptado para software: inicia em Test-first, busca por técnicas, experimenta; falha; pesquisa mais; tenta novamente; obtém o resultado, aprendendo a técnica; inicia o ciclo novamente.
Test-first é um conceito. Assim como design de software. Isto quer dizer que não existe uma resposta certa; mas sim, soluções aceitáveis. Para obter uma das soluções, você precisa:
- Ler livros, papers;
- Discutir com co-workers, listas de discussão;
- Praticar;
- Praticar;
- Praticar.
Equipando-se para se proteger em becos escuros
Como dito anteriormente, há algumas known tips que ajudarão você a manter-se focado na solução. Unclebob, já falou inúmeras vezes sobre isto em seu(s) blog(s), vídeos e palestras. Um conhecido é o Three Rules of TDD.
Você deve sempre começar a feature, criando um teste daquilo que deseja obter como resultado - e o teste deve falhar.
Você deve escrever apenas um teste de unidade por vez e este precisa falhar. Lembrando que não compilar é um erro também.
Você precisa escrever apenas o necessário para aquele código passar. Lembre-se de que TDD é para preguiçosos.
Pode parecer um tanto dogmático, mas depois de entender os objetivos do Test-first, essa coisa faz sentido.
Testes são especificações. Um conjunto de especificações formam um software funcional. Working software é o objetivo que devemos ter. De nada adianta um monte de prática se ao final o software não é entregue como deveria. Sempre tenha isso em mente: esse teste precisa ter um propósito claro dentro do meu projeto. Se o teste não é claro, pode ser que você esteja caminhando para um beco escuro.
Red, Green, Refactor. É uma versão amigável das três regras do TDD. Teste falhando; Teste passando; Limpar seu código de produção para deixá-lo o mais legível e simples possível.
Simples? Métricas para Simples:
Single Responsibility Principle. Seu método, sua classe, seu módulo(mixin, trait, etc) precisa fazer apenas aquilo que se propôs a fazer. Métodos do objeto devem ser claros, objetivos.
Outra métrica é o DRY. Don't Repeat Yourself. Fez copy-paste parcial ou totalmente de um trecho de código para utilizar em outro lugar? Duplicou o código.
Law of Demeter ou Tell do not ask: apesar do nome medonho, a coisa é fundamental estar registrada na tua cabeça: ao invés de perguntar algo de um objeto para com o retorno do método fazer alguma coisa, peça que esse objeto faça o que você quer utilizando seu input. Exemplo:
public class Order {
public void add(Produto itemComprado, int quantidade) {
if (itemComprado.estaAVenda() && itemComprado.getEstoque().getQuantidade() >= quantidade) {
OrderItem item = new OrderItem(itemComprado, quantidade, this);
}
}
}
Ao invés de expor as particularidades do Produto
e Estoque
para o Order
, podemos simplesmente fazer justiça com as próprias mãos:
public class Order {
public void add(Produto itemComprado, int quantidade) {
if (itemComprado.temDisponivel(quantidade)) {
OrderItem item = new OrderItem(itemComprado, quantidade, this)
}
}
}
public class Produto {
public boolean temDisponivel(int quantidade) {
return this.estaAVenda() && this.estoque.temDisponivel(quantidade);
}
}
Assim, Order#add
agora passa apenas a adicionar produto à Order
, sabendo apenas que precisa saber se tem estoque para tal. Como saber se tem estoque é problema do Produto e seu estoque não de Order
.
Apesar de parecer óbvio, é um dos code smells que mais fiz e vi durante esse tempo. É natural falando/escrevendo, mas no meio do seu código, isso passa batido facilmente. Keep on track.
Concluíndo
Técnicas e conceitos como S.O.L.I.D, precisam estar em nossas cabeças para evitarmos andar em direção aos becos escuros. Ruas sem saída, são parte do processo de aprendizado que são mitigadas com leitura e muita prática. Test-first não se aprende em um mês ou dois. Nem por isto, testing é uma coisa chata. Em minha opinião, os testes tornam o dia-a-dia muito mais divertido, desafiador e proveitoso.
Magnun Leno : Corrigindo Erro de Chaves no Ubuntu
5 de Maio de 2014, 6:11 - sem comentários aindaHá alguns meses acabei precisando voltar a utilizar o Ubuntu no meu notebook (problemas de drivers no Arch Linux). Claro, quem me conhece sabe que o Unity não me agrada muito, e por isso optei pelo Ubuntu Gnome.
Recentemente, como todos sabem, foi lançada versão 14.04 do Ubuntu e, consequentemente, surgiu uma atualização para o meu notebook. A atualização ocorreu bem, exceto por um detalhe…
Corrigindo Erro de Chaves no Ubuntu é um artigo original de Mind Bending
Blog do Gio : Elegance Colors!
3 de Maio de 2014, 23:32 - sem comentários aindaO Elegance Colors permite mudar de cor e até mesmo alterar o próprio tema do Gnome Shell de acordo com o atual tema GTK, possibilitando também a personalização dos mesmos.
Descobri o Elegance Colors ao tentar instalar o pacote de temas e ícones Numix aqui no Arch. Depois de instalado não era possível alterar e tema do Shell para o Numix com o Gnome Tweak Tool.
Consegui mudá-lo através do “EC”, com a ajuda do amigo Matt Dobson, na opção de configurações gerais, como dá para ver na screen abaixo:
Legal não?!
O pacote está presente no repositório AUR, podendo ser instalado manualmente ou através do Yaourt, logo:
$ yaourt -S gnome-shell-themes-elegance-colors
Você pode saber mais sobre o Elegance Colors aqui!
Abraço!
Magnun Leno : Curso de Filosofia GNU - Parte 9
29 de Abril de 2014, 6:00 - sem comentários aindaNo último texto do Curso de Filosofia GNU os autores, Richard Stallman e Bradley M. Kuhn, chamam a nossa atenção para o confronto entre os conceitos de liberdade e poder. Em dias de Snowden e NSA o software livre deveria ganhar tração, mas parece que todos ainda se sentem muito confortáveis sabendo que uma minoria de poderosos dita as regras e controla todo o nosso dia-a-dia através do software que utilizamos.
Lembrando que este é um conteúdo livre obtido no CDTC.
Curso de Filosofia GNU - Parte 9 é um artigo original de Mind Bending
Blog do Gio : Numix no Ubuntu 14.04!
28 de Abril de 2014, 14:53 - sem comentários aindaVamos utilizar para personalizarmos o nosso Ubuntu 14.04 o pacote de ícones e temas Numix!
Porém esse pacote não está nos repositórios oficiais, então precisamos adicionar o repositório que o contém, logo:
$ sudo add-apt-repository ppa:numix/ppa
Feito isso precisamos atualizar os repositórios:
$ sudo apt-get update
Agora vamos instalar o pacote “completo” de temas e ícones Numix:
$ sudo apt-get install numix-gtk-theme shimmer-themes numix-icon-theme numix-icon-theme-shine numix-icon-theme-circle
O Ubuntu ainda não fornece por padrão uma ferramenta que nos permita personalizar os ícones e o temas do sistema, além dos que já são padrões (Como assim Ubuntu?!). Para resolver esse problema vamos instalar a ferramenta Unity-tweak-tool, logo:
$ sudo apt-get install unity-tweak-tool
Agora basta abrir a ferramenta Unity-tweak-tool e fazer as personalizações, escolhendo os temas que mais gostar:
Como resultado:
Aproveite!
Ps.: Essa versão 14.04 do Ubuntu, está notavelmente mais rápida e eficiente, pelo menos em um primeiro contato.
Abraço!
Farid Abdelnour : Videoclipe Solidariedade Feminina
28 de Abril de 2014, 12:38 - sem comentários aindaSolidariedade Feminina é uma música-protesto contra a violência que mulheres ainda sofrem em todo o mundo. É um trabalho autoral da cantora Thabata. O videoclipe foi produzido pela Gunga, com a colaboração da comunidade do Mercado Sul de Taguatinga.
Serviços prestados: direção, edição, filmagem e produção
Sotwares utilizados: Kdenlive e GimpAno: 2014
Helio Costa - hlegius : Introspecção
28 de Abril de 2014, 7:32 - sem comentários aindaMudança. Todos temem à mudanças. E não seria diferente ao codificar software, não é mesmo? Para que mudar se podemos continuar com nossa atual rotina simples e praticamente automática? Aquela coisa de chegar no trabalho, fazer o de sempre, como aprendeu no tutorial há tempos atrás ou que viu o ex-chefe fazer e até hoje executa assim sem questionamentos.
Em software isso recebeu um nome no livro The Pragmatic Programmer. Caso o cenário acima encaixe no seu code-style, você está programando por coincidência. Gosto do termo em português, pois ele é duplo sentido. Além de indicar o estado profissional acima, ele também implicitamente diz que você está na área por um mero acaso. * O livro não fala disso. Essa segunda parte é totalmente de minha autoria. Pode parecer xiita, mas te convido a refletir sobre isso mais a fundo.
Ao entrar no seu modo automático e passar a fazer coisas sem se questionar o porquê está fazendo (ou fazendo novamente) aquilo, você está programando por coincidência. Seguir aquele fluxo toda vez que depara com um problema passado sem questionar-se o motivo e se há melhor alternativa, você está programando por coincidência. Se, você assume coisas - isso vale muito pra teste - por exemplo que o erro X é causado pelo Y, simplesmente porque você acha que isto ocorre, você está programando por coincidência. Neste caso você não deveria assumir, mas sim provar que o problema é aquele mesmo.
Saindo da coincidência
Uma das formas de evitar esse ciclo de tédio e comodismo é justamente fazer Test-First. Explico os motivos:
- Lego Effect: como comentei no Teste Unitário?, começar pelo teste fará você pensar em como aquela funcionabilidade que pretende fazer irá se relacionar. Isso te faz pensar mais e consequentemente, dúvidas virão e você buscará saná-las (livros, pesquisa na Internet, Twitter, outros devs, projetos Opensource).
- Ah, a preguiça! Os testes te ajudarão a achar o menor caminho possível para aquela implementação. (teste é coisa de preguiçoso, lembra?) Isto te fará repensar técnicas. Com a prática de novas técnicas, você evoluirá como desenvolvedor.
- Não mais dúvidas sem resposta! Com teste, você pode testar não apenas o código de implementação mas também as suas suposições. Pensamentos do tipo: será que isto pode funcionar desta forma? serão mais frequentes, uma vez que o espaço entre o será que... e a resposta são apenas escrever um assertion simples e executá-lo.
- You on Rails. A prática do Test-first te mantém na linha de fazer o que realmente importa. Sem suposições vazias; Sem achismo; Você se antecipa dos problemas que poderá encontrar. Estar alinhado em fazer o que importa te torna introspectivo.
- Test & fail. Test & Learn.
- Não sendo mais telespectador. Você no controle! Não mais sendo guiado por processos e rotinas sem saber o motivo de estar fazendo aquilo daquela forma.
Questione-se; Reflita; Pense um pouco mais sobre sua forma de fazer as coisas. Isso é realmente a melhor forma de se obter o resultado que deseja?
Recentemente peguei meu Card Deck que ajudei a fundar (?) no Kickstater. Um dos cards que mais me chamou a atenção, até pelo fato de eu já ter feito isso anteriormente é o Remove your BEST idea.
Conseguiu achar uma solução para o problema? Ótimo! Ela poderá ser seu backup caso as coisas dê muito errado. Empenhe-se para achar uma outra melhor ideia. Vale muito a pena esse exercício.
Concluíndo
Test-first é uma das formas de acabar com a programação por coincidência. Test-first entretanto não irá te salvar de todo o mal do mundo - mas posso afirmar, por experiência própria que ele te coloca on track novamente.
A propósito, já leu o The Pragmatic Programmer: From Journeyman to Master? Permita-me dizer que você deveria se ainda não o fez pelo menos uma vez.
Arch Linux Brasil : screen-4.2.0 não consegue recuperar instâncias antigas
24 de Abril de 2014, 20:00 - sem comentários aindaLeandro Inácio escreveu:
Usuários do programa screen não estão habilitados a recuperar instâncias antigas depois da atualização para a versão 4.2.0; isto acontece devido ao upstream ter realizado muitas mudanças internas, e trocada a comunicação através de pipes para sockets. Por favor, certifique se suas instâncias atuais não são mais necessárias antes de atualizar.