Daniel Tamiosso

Um apaixonado pela vida e suas várias variáveis.

Utilizando diferentes layouts erb no sinatra

Em um projeto pessoal, e possível idéia de negócio, estou utilizando o sinatra. E como engine de templates o erb.

Em um determinado momento, verifiquei a necessidade da utilização de diferentes layouts para áreas distintas do projeto. De acordo com o contexto e o gosto de cada usuário.

Como eu não gostaria de informar o layout a ser utilizado em cada um desses casos, no módulo de configurações do projeto criei os seguintes métodos:

Quando eu necessito apenas mostrar um layout de um contexto específico do cliente, eu o utilizo da seguinte forma:

Agora, quando layout é uma escolha do usuário eu utilizo o método específico para exibição do seu layout favorito:

Para os demais casos, onde o layout a ser exibido é o default, continuo utilizando da maneira tradicional para informar o erb a ser renderizado.

A idéia é simples. Se alguém souber de alguma outra maneira, fique a vontade para contribuir.

Test-driven development & Mocking

Semana passada fiz uma apresentação sobre o assunto Test-driven development & Mocking aqui na empresa. Falei sobre alguns equívocos na adoção de TDD e a confusão entre os dublês de testes. O uso de mocking pode definir o estilo do nosso TDD. E a atenção que devemos dar aos “test smells”

Boas referências sobre o assunto:

Martin Fowler – Mocks Aren’t Stubs

Steve Freeman, Tim Mackinnon, Nat Pryce, Joe Walnes – Mock Roles, Not Objects

Pontapé intermediário

Bom, depois de quase um ano sem escrever: estou aqui novamente. Este blog estava na completa inércia, talvez culpa do twitter; com toda certeza culpa minha.

Foi então que surgiu o Wagner Andrade, agora colega de empresa, entusiasmado com a sua nova gama de projetos e me apresentou o Wind. Uma engine de blog desenvolvida em cima de HTML5, Sinatra e Sequel.

A troca foi realizada, sai do monstruoso e famigerado Wordpress para o simples e notável Wind. Como não gostaria de perder meus posts antigos, fiz um pequeno plugin para realizar a importação dos posts a partir do Wordpress.

Agora, em dois cliques posso escrever muito mais a vontade. Sem frescuras!

Ou uma coisa ou outra: Command and Query Separation

Muitas vezes ao usufruirmos do uso de um simples método nos deparamos com indesejados efeitos colaterais. Métodos devem ser uma coisa ou outra. E apenas isso. Sem esconder outras variações inesperadas.

Uma prática para escrevermos métodos coesos, que falem ao invés de questionarem, é separar em dois tipos os nossos métodos. Os métodos commands, que modificam o estado de um objeto. E os métodos queries, que devem apenas retornar alguma informações sobre um objeto. Devemos sempre evitar fazer as duas coisas ao mesmo. Oferecer ambas funcionalidades em um único método causa confusão.

Por exemplo, vamos supor que temos uma necessidade de adicionarmos uma comissão a um vendedor, em uma nova funcionalidade do sistema. Olhamos para o nosso software e vemos que existe um método com a seguinte assinatura, na classe Vendedor.

Do ponto de vista de um desenvolvedor, usuário desse método, ficamos confusos com o retorno de um booleano. Na verdade aquele retorno nos diz que foi possível adicionar comissão ao vendedor, pois o vendedor possui direto a ele. Poderíamos pensar em simplesmente renomear esse método para:

Mas continuaríamos tendo um método que faz ambas as coisas. E do ponto de vista de reutilização de código, temos um desperdício. O correto seria dividir esse método em dois outros métodos, um command e uma query, onde o resultado do seu uso nos traria um bloco de código de fácil leitura:

Um caso de efeito colateral ao não utilizar a prática de Command And Query Separation pode ser dado pelo seguinte exemplo:

Nesse caso temos um efeito colateral – totalmente indesejado – ao verificarmos uma permissão de acesso, e termos o acesso liberado imediatamente.

É bastante simples o entendimento e a aplicação do Command and Query Separation. Seu propósito fundamental é evitar efeitos indesejáveis na utilização de métodos, aumentando a confiabilidade do sistema. É também uma grande ajuda no desenvolvimento de código expressivo.

O impacto de TDD no design

Quem tem utilizado desenvolvimento orientado por testes (TDD) sabe o quanto ele está diretamente ligado a design de código. Um design testável normalmente é um design desacoplado e reutilizável. TDD é muito mais sobre design do que sobre testes.

TDD é uma prática que envolve o desenvolvimento como um todo. Principalmente o design. Há quem diga que a sua última letra, a letra D, deveria significar design e não desenvolvimento. Ou seja, design orientado por testes.

Eu, particularmente, gosto muito dessa idéia. É como ter um design executável. TDD questiona o desenvolvedor freqüentemente sobre questões como princípio da responsabilidade única (SRP) e não se repita (DRY). Trata as violações das práticas de orientação a objetos. E ataca os pontos mais humanos, simplificando o projeto, onde se implementa somente o necessário (YAGNI).

Esses questionamentos são feitos a medida que sentimos a menor dificuldade em testar alguma coisa. Porque eu preciso depender de outro objeto pra testar apenas esse? Será que esse método deveria funcionar quando chamado por ele mesmo? Esse não era pra ser apenas um método de comando? Então porque alterou meu objeto?

TDD encoraja a testar e verificar cada componente do software independentemente. Isso faz o design emergir de forma extremamente simples e poderoso. Simples por tornar qualquer futura mudança ou manutenção fácil e rápida. Poderoso pela facilidade de extensão com um alto grau de segurança. Como estamos trabalhando com o teste executando a tarefa de um consumidor final e direto, conseguimos alcançar coesão e baixo acoplamento naturalmente. Passo a passo.

Sabemos que a qualidade do design de um software é também relacionada ao conhecimento da equipe de desenvolvimento em relação ao domínio em questão. E TDD também é extremamente influente nesse quesito. Tendo como testes executáveis o primeiro ciclo do desenvolvimento, é no mínimo necessário o desenvolvedor saber o que estará testando e onde ele quer chegar. É ele quem vai desenvolver os critérios de aceitação.

É impossível praticar TDD sem refatoração constante. E esse é o ponto-chave. Usufruindo dos ciclos de refatoração estamos a todo o momento focado no design. Coisa que não acontece em um fluxo tradicional de desenvolvimento.

Engana-se aquele que afirma que TDD não é produtivo. Muito pelo contrário. Por mais que em um primeiro momento o pareça improdutivo, definitivamente ele não é. No momento que focamos no design, e somente no que é essencial já estamos garantindo baixo desperdício. Sem contar que com todo o nosso código coberto por testes, evitamos aquelas longas sessões de depuração. E claro, sem falar no design. Legível, flexível, simples, eficiente, cuidadoso… De fácil manutenção. Quer algo mais produtivo? Sem contar que estamos movendo naturalmente para a idéia de zero defeito. E quanto mais defeitos mais retrabalho.

Uma ótima série de artigos escritos por Neal Ford, sobre arquitetura evolucionária e design emergente, mostra na prática o impacto que TDD causa no design de um software.

Aposte suas fichas no desenvolvimento guiado por testes e veja o design do seu código emergir com qualidade.

Versão em espanhol, por Diego Gomez: El impacto de TDD en tu diseño

As três leis do desenvolvimento dirigido por testes (TDD)

Assim como acontece quando aprendemos orientação a objetos, metodologias ágeis e até mesmo tecnologias bem específicas, precisamos antes de tudo conhecermos alguns princípios. E em TDD isso não deveria ser diferente. Acredito, e muito no aprender fazendo, desde que neste contexto esteja incluído um estudo conceitual do caso.

A resistência para colocar em prática TDD em equipes que não estão hábeis com essa prática não é pequena. Mesmo todos reconhecendo o valor e o retorno obtido pela sua prática, o pontapé inicial pode se tornar complicado. É onde ocorre o maior número de desistência no uso da prática.

Para nos auxiliar no desenvolvimento dirigido por testes, devemos obedecer as suas três leis:


  • Primeira lei: você não deve escrever qualquer implementação antes que você tenha escrito um teste que falhe;

  • Segunda lei: você não deve escrever mais que um teste unitário para demonstrar uma falha;

  • Terceira lei: você não deve escrever mais do que o necessário para passar por um teste que está falhando;

Seguindo essas premissas básicas, descritas originalmente pelo famoso Tio Bob, e realmente tratá-las como leis dentro da equipe, teremos então código testável e os benefícios de TDD serão facilmente visualizados pela equipe. E a motivação para trazer essa prática para o processo de desenvolvimento interno é conseqüência.

O risco do desenvolvimento dirigido pela arquitetura

Colocar na arquitetura o principal ponto de um projeto é uma das principais falhas em projetos de desenvolvimento de sistemas. Quando isso acontece, o primeiro passo dentro do processo interno de desenvolvimento é definir toda a arquitetura de um projeto, ao invés de termos a arquitetura como uma conseqüência de um processo do projeto como um todo. Por mais que a arquitetura pareça e seja essencial, ela jamais pode ser o principal recheio do bolo.

Sabemos muito bem, que essa é uma premissa dentro das “fábricas de softwares”, mas não é missão impossível encontrar o desenvolvimento dirigido pela arquitetura, em várias equipes de desenvolvimento. Talvez essa seja apenas uma conseqüência cultural. Talvez seja um medo empírico de perder o controle sobre o projeto, criando as fronteiras do mesmo, com a diversidade divina de frameworks presentes no mercado.

Quando a arquitetura é o principal ponto de um projeto, podemos ter certeza que correremos sérios riscos de termos um software longe de um design aceitável. Sem contar também, no incrível acoplamento que ganharemos de brinde. Na verdade o brinde é o cliente quem vai ganhar, quando precisar solicitar uma mudança no sistema. Ironia, mas essa é uma estratégia consolidada dentro das benditas fábricas de software.

E o que dizer quando se opta por uma arquitetura-faz-tudo-e-mais-um-pouco sem uma linha de implementação de um estória. Muitos afirmam que a escolha pela arquitetura como elemento chave é a produtividade. Em um primeiro instante isso pode soar muito bem aos ouvidos. Mas, antes de concordamos com essa afirmação, devemos nos perguntar o que é produtividade dentro de um projeto? É a quantidade de linhas de códigos duplicados e muitas vezes mal-escritos? Ou a qualidade de um sistema em ser coeso e incremental?

Pensar na arquitetura antes (e acima de tudo), é como cometer o erro praticado, em um nível gerencial, ao estimar um escopo de duração de dois anos para um determinado projeto. Um tiro no pé. Um salto no escuro. Ou qualquer coisa muito pior que isso. Assim como o mundo muda (e muda muito) em dois anos, a tecnologia evolui de maneira extremamente significante nos mesmos dois anos. Vale lembrar que em um mundo onde hoje gigantes multinacionais estão entrando em concordata, ninguém pode garantir que o seu framework preferido não possa ser descontinuado nos próximos meses.

Uma das conseqüências de desenvolver dirigidos por uma arquitetura é a complexidade demasiada e desnecessária que nosso sistema possuirá. Devemos adotar a simplicidade e adorá-la como um astro-rei. Eu, sinceramente não conheço ninguém e nem tenho idéia como tomar decisões tão complexas como processamento distribuído, a persistência, internacionalização, a segurança, controle transacional do projeto nos seus primeiros dias de existência. Claro, infelizmente, ainda não possuímos a capacidade de definir alguns itens antes de tudo. A linguagem de programação é um desses itens. Não podemos tratar esse ponto de forma incremental. Não por enquanto.

Tudo bem que não podemos deixar de lado o futuro. Devemos exercitar o nosso bom senso diariamente, pois com certeza não podemos deixar de pensar em futuros problemas. Mas não devemos correr o risco de sair implementando tudo o que poderia acontecer e deixar de lado o que precisa acontecer.

Um exemplo simples de um risco é a internacionalização de moedas. Todos nós sabemos o quão custoso é desenvolver em um sistema que necessita de internacionalização. Então, imagine o quão decepcionante é reler uma decisão que definia que o sistema deveria utilizar internacionalização desde o princípio. E na verdade ele jamais sairá de solo nacional. Agora se seu cliente solicitasse em um determinado momento a internacionalização, aí sim ela receberia sua devida atenção. E um refactoring resolveria a situação.

Um dos princípios que devemos adotar para podermos nos preocupar efitivamente com o futuro é limitar os nossos esforços com ele para melhorar o design de nosso projeto. É nele que está a chave de ouro para o nosso projeto. Então devemos fugir dos riscos do desenvolvimento orientado pela arquitetura, e de vez mergulharmos em práticas que focam no design incremental. Desde a nível de código como TDD a nível de processo como programação em par.

A arquitetura de um projeto jamais deixará de ser importante. Só precisamos ter a real idéia de que não é ela quem deve guiar nossos próximos passos dentro do processo de desenvolvimento interno. E sim acreditarmos em uma concepção incremental, e que a cada iteração trará novos avanços, funcionalidades e acima de tudo melhorias no design. Assim você não precisará atrasar nenuma iteração por necessitar desacoplar sua arquitetura da implementação do sistema. Então a toda iteração, a qualidade do software é melhor do que era na iteração anterior. O resultado é um software cada vez mais fácil de manter, ampliar e prazeroso de trabalhar.

Que tal o seu código falar?

“Qualquer idiota pode escrever código que um computador possa entender. Bons programadores escrevem código que os seres humanos possam entender.” – Martin Fowler

A idéia é simples, mas muitos desenvolvedores insistem em ignorá-la. Estou falando de código expressivo. Código escrito de ser humano para ser humano. Código que fala por si só. No nosso dia-a-dia sabemos que são raros os casos em que o encontramos. E a resistência é grande. Porém não podemos tapar o sol com a peneira, escrever código expressivo é uma tarefa que exige muito estudo e dedicação.

Normalmente não existe um incentivo natural para que isso aconteça. Infelizmente essa possibilidade, dentro de um projeto, recebe uma prioridade muito baixa. Primeiro busca-se obedecer e seguir a linha um calendário pré-estipulado. Depois tenta-se chegar aos requisitos. Uma boa apresentação. Um pouco de robustez. E, quem sabe, pode ser adicionada uma pitada de performance. E lá depois disso tudo, vem o cuidado em desenvolver um sistema com qualidade de código.

Hoje estima-se que mais de 60% do custo de um projeto de sofware é gasto com sua manutenção. Os benefícios ao buscarmos quebrar esse índice são fáceis de vislumbrar. É importante ressaltar que eles não são poucos. Facilidade na leitura coincide automaticamente com a facilidade de mudança. Quanto mais perto da linguagem de dominio o código estiver, mais pré-disposto a uma mudança ele estará, além de estar falando a mesma língua do usuário final do sistema. Além de trabalharmos com muito mais objetividade e altamente focados.

Muitos entendem que a melhor forma de programar está no “quanto menos melhor”. Outros depositam suas fichas nos comentários de códigos. Há ainda aqueles que apoiam-se em uma arquitetura em camadas (lêia-se muitas camadas). E existe espaço ainda para os diversos frameworks existentes no mercado. Colocamos nesse bolo, também, a sopa de letrinhas que aumenta a cada dia. É a síndrome da bazuca pra matar uma mosca perdida no ar.

Então é escolhido sempre o caminho mais difícil. Ao invés de simplificar, é preferível complicar. Ao invés de codificar o necessário, codifica-se o pior cenário. Complexidade acima da real necessidade, seja por prazer ou por qualquer outro motivo, é um mal que atinge muitos desenvolvedores. Esse mal costuma vir acompanhado pela aversão de testes. Resultando assim em um monstruoso código legado.

Hoje temos a oportunidade de trabalhar com linguagens de alto nível. Linguagens orientadas a objetos. Linguagens guiadas pela nossa realidade. Mas a insistência instintiva em continuarmos programando proceduralmente é alta. Hoje podemos nos dar ao luxo de deixar pra trás etapas que se consolidaram no desenvolvimento de software. A principal delas é a oportunidade de projetar o sistema diretamente em código, ao invés de em uma linguagem de baixo nível, quando precisavamos de artefatos como diagramas.

Para colocarmos o nosso código a falar precisamos estar focados em alguns aspectos importantes. Começando pela nomeação de qualquer coisa que você é criada. Acredite, isso é muito importante. Devemos estar atentos se o nome que a criatura irá receber está clara o suficiente para a representar. Vale fazer o teste se às duas horas da madrugada você entenderia o por que dela receber esse nome. A formatação de código, tarefa que hoje deixamos a cargo da nossa IDE preferida, é de suma importância para a boa leitura de código. É interessante a equipe toda aderir ao estilo de formatação único. Devemos sempre conhecer as convenções da nossa linguagem para seguir assim um modelo internacional de codificação. Assim como estar apto a identificar o uso de padrões de projeto. E usá-los. E o mais importante, na minha opinião, é focarmos em princípios de design como a responsabilidade única, não se repita (DRY), lei de demeter e muitas outras. E sem nunca esquecer que tudo isso deve ser dirigido e coberto por testes tão expressivos quanto o código final.

Talvez você gostaria de adicionar aí mais um item: comentários. Mas os comentários são um mal para o nosso sistema. Eles realmente não deveriam ser necessários. Mas como sabemos: muitos vezes se tornam um mal necessário. É nossa missão fazermos o melhor possível para eles não fazerem falta em um projeto.

Precisamos ter certeza que um objeto só pode ter uma única responsabilidade. Que um método, assim como um teste, só pode fazer uma única coisa. Que condicionais ternários, na maioria dos casos, são de dificil leitura humana. Que os nomes que damos as nossas criaturas (classes, métodos, variáveis…) devem ser pronunciáveis. Termos o cuidado em não duplicar código. Saber que métodos longos causam muitas redundâncias. Que quanto menos parâmetros passarmos em nossos métodos mais coeso está o nosso código. Evitar usar múltiplas saídas em métodos. E ter a consiência que a simplicidade é a nossa melhor forma de expressão.

O Lento Foguete Foo (leia-se qualquer tecnologia, ou você)

Do dia pra noite a discussão volta à tona. São muitos os fãs entusiastas desse tipo de duelo. Egos a flor de uma pele enrustida por falsos ideais. Ideais? Que nada. Contradições tão contraditórias quanto a citada na frase anterior. Admita que você pobre mortal já se deparasses com no mínimo infinitas dessas malditas discussões. Ou quem sabe, infelizmente, acometido por um momento de emoção contribui para o circo pegar fogo? Ah sim! É verdade! Ainda não mencionei o duelo ainda. Então preparem as pipocas, tirem as crianças da sala, pois no duelo de hoje teremos o Lento Foo – o desprezível da última semana, de um lado do ringue contra o Foguete Foo – o temível da nova era, do outro! Só não contem comigo para assistir o massacre.

Seja no seu fórum preferido ou no seu ambiente de trabalho. Quantas vezes ao mês, desenvolvedores de sistemas e afins duelam por amor a suas causas perdidas? Pode ser o lento Java contra o veloz .Net. Ou quem sabe o “gambiarrento” .Net contra o meticuloso Java. Ou que tal a batalha sangrenta pelo fim do Java e do .Net com a chegada do não tão novato Ruby na área. Não importa os personagens. Elas existem e estão por todas as partes. O motivo é quase sempre o mesmo (ou pelo menos corre em suas fronteiras): velocidade, nada mais abstrato para uma discussão tão vazia. Há também aqueles que abandonam tudo por uma nova tecnologia – se fosse uma garota até poderíamos entender.

Lembro-me quando iniciei a minha carreira. A moda era a disputa entre .Net e Java. A premissa era a seguinte Java é lento e .Net é da Microsoft. Uau! Plac… plac.. plac… Tudo bem era algo “somente” semelhante a isso. Eu espero! Cada um defendendo seu ganha-pão, sua zona de conforto e sua comodidade. O mais incrível é ver profissionais com um ano de experiência com muito mais certezas do que dúvidas. Não teria que ser ao contrário? É, são realmente fora de séries. E há pouco tempo atrás não tivemos um grande debate mundial sobre a tão famigerada escalabilidade do Rails no Twiter? E os divinos benchmarks de coisa nenhuma, que tal? Como diria o ilustre Galvão Bueno: “É amigo! É copa do mundo”.

Eu ainda vejo muitas pessoas que começaram comigo, ou até mesmo muito antes disso, batendo nessa mesma tecla. Apesar de existir um grande movimento na comunidade, uma imensidão de bons livros, ótimos profissionais nas nossas equipes, todos com informações sobre qualidade de sistema;o valor de um código expressível por si só; a importância e a obrigação de testes automatizados; as metodologias que agilizam nossos processos; refatoração constante; linguagens de domínio. E tantas outras vertentes (umas novas outras bem antigas – mas não ultrapassadas) que realmente nos dão a coordenada para termos um sistema que atenda a necessidade nossa e de nossas clientes. Mas muitos ainda teimam em ir contra essa maré. E ficam atrás de respostas para perguntas como essa: quem é o Lento e qual é o Foguete?

Há uns dias que presenciei uma cena um tanto quanto massacrante. Após alguns gerentes lerem um pequeno esboço sobre a utilização de Scrum e XP (vale lembrar que antes da informação chegar na mesa deles, não sabiam nem da existência do mesmo), chegaram a conclusão em alto e bom som que era isso que precisavam que todos os inúmeros problemas organizacionais estavam resolvidos. E que tudo seria muito simples. O que for diferente daquilo não presta. Ora bolas, mas então porque estão nessa vida a cerca de quinze anos? Levou-se um minuto pra descobrirem que aquilo tudo – ou no caso aquilo nada – é como caminhar nas trincheiras amigas.

Acredito que o grande diferencial dentro de qualquer coisa, são as pessoas. E no desenvolvimento de software tenho ainda mais fé nessa crença. E como é difícil montar uma equipe comprometida. Se cada um fosse comprometido consigo mesmo já seria um ganho. E as empresas porque não investem na motivação de seu corpo técnico?  E quando nos deparamos com aqueles empresas que insistem em uma coisa: produtividade, sem ao menos saber como se conseguir isso dentro de uma equipe científica. Bom nessa caso vamos de Taylor, Ford… Sistemas também são para desenvolvedores e não só para nossos clientes. Precisamos buscar o entendimento da ciência como um todo; a paixão vem logo em seguida. E por favor, não paremos no tempo com duelos infames como os citados anteriormente. Nós podemos fazer a diferença. Ou você quer ser um dos personagens de um duelo desses? Ou pior, sendo para sempre o Lento da estória.

Next page →