Magnun Leno : Programando Java sem IDE
5 de Junho de 2014, 10:23 - sem comentários aindaHá algum tempo eu concluí minha Pós-Graduação (ainda estou devendo um texto sobre isso aqui) e, devido a "regras institucionais", fui "instigado" (*cof*obrigado*cof*) a usar Java. Sendo eu um usuário de VIM, uma das coisas que mais me irrita ao programar em Java é essa amarração de IDE. Então resolvi fazer algo que poucos programadores Java sabem, programar sem IDE.
Sim, eu sou cabeça dura a esse ponto. Meu fluxo de trabalho no VIM já é muito bem estabelecido, e me adaptar a uma nova ferramenta com inúmeras limitações (quando comparado à edição no VIM) não é nada agradável.
Programando Java sem IDE é um artigo original de Mind Bending
Arch Linux Brasil : Perl atualizado para 5.20
3 de Junho de 2014, 20:00 - sem comentários aindaLeandro Inácio escreveu:
Perl 5.20, como qualquer outra nova versão do perl, requer que todos os módulos que o código não seja perl puro precisa ser recompilado. Fizemos isto em todos os pacotes em nossos repositórios.
A última grande atualização mostrava uma mensagem de erro quando tentava carregar os módulos compilados com a versão errada, 5.20 parece causar falha de segmentação. Por favor, certifique-se de recompilar todos os módulos e binários padrão instalados com CPN que aponta para libperl.so.
Atenção para o meu post na arch-dev-public para um script que ajuda a identificar estes pacotes.
URL da notícia: https://www.archlinux.org/news/perl-updated-to-520/
Helio Costa - hlegius : Code Coverage: uma das consequências do Test-First
2 de Junho de 2014, 7:01 - sem comentários aindaQuando comecei a tentar testar meus códigos, iniciei também a busca por métricas que indicassem que eu estava no caminho correto, evitando me desvirtuar durante essa mudança de pensamento ao codificar software. Na época, o manual do PHPUnit indicava que o framework de teste possuia ferramentas para cobertura de código. Eis que fui apresentado ao Code Coverage.
"Uau! Esta é uma métrica indiscutível para mensurar a qualidade de meus testes!" - pensei na época.
Depois que tomei conhecimento da análise da Cobertura de Código pelos testes, não se falava em outra coisa a não ser:
Neste projeto o objetivo é ter 90% de cobertura de código; Mas no próximo, aaaaah, no próximo nada menos do que 98% pode ser aceito.
Sério. Ficávamos numa neura assim mesmo. Não era para menos. Pense comigo: sendo como objetivo do teste, garantir que o código de produção funcione, nada mais sensato do que cobrir a maior quantidade do Código de Produção (todo código que não é de teste ou do framework no projeto, assim digamos) possível. Ou seja: a ideia é que nossos testes passe pelo maior número de linhas possíveis para garantirmos que toda linha está funcionando como deveria em seu devido fluxo. Por exemplo:
class User {
public void fazLalala(String comFoo) throws Exception {
if (comFoo == null) {
throw new Exception("Lascou!");
}
if (comFoo.startWith("Lalala")) {
this.doSomething(comFoo);
} else {
this.doAnother(comFoo);
}
}
}
No caso deveriamos exercitar os 3 possíveis casos: lançamento de exception
; if == true
e if != true
, afinal o teste é para verificar se a exception é lançada somente quando necessário e o if/else trabalhar conforme o esperado vindo do input do método.
Porque este pensamento está incorreto
Testar as possibilidades do comportamento de um método de um objeto é fundamental, porém, no caso acima, eu estava olhando pela ótica errada.
Eu estava testando para obter Code Coverage ao invés de obter Code Coverage por estar testando.
Inversamente a Matemática, no português a inversão dos valores podem não serem equivalentes, como neste caso. Testar com o objetivo de obter Code Coverage não é um bom motivo; agora, obter um bom Code Coverage por causa do teste é algo muito bom.
Para ilustar o problema de Testar Code Coverage Driven, vamos ver o código abaixo:
class User {
public void addCredentials(String username, String password) {
// do something...
}
public String getName() {
return "...";
}
public String getCredentials() {
return "...";
}
public String getLastname() {
return "...";
}
}
Ao Testar focado em obter Code Coverage, algo assim poderá ser encontrado na classe de teste do User
:
class UserTest {
@test
public void testGetName() {
user = new User();
user.setName("name");
assertEquals("name", user.getName());
}
@test
public void testGetLastname() {
user = new User();
user.setLastname("last name");
assertEquals("last name", user.getLastname());
}
@test
public void testAddCredentials() {
user = new User();
user.addCredentials("username", "senha_marota");
assertEquals([["username", Digest::MD5.hexdigest("senha_marota")]], user.getCredentials());
}
É possível observar dois problemas aqui:
- Getter/Setter foi testado isoladamente, como se fosse uma regra de domínio.
- O teste do addCredentials teve o mesmo tratamento do que os Getters/Setters.
Não me entenda errado: não existe nada que diga para não testarmos getters/setters. O problema é: testar coisas que serão testadas em métodos futuros por consequência. Por consequência que digo seria:
@test
public void testCredentialUsernameShouldNotEqualsToName() {
String name = "Mesmo nome";
user = new User();
user.setName(name)
user.addCredentials(name, "senha_marota");
assertEmpty(user.getCredentials());
}
Assumindo que uma das regras da Credencial é que o username não seja igual ao nome do usuário, um teste deste tipo já nos garante que o setName()
e o getName()
funcionam como esperamos que funcionará, pois o addCredentials
irá chamar o getName
para achar o nome do usuário:
public void addCredentials(String username, String password) {
if (getName() == username) {
// do nothing / throws exception
}
}
Com isto, o teste testGetName()
pode ser dispensado tranquilamente, pois ele foi testado em consequência ao teste de negócio testCredentialUsernameShouldNotEqualsToName
.
O segundo problema é ainda mais grave: por testar getter/setter, você poderá cair em copy/paste nos testes pela sua similaridade e talvez isso o fará cair na armadilha de esquecer de testar o que realmente precisa de atenção por conter Regras de Negócio (Domínio) envolvida, como o addCredentials
tem. Testes válidos para a classe proposta seriam: testAddNewCredential
, testCredentialUsernameShouldNotEqualsToName
e talvez até testDuplicatedCredentialShouldRaiseError
.
Porque este pensamento está correto
A corretude de Testar Orientado a Cobertura de Código está em se e somente se o Teste fosse para garantir que o código funciona o que não é o objetivo do teste de unidade. Por não ser objetivo principal, testar para satisfazer a cobertura de código não trará garantia alguma, além de que o software não têm erros de sintaxe ou fluxo. É alguma coisa? Sim, claro! Mas estará longe da grande vantagem que Test-First traz: montar sua aplicação da forma mais orquestrada possível.
Concluíndo
Foque nos testes que agregam valor ao negócio(domínio) do software que os métodos auxiliares serão avaliados em consequência, trazendo uma cobertura altíssima e mais: confiável. Exercite seu addCredentials
criando um teste para cada regra de negócio que lhe foi solicitada, dando segurança real no seu Código de Produção.
Helio Costa - hlegius : Mock elevado à enésima potência
25 de Maio de 2014, 7:35 - sem comentários aindaMocks: mock é um assunto polêmico em Software Testing nos dias atuais. Quase todos defendem o uso, Robert Martin que o diga. Logo, você começa a ler, um passo depois está fazendo seus próprios mocks e gosta do que vê. Num piscar de olhos, está Mockando tudo que pode e fica feliz com isto.
Ver um teste com 3, 4, 5 até 6 mocks pode no começo parecer algo sensacional, mas uma coisa que é necessário aprender sobre Mocks é que assim como seu teste, ele fala. Não uma mutação do say do OS X, mas com sua própria e simples linguagem: em excesso torno-me algo extramemente ruim. É exatamente isso que ele diz aos berros quando ele é super utilizado em um mesmo Test Case.
Pecando pelo excesso
Ao Mockar, esqueça essa frase popular de que é melhor pecar pelo excesso. Overmocking é tão ruim quanto não mockar at all. Se eu tivesse que escolher entre Mockar excessivamente ou não mockar nada, eu optaria pela segunda opção mantendo todas minhas dependências levemente soltas. (assunto para posts futuros!)
Quando você estiver forçado a stubar/mockar muita coisa para que um teste seu possa ficar isolado o suficiente para então testar a funcionabilidade (que você isolou), isso quer dizer simplesmente o seguinte: seu design ficou acoplado e como tal, precisa ser repensado para algo menos atrelado. Deixando suas dependências (outras classes) mais independentes, a quantidade de mocks por teste cairá e seu problema sucumbirá.
O acoplamento é aterrorizante para alguns ou/e em algumas situações, mas eles acontecem quando se perde o controle do que está criando ou quando se modifica o comportamento sem modificar como as coisas se falam. Sabe aquela história de: "ah, modifica isso aqui rapidinho só para X fazer Y." - quando você muda, 99.9% de chances de criar acoplamento e a consequência disso reflete diretamente sobre a quantidade de itens mockados por teste.
Mocks por Teste
Matematicamente dizendo, não há um número exato para mocks por teste (mocks/teste), mas eu tenho meu limite pessoal baseado em nada erro e acerto: 3 mocks/teste para mim é o limite aceitável. Ao ultrapassar isto, automaticamente aquele meu código que o teste exercita cairá na minha Lista de Redesign. Isto forcará a repensar se é caso de refazer ou se é uma exceção. Tudo questão de análise caso a caso. Caso você tenha uma abordagem diferente com seu limite por teste, comente ao final ;)
Mockar apenas o que te pertence
Um ponto defendido por alguns é o de only mock what you own, em outras palavras seria: não mock seu framework; não mock sua API; Mock apenas o que você criou. Aquilo que faz parte do seu domínio. Seu framework é um domínio transversal, ou seja, é um domínio que auxilia você a criar seu próprio domínio. Lembre-se disso!
Com o Rails em particular, eu acabei por várias vezes não seguindo isto. Na verdade, eu não sou muito a favor disto pode me julgar, xingar, etc.. O motivo é simples: o Active Record se mistura de uma forma tão intríseca ao seu domínio, que em alguns momentos é difícil dizer aonde está a linha que separa o framework do seu código. Por este motivo, eu já fiz mock dos finders
do ActiveRecord.
O problema de mockar o framework é que você ao fazer esse tipo de maluquisse precisa estar atento é de que ao mocka-lo, você presume como ele irá se comportar dado um certo input porém se por algum motivo sua intuição/palpite estiver errado, seu teste te dará um resultado errado. Com o resultado errado, seu teste passará, mas na hora de rodar o código de produção sem os mocks, o comportamento esperado não acontecerá. O Teste te deixará na mão, por causa do mock e por falha sua.
Mockar o framework é muito perigoso. O teste poderá tornar-se arisco. O true poderá ser false e você precisará lidar com isto.
Concluíndo
Mock é um aliado importantíssimo em Test-First. Sabê-lo utilizá-lo é ainda mais importante.
Magnun Leno : Palestra de Introdução ao Git
20 de Maio de 2014, 9:00 - sem comentários aindaHá muito tempo atrás, eu e um grupo de pessoas participamos de um projeto chamado Criandeiros. Esse projeto gerou algumas palestras bem interessantes que já foram citadas aqui. Entretanto, devido a diversos fatores, esse grupo se desfez e eu postei por aqui apenas as palestras de Particularidades do Python e Modelo MVC.
Curiosamente, depois de gravar um episódio como convidado do SciCast, acabei me lembrando de uma palestra muito legal que eu preparei para o Criandeiros, o tópico era o versionador Git…
Palestra de Introdução ao Git é um artigo original de Mind Bending
Helio Costa - hlegius : Definir classes não é programar com orientação a objetos: Ciclo de vida.
19 de Maio de 2014, 7:35 - sem comentários aindaHá pouco mais de 2 anos, falei sobre esse tema na PHP Conference Brasil e acho válido revisitá-lo uma vez que muitos desenvolvedores sentem orgulho em dizer que programam orientado a objetos, mas ao fazer uma simples pergunta acabam não sabendo respondê-la:
O que é Orientação a Objetos ?
Alan Kay, criador da linguagem Smalltalk e um dos primeiros defensores da orientação a objetos, a explicou da seguinte forma:
"The big idea is "messaging" (...)
Pronto, fim do post. Obrigado por ler.
Messaging ?
De nada adianta falar sobre Test-First, Princípios de Orientação a Objetos, Mocking, AntiPatterns uma vez que não se conhece o núcleo da Orientação a Objetos.
O grande cerne da questão é justamente a troca de mensagem entre objetos através de seus métodos. É assim que Alan Kay defendeu e é assim que o Smalltalk funciona. Recentemente, alguns desenvolvedores, especialmente em Ruby, têm voltado a reforçar o propósito em OO.
A melhor forma de manter seu código desacoplado e "falante" é forçar os objetos a trocarem mensagens. Lembra do Tell Don't Ask? Pois é, aqui isso é parte chave para atingir-se tal objetivo.
Vou repetir:
- http://c2.com/cgi/wiki?TellDontAsk
- http://pragprog.com/articles/tell-dont-ask
- http://martinfowler.com/bliki/TellDontAsk.html
- Tem a versão do Giovanni Bassi, do .NET Architects também;
Pronto, acho que deu para entender o quão importante é manter no objeto a responsabilidade de manipular os próprios dados (armazenados em vossos atributos).
O Ciclo de Vida de um Objeto
Já parou para pensar em qual seria o ciclo de vida de um objeto?
Bom, inicialmente ele Nasce, depois Cresce, Continua disponível e finalmente Morre.
O nascimento de um objeto
O nascimento do objeto é através de seu construtor. Simples, porém muitas vezes ele acaba ignorado, ainda mais quando vicia-se em utilizar frameworks arquiteturais sem entender o motivos das coisas.
Correto:
Employee.new(name: "Durval", lastname: "da Silva", cpf: "123.123.123-X")
new Employee("Durval", "da Silva", "123.123.123-X")
Incorreto:
durval = Employee.new
durval.name = "durval"
durval.lastname = "da Silva"
durval.cpf = "123.123.123-X"
durval = new Employee();
durval.setName("durval");
durval.setLastname("da Silva");
durval.setCpf("123.123.123-X");
O motivo é simples: o construtor é o contrato que nos diz: "para você obter um novo objeto tipo Employee
, você precisa obrigatoriamente me informar: Nome, Sobrenome e CPF, pois caso contrário, você criará um Employee
inválido."
E é justamente o que o exemplo incorreto faz: cria um Employee
sem dado algum. Quem garante que eu irei chamar setName
, setLastname
e setCpf
depois? Eu posso esquecer. Pode nem ser eu o responsável por utilizá-lo depois. (APIs-like).
Lembre-se o construtor é a certidão de nascimento do objeto. Não tire dele esse direito. Brasil, país rico é país...
Cresce
Aqui temos outros métodos que mudarão o status de nosso objeto ao longo de sua vida. Nem sempre é com setter - outro erro comum daqueles que programam por coincidência. Veja exemplos:
Correto:
employee.exame_admissional = arquivo_pdf_do_exame # snake case r0cks
employee.setExameAdmissional(arquivoPdfDoExame)
employee.definir_credencial_de_rede(username: "new_username", password: "983hJfh78")
Incorreto:
objeto_credencial = Credencial.new(username: "new_username", password: "9789237498")
employee.credencial = objeto_credencial
objetoCredencial = new Credencial("new_username", "3798472398478234")
employee.setCredencial(objetoCredencial)
Neste caso, o incorreto viola o encapsulamento da Credencial, deixando a cargo do cliente conhecer como a Credencial é criada. Para entender melhor, desenho:
Cliente é toda classe que utiliza outra. Só para deixarmos as coisas claras por aqui.
O problema aí é que no caso o Controller precisa saber como construir Employee e Credencial, além de precisar conhecer como relacioná-las. Um exemplo mais OOP seria:
Agora, o Controller precisa apenas lidar com Employee
e este lidará com a Credencial
. Em pseudocódigo, ficaria:
# Ruby
class Employee
# construtor e outros métodos ocultados
def define_credencial(username: username, password: password)
@credencial = Credencial.new(username: username, password: password, employee: self)
end
end
# Java, et al.
class Employee {
private Credencial credencial;
public void defineCredencial(String username, String password) {
credencial = new Credencial(username, password, this);
}
}
Neste caso, Credencial
é um Value Object
pertencente ao Employee
. Esse tipo de relacionamento é parte do Domain-Driven Design e é chamado de Aggregate Root.
Aggregate root são úteis quando você tem um relacionamento aonde a Parte (Credencial) é totalmente dependente do Todo (Employee). Em outras palavras: a Parte só tem vida quando o Todo tem vida. Não é legal que uma Parte tenha vários Todo(s).
Continuando disponível
Em orientação a objetos, nossa linha de pensamento deveria ser um pouco mais ampla. Ou seja, devemos pensar que uma vez que o objeto é criado (instanciado) ele ficará disponível até que alguém o mate (remova da memória). Enquanto ninguém o remover da memória, ele continuará vivo.
É importante esquecer o meio/tipo de armazenamento aqui. Robert Martin (@unclebob) falou sobre isso na sua must watch palestra na Ruby Midwest 2011 - sério: assista até o fim. Você será outro depois disso ;)
Morre
O objeto é removido através do Garbage Collector, Removido com ORM, etc. Aqui não há novidade mesmo.
1 imagem, 1000 palavras
O meio de vida do objeto (aquele dentro do retângulo) é aonde a maior parte dos objetos estarão. Ao buscar um objeto com um Repository
por exemplo, devemos pensar que o objeto estava em memória, já construído e do jeito que o deixamos da última vez que trabalhamos com ele. Ou seja: o Repository
não dará new
novamente, pois o objeto já existe. Pelo que me lembro, o Doctrine 2 seguia isto: ao recuperar um objeto do Repository
o construtor não era chamado novamente - o que é excelente, pois o Ciclo de Vida do Objeto não é quebrado!
Concluíndo?
O tema é extenso assim como Test-First. Conhecer bem o que a Orientação a Objetos reserva e espera de você é pré-requisito para iniciar com Teste de Software em aplicação Orientada a Objeto. Na sequência, continuarei a falar sobre Object Oriented Design para permitir que se veja além ao testar software.
Magnun Leno : Corrigindo Arquivos CSV com Python
16 de Maio de 2014, 10:32 - sem comentários aindaOntem eu estava conversando com alguns colegas e um deles acabou soltando que estava tendo que fazer um trabalho braçal: Corrigir um arquivo CSV manualmente, pois a rotina que processava sua entrada só compreendia campos do CSV se eles estivessem envolvidos entre aspas duplas.
Na hora eu falei pra ele, "Use Python!", e em seguida todos me disseram que era trabalho de mais escrever um programa só pra isso. Será mesmo?
Corrigindo Arquivos CSV com Python é um artigo original de Mind Bending
Arch Linux Brasil : screen-4.2.1 também não consegue recuperar instâncias antigas
14 de Maio de 2014, 20:00 - sem comentários aindaLeandro Inácio escreveu:
Melhorias do upstream no screen-4.2.1 deixará usuários incapazes de recuperar instâncias antigas criadas com versões 4.2.0 ou mais antigas. Por favor atualizem para screen-4.2.1-2 apenas quando elas forem desnecessárias. Desculpem novamente pelo inconveniente.
Arch Linux Brasil : Gerenciando pacotes Haskell com GHC 7.8.2
14 de Maio de 2014, 20:00 - sem comentários aindaLeandro Inácio escreveu:
Mudanças que vieram nesta versão, incluem:
-
Mover todo pacote que não seja ghc ou cabal-install para [community]. Isto permitirá um melhor suporte das principais bibliotecas do haskell desde que não uso estes pacotes, devido ao cabal-install.
-
Passos recomendados para que o usuário possa instalar os pacotes são os seguintes:
-
Usando o cabal-install para instalar os pacotes haskell. Isto permite ao usuário acessar todo pacote haskell no hackage. O problema é que você agora está usando pacotes que são gereciados fora do pacman. Isto é usualmente a melhor opção se você está desenvolvendo qualquer aplicação haskell devido a nova sandbox que o cabal-install 1.18 tenha introduzido.
-
Usando pacman para instalar os pacotes haskell. Isto permite que o usuário tenha acesso a um pequeno subconjunto de pacotes hackage, os quais são conhecidos por funcionarem no archlinux e são geralmente bons o suficiente para desenvolvedores não haskell.
-
Usando um repositório não oficial chamado Arch Haskell. Você pode encontrar mais informações sobre o repositório na seguinte página
-
URL da notícia: https://www.archlinux.org/news/managing-haskell-packages-with-ghc-782/
Magnun Leno : Hack ‘n’ Cast v0.1 - Cultura Hacker
13 de Maio de 2014, 7:22 - sem comentários aindaSejam todos bem vindos ao primeiro episódio do Hack ‘n’ Cast! É isso aí pessoal, após muito tempo juntando ideias, convidado pessoas, perdendo participantes, levantando tópicos, esboçando logos, testando equipamentos e fazendo testes de edição, finalmente posso anunciar esse novo projeto do site Mind bending em conjunto com o Bruno Barbosa (do Algoritmizando) e com o Ricardo Medeiros (nosso estagiário).
É isso aí, quem me conhece pessoalmente sabe que sou um grande fã da mídia podcast e que tenho influência de vários podcasts, o que é perceptível nessa edição. E como o logo aí em cima ressalta, ainda estou considerando esse projeto como estando na fase Beta (o Ricardo diz Alpha), ainda não definimos uma periodicidade e ainda não temos um Feed para assinatura (vou ter que hackear o Pelican pra isso), mas estamos trabalhando para colocar tudo em ordem.
Hack ‘n’ Cast v0.1 - Cultura Hacker é um artigo original de Mind Bending