Magnun Leno : Hack ‘n’ Cast - v0.3 Introdução ao GNU/Linux
5 de Julho de 2014, 19:38 - sem comentários aindaO GNU/Linux foi a mola propulsora da Internet como a conhecemos hoje e, por isso, é uma peça de tecnologia fundamental pra qualquer profissional. Hoje vamos saber um pouco de sua história, entender porquê escrevemos GNU antes de Linux e discutir um pouco sobre a disputa épica entre Linus e Tanenbaum.
Baixe o episódio e leia o shownotes
Magnun Leno : UNIX System Signals em Python
30 de Junho de 2014, 14:00 - sem comentários aindaApós publicar o texto sobre UNIX System Signals em C, percebi que pode ter dado a impressão que apenas a linguagem C possui essa integração. Com isso, escrevi este artigo para demonstrar o mesmo mecanismo demonstrado pelo Fernando Almeida.
Todo o conceito de sinais, sua dinâmica de envio e uma tabela listando todos os sinais existentes está disponível aqui. Então vamos direto para o código!
UNIX System Signals em Python é um artigo original de Mind Bending
Farid Abdelnour : SucoLento – Ep.01 (piloto)
27 de Junho de 2014, 10:03 - sem comentários ainda“SucoLento” é uma série de vídeos sobre sucos verdes.
Este é o episódio piloto da série, estamos brincando e experimentando com a linguagem visual, e queremos saber sua opinião.
Você tem alguma sugestão ou receita para darmos continuidade ao projeto? Deixe seu comentário!
Magnun Leno : UNIX System Signals em C
25 de Junho de 2014, 11:51 - sem comentários aindaSempre que desenvolvo programas, tento saber as regras básicas de cada sistema operacional. Os motivos? Bem, por dois simples motivos: Compatibilidade e Praticidade
Compatibilidade porque esses programas, para serem considerados compatíveis, devem obedecer as regras e práticas do sistema operacional alvo. Essa compatibilidade também pode ser chamada de compliance. Praticidade porque muito do que o programador precisa já existe no sistema operacional. Nada de reinventar a roda!
UNIX System Signals em C é um artigo original de Mind Bending
Farid Abdelnour : Mulheres Brincantes
17 de Junho de 2014, 8:03 - sem comentários aindaEntre ritos e brincadeiras, o espetáculo Mulheres Brincantes reúne quatro histórias de transformação vividas por mulheres brincantes da cultura popular. Protagonistas invisíveis que cantam, dançam, botam bonecos e máscaras. No palco, vida e morte, passado e presente, a tradição e o contemporâneo. Essas mulheres são meninas, mães, avós, trabalhadoras, guerreiras que superam a dor e celebram o prazer pelo fazer da arte. As cenas trazem bastidores das tradições, com intuito de revelar o protagonismo, a fragilidade, a força e a resistência dessas mulheres. Inquietações femininas que são, no seu sentido mais profundo, inquietações humanas universais. Tem dramaturgia e trilha sonora criadas em processo colaborativo. A direção musical é de Daniel Carvalho e a direção teatral de José Regino.
Cliente: Casa Moringa
Serviços realizados: programação visual e fotografia
Softwares utilizados: Inkscape, GIMP e FontMatrix
Ano: 2014
Magnun Leno : Registradores no VIM
16 de Junho de 2014, 12:30 - sem comentários aindaEsses dias surgiu uma pergunta do Arthur na lista de discussão de usuários de VIM do Brasil sobre "realizar deleções sem sobrescrever o texto já copiado". Parece uma coisa boba para quem vem de outros editores, mas tudo no VIM é extremamente profundo, se você se dedicar a explorar uma pequena funcionalidade você pode perder o dia todo e não ter lido/entendido tudo sobre o assunto.
"E por quê perder tanto tempo entendendo uma funcionalidade do VIM pode ser útil? Não basta apenas saber o básico e seguir adiante?" Não, não basta. Simplesmente porque o VIM é como um monstro de LEGO e se você entender melhor uma pequena peça, você vai ver que pode usar essa peça combinada com centenas de outras, e assim ter um fluxo de trabalho extremamente otimizado.
Registradores no VIM é um artigo original de Mind Bending
Helio Costa - hlegius : Unit Testing em aplicações já existentes e sem teste
16 de Junho de 2014, 6:35 - sem comentários aindaad: salve o Feed do blog no seu leitor e passe a ler os posts antes d'eu divulgá-los.
Se você achou interessante começar uma aplicação com Test-Driven Development, o que dizer sobre um dos fatores mais comuns em nossa área que é assumir um projeto que já está em produção, porém não possui testes de unidade ?
Softwares legados também possuem direito de ter seu lugar ao sol !
Cenário clássico
Você entra para uma nova equipe de desenvolvimento. Como um tester acostumado com as práticas do Test-First, você vai cegamente à procura do diretório(s) com os testes para: executá-los afim de descobrir se configurou o ambiente corretamente; ler, afinal quer entender um pouco mais do projeto; depois de vasculhar /tests
, /spec
, /xpto/namespace/module/tests
e não encontrar nada você descobre que: o projeto não possui testes!
Normal? Infelizmente sim - Há muitos desenvolvedores que não gostam de testes. Os motivos variam e é assunto futuro -, vários projetos que vi não possuiam testes at all. Em todas às vezes porém, meus gestores eram favoráveis a adoção e receptivos a mudança de comportamento que isto causaria.
Sem testes e com carta branca para começar a mudar o cenário. O que fazer agora ?
$ ./configure
Antes de tudo, você precisa ver como o projeto está feito. Passe umas horas ou dia olhando o que tem ali e por onde poderia começar a trabalhar. Após isto, vamos listar coisas importantes sobre o código que já funciona em produção:
- Não faça testes de unidade do que já existe;
- Não seja convencido a fazer testes de unidade do código existente;
- É insanidade querer testar as partes de um código que já funciona. Não faça isso;
- Não faça teste de unidade do código existente.
Motivo para todos itens acima é o mesmo: teste de unidade é seu guia para construir o software requisitado da menor e melhor forma possível. Ele é um guia e não uma Bug Tool. Se o código já está presente, você, se cair na tentação de fazer teste daquilo, forçará seu teste a passar naquele código. Seu teste pode até pegar um bug, mas você, novato no projeto, não saberá que é um bug e acabará mudando o teste para passar naquela condição bugada. Costumo dizer que testar código já feito é perder tempo.
Vou comentar dois cenários aqui: a) você precisa criar um módulo/integração/package novo dentro desse projeto legado; b) você precisa adicionar testes ao código existente.
Vamos lá :)
$ make all
Vou pegar os dois casos e comentários sem separado:
a) Você precisa criar um módulo/integração/package novo dentro desse projeto legado
Para mim, dentre os dois esse é o mais fácil. Tudo que você precisa fazer é começar o módulo novo de forma isolada. Ou seja: evite depender do código sem teste dentro do seu módulo novo. Você pode obter isso com o uso de Adapters. Crie seu módulo novo, seguindo Test-Driven Development e toda vez que precisar da colaboração de uma classe/objeto que não tem o devido teste, crie um Adaptador que isolará aquela dependência instável do seu código novo. Isso te dará maior confiabilidade no que está fazendo.
Isole toda a comunicação do seu módulo novo, com o uso de Façades.
Supondo que você está fazendo um módulo de pagamento, crie uma façade para seu código e a faça prover os recursos que o restante do software necessitar:
class PaymentFacade {
public ... create(...);
public ... createRecurrent(...);
public ... getPayments(Datetime forDate);
public ... cancelRecurrent(Integer paymentId);
public ... processPayment(Integer paymentId);
....
}
Na sua Façade, trafegue valores escalares e não objetos do sistema. Isto tornará seu module de pagamento mais isolado e protegido do código não testado.
b) Você precisa adicionar testes ao código existente
Lembre-se: não adicione testes de unidade ao código já existente e sem teste. Partindo disto, seguimos:
Este é mais complicado. Costumo utilizar uma técnica do livro Domain-Driven Design de Eric Evans chamada Anti-corruption Layer.
A ideia aqui é fazer igual na figura: o "ACL" é o Anti Corruption Layer, a camada que irá defender seu código novo do código legado sem testes.
Dando um zoom nesta imagem, tudo que precisamos fazer é criar uma layer que conterá classes/objetos ou/e métodos em classes existentes que farão adapters/façades, traduzindo o que o sistema já tem para conseguirmos encaixar no que estamos fazendo.
Client System: seu sistema legado Anticorruption Layer: o meio entre seu sistema legado e seu módulo novo External: seu código novo, totalmente Test-First.
Não sinta-se intimidado em tentar fazer deploy de uma versão funcional com seus adapters, façades e anticorruption layer. Eu já mantive em produção por algumas semanas código "macabro", cheio de "fios pendurados" e coisas em aberto, até que eu pudesse ajustá-las para em deploys futuros, pudesse removê-los tranquilamente.
# make install
Agora que consegue deployar seu código novo e testado junto do software que tinha antes sem testes de uma forma até que harmoniosa e isolada, você precisa derrubar o muro de Berlim que construiu: você precisará refatorar seu código legado e sem testes para que comece a adicionar testes nele também. Ao adicionar testes no código refeito, você poderá remover os Adapters, Façades e até a Anticorruption Layer daquele pedaço que isolava o código sem testes do código "novo".
Isto é uma parte importante, pois você precisará fazer tudo de dentro para fora. Explico: fora é a parte mais próxima do seu cliente possível (Controller, API, etc); dentro é a parte mais próxima do código que está isolando/refatorando. Sempre venha de dentro para fora nas tuas refatorações, pela razão de que assim, você afetará a menor quantidade possível de classes, pois identificará logo de pronto até onde pretende refatorar, colocando logo na sequencia disto seus adapters/façades.
Concluíndo
Agora você tem um bom motivo para utilizar adapters e façades. Esse tipo de refatoração é uma das minhas favoritas, pois envolve muito de lidar com isolamentos bem construídos e como manter isto de forma que não quebrará todo o software. O resultado final é uma aplicação funcional com um toque de código novo e testado ao mesmo tempo.
Recados
Na próxima semana, 23/06/2014, não apresentarei um post novo sobre Test-First. Dia 30/06 (última segunda do mês) porém, voltarei com o tema semanal do blog. Aproveite para revisitar algum post ou mesmo discutir o tema com seus conhecidos ou comigo ;)
Helio Costa - hlegius : Arquitetura, Rails e o ecossistema Ruby
13 de Junho de 2014, 7:35 - sem comentários aindaRails acredito que seja a primeira palavra a vir à cabeça quando se fala em Ruby. A coisa é tão intensa, que não é difícil encontrar vagas e programadores entitulando-se: Rails Developer. Nem Engenheiro de Software; Nem (Back|Front)end Developer, tão pouco Ruby Developer.
Que o Rails é o framework mais conhecido dentro (e até fora) do mundo Ruby isso é um fato. Fato também é o quão simplificado o desenvolvimento utilizando ele é; Mas, já parou para pensar no trade-off existente aí?
Architecture: The Lost Years
Keynote apresentado pelo Unclebob lá no distante 2011, sobre o quão ofuscados ficamos com o Rails - e o que isso trouxe como consequência. Não é um ataque direto ao Rails, mas sim um: hey, vamos acordar pra vida e utilizar o Rails de uma forma um pouco mais decente ?
Se você nunca viu esta palestra. Pare de ler agora e veja até o final. Depois, continue lendo (pois vou assumir que você viu ao keynote)
Obviamente que ele não é o único a pensar assim. A apresentação dele gerou diversas threads na Internet sobre como fazer um aplicativo Rails desacoplado e mais sob o controle do desenvolvedor do que do framework.
Acredito que o desejo de muitos seria ter uma especie de Symfony Framework + Doctrine 2.x para Ruby. Desacoplamento. O desenvolvedor escolher as peças; ou como o Unclebob disse na palestra: acessar o diretório do projeto e pensar: "Ah, isso é um software de X; ao invés de: Aaah, isso é um app Rails."
Moldar o Rails para algo mais Domain-Driven Design
Resolvi apostar. Aposta simples, silenciosa. Aproveitei a (maior) modularidade do Rails 4 para começar a extrair algumas coisas e definir uma estrutura nova de diretórios. Preferir transparência no domínio às convenções do Rails. Movi tudo para o /domain/(modulo)/
.
- O Rails convenciona que Models devem estar dentro de
app/models
, caso contrário, o ActiveModel não funciona corretamente as relações de ORM.
Ao topar com este empecilho, não quis me alongar nisso e preferi manter todos os "Models" dentro do diretório que se é convencionado. Já viu a sopa de diretórios que isso ficou, né ? /domain
; /app/models
.
- O ActiveRecord possui features intrigantes, como por exemplo os scopes, porém os Contras são maiores do que os Prós.
O Avdi Grimm no livro Objects on Rails mostrou passo a passo como ele construiu um software Rails-based postergando relacionar suas entities ao ActiveRecord. No final, ele preciso modificar bastante coisa para tê-las in place. Alguns testes precisarão ser de integração (scopes, olho para vocês) - pois teste de Unidade Comportamental (Unit-Testing Behavioral) não garantirá que o scope está correto mesmo.
Pode parecer xiitismo, mas o ActiveRecord é pesado. E esse peso aparece ao rodar os testes de unidade. Mesmo utilizando Test Double, só de precisar subir toda aquele estrutura do ActiveRecord, o processamento já fica mais lento do que se as entidades fossem livres do meio de persistência.
- Convention Over Configuration em um framework Arquitetural (One Size Fits All) é nocivo para adotar meios e métodos alternativos.
Seguir o caminho sem o Rails
Optar por deixar o Rails de lado, utilizando somente o que você precisa e quando precisa é uma das alternativas dos Rubistas (outside Brasil) atualmente. Isso explica a popularidade que o Sinatra ganhou nos últimos tempos. Sinatra pois ele fornece uma interface simples entre o Rack e sua aplicação web. Sinatra, pois ele é somente isso, deixando todas as demais decisões para você. Com isto em mente, vale lembrar de que precisará criar suas próprias coisas.
Algumas muito simples outras nem tanto:
- Criar e configurar seu
config.ru
para que o Rack o leia e suba um stack; - Configurar seu
spec_helper.rb
outest_helper.rb
para Unit Testing com RSpec ou MiniTest; - Criar seu Environment Manager, para conseguir distinguir Development, Testing e Production modes - Dica:
ENV['RACK_ENV']
pode ser usado pra isto; - Configurar seu
Rakefile
para manipular Rake Tasks; - Definir um Autoloader para ler sua estrutura de diretórios.
/domain
e/controllers
, como é o meu, por exemplo. - Migration, Validation, ORM, etc.
Particularmente quando fiz isso pela primeira vez me senti perdido. Não é cuspindo no prato não, mas o Rails o faz criar manias e uma certa dependência nele.
Importante resaltar que você não precisará das coisas da mesma forma que o Rails criou. A vantagem é que você cria as coisas on demand, voltadas às suas necessidades. Por exemplo, meu Environment Manager é muito mais simples do que o do Rails, entretanto, consigo com ele diferenciar os Envs e subir coisas diferentes.
Outra vantagem é que construo um stack muito simples, rápido e customizado. Precisei apenas de 2 dias para ter um sandbox com Sinatra funcionando e meus testes de unidade com RSpec ficam na casa dos 0.00xx sec.
O tempo "gasto" estudando como fazer certas coisas vale muito a pena, pois você entende melhor como funciona a arquitetura por debaixo do Rack. Você no controle!
Desta forma, até agora não poluí meu código com ORM, Validations, etc. Quando realmente preciso de alguma coisa, vou lá e pontualmente a configuro/instalo.
Próximos steps: Virtus gem para Entity Modeling; ActiveModel::Validations ou o ActiveValidators; Sequel ou Rom-rb; Asset Pipeline - Sim, nada me impede de utilizá-lo standalone numa arquitetura onde eu consigo ter o controle ;)
Aos poucos pretendo ir comentando minhas aventuras nessa área. O resultado tem sido bem satisfatório até o momento. Recomendo tentar você também!
Concluíndo
Não me entenda errado: o Rails possui seus pontos positivos. Particularmente, gosto do Asset Pipeline e dos Validators (externos à classe, não aqueles validates :field
). O propósito aqui é fazer o que muitos developers lá fora já fazem: abrir o olho da comunidade de que há um mundo imenso fora do Rails e que você precisa pensar: eu preciso do Rails ou estou apenas com medo/preguiça de seguir outra solução?
1 - Foto da arquitetura da Ponte de Londres.
Magnun Leno : Hack ‘n’ Cast v0.2 - HTML & CSS
10 de Junho de 2014, 21:47 - sem comentários aindaO HTML é co-responsável pela grande revolução que foi a internet. Junte-se a trupe do Hack 'n' Cast e descubra se isso é uma tecnologia, doença ou solução. E saiba porquê você deve usar um guarda-chuva ao escrever CSS.
Baixe o episódio e leia o shownotes
Helio Costa - hlegius : Test-First: a anatomia de um teste
9 de Junho de 2014, 7:35 - sem comentários aindaAgora que as devidas apresentações foram feitas, você já deve estar inteirado O que o Test-Driven Development não é; O que são Testes de Unidade e até como conseguir criar seu primeiro teste. Assim sendo, acredito que é possível partirmos para conteúdos mais específicos dentro de cada assunto.
Para começar, vou apresentar o que acredito ser uma anatomia válida para um teste de unidade.
Ana....tomia ?
Uma pergunta até que comum que alguns co-workers têm feito é: como identificar se meu teste está bem construído ?
Essa pergunta é um resumo das seguintes perguntas:
- (Até) Quantas linhas deve ter um teste de unidade ?
- Já li que é assertion por teste. Não pode ter mais por quê ?
- Como consigo testar se um Adapter que formata dados para JSON retorna valores fidedignos, se eu tenho √784 itens no retorno ? Fiz um assertion para cada key. Não posso ficar sem testar isso. Tem ideia melhor ?
Para conseguir mostrar visualmente como isso é possível, temos que adicionar ao nosso In-Memory Testing Toolbox a técnica de como identificar se um teste tem partes faltantes (ou excedentes).
Um Teste de Unidade - teste no geral - pode ser separado em três partes: inicialização de dados; exercitar o código de produção; e, analisar resultados. Let's turn it visible:
public void testSomaDoisValoresDistintos() {
int valorA = 10;
int valorB = 20;
float resultado = subject.somaValores(valorA, valorB);
assertEquals(30, resultado, 0.0);
}
Identificando as três partes:
Inicialização de dados:
int valorA = 10;
int valorB = 20;
Exercitar o Código de Produção:
float resultado = subject.somaValores(valorA, valorB);
Analisar Resultados:
assertEquals(30, resultado, 0.0);
Acredito que essa regra sirva muito bem para você se policiar sempre ao fazer seus testes de unidade. Isso quer dizer: você não precisa fazer 1 assertion/teste; Não precisa sempre criar teste com três linhas (exceto quando estiver treinando - assunto futuro(..)).
Isso quer dizer que não tem nada errado em ter aqueles √784 (28) assertEquals
no meu teste do Adapter JSON, certo?
Errrr.... errado! Teoricamente falando isso é possível, porém é importante lembrar que frameworks de testes deste século utilizam técnicas de Hotspoting (assunto p/ outro post) que permitem nós definirmos nossos próprios assertions. Já visualizou como resolver o problema do JSON?
public void testJsonAdapterReturnsEncodedJsonString() {
# ... inicializa seu objeto para popular dados
assertJsonAdapterWillContainKeysValues(subject.toJson());
}
Mesmo sendo uma forma mais compacta, ainda assim temos a inicialização do teste, o exercício do código de produção a ser testado e a validação de que aquele código está de acordo com a especificação.
Mas... porque raios está errado colocar 28 assertions dentro de um teste?
Seu Teste é uma Especificação
Como disse Richard Stallman em The Code Linux, seu código é uma receita. Vamos utilizar a analogia dele em nosso favor: sendo o Teste uma receita, ele deve possuir steps que irá definir como ele chegará ao resultado final, ou seja, o Teste é uma Especificação de como aquele comportamento exercitado pelo mesmo deverá funcionar.
- Coloque 400ml de água dentro de uma panela e leve-a ao fogo médio;
- Espere 5 minutos para esquentar;
- Abra o pacote do miojo e o coloque dentro da panela;
- Após 3 (tsc, tsc) minutos, adicione o tempero e misture bem.
- Sirva.
Se conseguir enxergar aqueles três passos da anatomia do teste como uma receita, ficará mais fácil para lembrá-los e visualizá-los nos códigos alheios.
Como uma especificação, ao invés de precisar ler 28 linhas para entender que tudo aquilo é apenas o passo de análise de resultados, não acha mais fácil criar seu assertion customizado e resolver isso com apenas 1 linha - assertJsonAdapterWillContainKeysValues(resultado)
?
A Anatomia apontará mutações genéticas
Seguindo a Anatomia do Teste, se algum dos passos aparecerem mais de uma vez por teste, é indício de que seu teste está testando mais do que uma unidade. Ao topar com isto, você deve: extrair a duplicação e criar outro teste para aquele conteúdo duplicado. Em casos extremos, a duplicação não poderá ser removida. Isso indica ao coder de que a abstração dele caiu por terra ou ainda você está testando o comportamento errado. Será necessário repensar a solução daquele pedaço.
Concluíndo
Adote a Anatomia do Teste como sua métrica para um teste conciso. Leia sobre como criar Custom Matchers/Assertions em seu framework favorito de testes. Pratique isso no seu tempo livre. Avalie e peça avaliação de seus códigos de Teste e Produção. Exponha-se à críticas. Fará muito bem.