1up4developers logo

1up4developers

Nadando contra o Waterfall. tail -f /mind/realworld >> /blog

Remarkable, jqGrid No Rails, Heroku E Github Issues

| | Comments


Este é o primeiro post que publicaremos semanalmente reunindo novidades sobre desenvolvimento, artigos, notícias e temas variados sobre Rails.

Remarkable 3.0

Foi lançada a nova versão do Remarkable, um framework para testes com RSpec. Dentre as novidades, estão:

  • I18n, possibilitando gerar o output das specs no seu idioma favorito fluente

  • Pending Macros, facilitando o agrupamento das specs pendentes

  • Macro stubs e mais opções de Matchers, simplificando testes com mocks

Para instalar basta um sudo gem install remarkable_rails

Saiba mais no site do Carlos Brando, lendo a documentação ou espiando o código no Github.

jqGrid no Rails

jQuery é um dos frameworks Javascript mais populares do mercado. O que esse cara fez foi juntar o jqGrid, que é um plugin muito bom para trabalhar com grids, num plugin para Rails, facilitando sua utilização.

Veja aqui um guia de utilização do plugin, a aplicação de exemplo ou confira o código no Github.

Heroku

Apesar da simplicidade do Business Bingo Generator, houve muitas “manhas” aprendidas no seu desenvolvimento. O Heroku foi uma delas, onde pudemos publicar rapidamente a aplicação. Se você quer hospedar um projeto simples feito em Rails, nós o recomendamos. O seu uso é muito simples e a incrível idéia de usar o git como interface para deploy é realmente sensacional. Basta instalar o client do Heroku, dar um “git push” e pronto: a aplicação está no ar!

Github Issue Tracker

Nova funcionalidade no GitHub para facilitar nossas vidas, permitindo informar os “bugs” nos projetos. No link acima, contém o vídeo “I_ntroduction to GitHub Issues_” para mais detalhes.

Caso já use um Issue Tracker para o seu projeto no github, você pode desabilitá-lo na seção do Features na aba Admin.

Business Bingo Generator

| | Comments


Para quem tem algum tempo de internet, é fácil notar como as piadas se repetem, ou melhor, assim como olimpíadas ou copa do mundo, re-aparecem a cada quatro anos por exemplo. Não foi diferente com a piada que recebi (novamente) a pouco tempo, o Business Bingo. O que torna a piada muito divertida é o seu alto teor sarcástico e real, foi quando pensei, porque não imprimir esta cartela e realmente testar! Foi assim que surgiu a idéia de fazer um gerador de cartelas para o Business Bingo! :D

idéia

Business Bingo! Generator

A idéia deste post, além de ajudar a divulgar o site, é ter um local central para comentários, sugestões, reclamações e elogios para o Business Bingo Generator.

Curiosidade

  • O Business Bingo, também conhecido como Buzzword Bingo, ganhou notoridade em 1994, com uma tirinha publicada do Dilbert.

  • Um dos “grandes” eventos “documentados”, foi em 1996, que alunos do MIT o usaram no discurso do vice-presidente dos EUA, Al-Gore.

Uma nota rápida a desenvolvedores

A primeira versão foi desenvolvida em dois dias, isso mesmo, dois dias e já estava em produção. Eu e o Rodrigo Panachi resolvemos implementar a idéia do “generator” para aprender na prática como funciona o Ruby on Rails. Num post futuro irei colocar mais detalhes técnicos, que apesar de ser uma aplicação muito pequena, podemos tirar proveito de grandes aulas. Para quem quiser contribuir, o Business Bingo Generator está no GitHub.

TPW - Testando Sistemas Legados: Classes Utils

| | Comments


Aproveitando o gancho do post anterior sobre manipulação de dependências, decidi dedicar um post apenas sobre este tema, pois acredito ser de grande ajuda para todos desenvolvedores que precisam manter código legado.

Em projetos legados é comum encontrarmos classes Util (aka Helpers) espalhadas por todo o código, fazendo desde coisas simples como formatar datas ou números, até coisas mágicas como cache de objetos, operações com reflection, escrita de logs, etc. Mesmo que tenham sua “utilidade”, são um terror quando falamos de testes! Além de ser um forte indício de um design fraco, as chamadas a seus métodos, geralmente estáticos, geram dependências nas classes que a utilizam.

Este é a estrutura comum (bem simplificada) de uma classe Util com métodos estáticos:

1
2
3
4
5
public class MagicUtil {
    public static String getConstanteSecreta() {
        return "VALOR_SECRETO_AMBIENTE";
    }
}

Neste caso, uma boa estratégia para os testes seria encapsular a chamada da classe Util em um método protected, para que seja sobrescrito na classe de teste, assumindo o comportamento desejado. Porém, se a classe Util for largamente referenciada no projeto (o que é comum) seria preciso refatorar todas a classes que a utilizam para escrever um teste completo.

A estratégia proposta é refatorar a classe Util, aplicando o padrão Singleton e transformando os métodos estáticos em métodos de instância, porém mantendo as assinaturas estáticas, que devem referenciar os métodos da instância. Uma vez que a Util pode ser instanciada (mesmo que internamente), é possível manipular seu comportamento através da injeção de um objeto Mock, por exemplo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class MagicUtil {
    private static MagicUtil instance = new MagicUtil();
    protected static MagicUtil getInstance() {
        return instance;
    }
    protected static void setInstance(MagicUtil obj) {
        instance = obj;
    }
    public String getConstanteSecretaInstancia() {
        return "VALOR_SECRETO_AMBIENTE";
    }
    public static String getConstanteSecreta() {
        return getInstance().getConstanteSecretaInstancia();
    }
}

Assim, a Util continua com o mesmo comportamento e seu contrato foi mantido. Agora, no seu teste, basta escrever o mock (estendendo a classe e sobrescrevendo os métodos) e injetá-lo na instância interna da Util:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class ClasseTest {
    @Test
    public void testaMetodoDependenteDeMagicUtil() {
        new MagicUtil() {
            {
                setInstance(this);
            }
            public String getConstanteSecretaInstancia() {
                return "MEU_VALOR_MOCK";
            }
        };
        Assert.assertEquals("MEU_VALOR_MOCK", MagicUtil.getConstanteSecreta());
    }
}

Neste caso a classe anônima (que estende a Util) passa sua própria instância (this) para o método protegido setInstance(). Note que a chamada do método (estático) da Util continua igual ao da classe original, sem o refactoring.

Nos projetos que preciso manter, esta estratégia tem sido muito útil para resolver os problemas das “teias” de Utils. Porém é um recurso paliativo e não deve ser utilizado como o “padrão”. O ideal é sempre evitar classes Utils, lembrando que uma classe deve sempre ter comportamentos bem definidos e o nome já deve indicar sua responsabilidade.

TPW - Testando Sistemas Legados: Manipulando Dependências

| | Comments


Pela definição de Michael Feather, código legado é código sem testes! Não importa se o código foi escrito semana passada ou alguns anos atrás. Qualquer manutenção será de difícil entendimento por outra pessoa e não haverá garantias de seu funcionamento. Uma vez que não há “controle”, é mais difícil rastrear as alterações; pior do que uma nova funcionalidade que não funciona, é uma funcionalidade antiga que começa a falhar. Este é um risco que um desenvolvedor não pode correr!

Não altere código legado até que seja possível testá-lo

Um dos problemas mais comuns em sistemas legados é a interdependência de classes, ou seja, o alto acoplamento), que sempre está ligado com a baixa coesão). Se estes termos são difíceis de entender, pense em acoplamento como sendo o grau com que as classes referenciam umas as outras e coesão o quanto uma classe está focada em realizar suas responsabilidades.

Para que seja possível testar o comportamento de uma classe “acoplada”, o comportamento de suas dependências precisa ser simulado. Isto normalmente é feito através de objetos falsos, ou mocks, que são injetados na instância da classe em questão. Este padrão é conhecido como Inversão de Controle e Injeção de dependência, onde o controle sobre as dependências da classe são delegados à outro objeto, ou normalmente um container de objetos, responsável por injetar as dependências nas instâncias das classes. Simples, não?! Mas isso será detalhado em outro post…

Voltando para os testes, no post anterior começamos a organizar o projeto automatizando o build e centralizando a execução dos testes para evitar que fiquem “soltos” pelo código. Agora vamos nos concentrar em escrever os casos de teste, refatorando o necessário para lidar com as dependências das classes.

Partindo da premissa que o projeto não possuí nenhum framework de inversão de controle, utilizaremos um certo “padrão” que permite manipular as dependências de uma classe por meio de herança, sem alterar seu comportamento original. A idéia é resolver as dependências da classe através de getters protegidos, que podem ser sobrescritos em uma classe filha no momento do teste. Isso permite que, na classe estendida, o método sobrescrito retorne um objeto mock, por exemplo, com o comportamento esperado para o teste.

Vamos tomar como exemplo, uma classe simples com algumas dependências e responsável por encapsular algumas regras de negócio referentes à Estoque.

1
2
3
4
5
6
7
public class EstoqueLogic {
    public boolean verificaDisponibilidade(Produto produto, Integer quantidade) {
        EstoqueDAO dao = new EstoqueDAO();
        Estoque estoque = dao.localizaProduto(produto.getCodigo());
        return estoque.getQuantidade() >= quantidade;
    }
}

Da forma como esta classe foi escrita, é impossível testar a regra de disponibilidade independentemente, pois depende do objeto EstoqueDAO para localizar as informações necessárias para o método. Mas com um pequeno refactoring, a responsabilidade de resolver a dependência EstoqueDAO passa a ser responsabilidade da própria classe Estoque:

1
2
3
4
5
6
7
8
9
10
public class EstoqueLogic {
    public boolean verificaDisponibilidade(Produto produto, Integer quantidade) {
        EstoqueDAO dao = getEstoqueDAO();
        Estoque estoque = dao.localizaProduto(produto.getCodigo());
        return estoque.getQuantidade() >= quantidade;
    }
    protected EstoqueDAO getEstoqueDAO() {
        return new EstoqueDAO();
    }
}

Desta forma, é possível “injetar” um objeto que simule a dependência do EstoqueDAO estendendo a classe e sobrescrevendo o método getEstoqueDAO() para retornar a instância desejada. O teste ficaria mais ou menos assim:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
public class EstoqueLogicTest {

    public void testVerificandoDisponibilidadeDeUmProduto() {

        //Criando o objeto EstoqueDAO mock, simulando o comportamento desejado
        final EstoqueDAO estoqueDAOMock = new EstoqueDAO() {
            @Override
            public Estoque localizaProduto(String codigo) {
                Produto produto = new Produto();
                produto.setCodigo(codigo);
                Estoque estoque = new Estoque();
                estoque.setProduto(produto);
                estoque.setQuantidade(5);
                return estoque;
            }
        };

        //Sobrescrevendo o método getEstoqueDAO para retornar o Mock
        EstoqueLogic logic = new EstoqueLogic() {
            @Override
            protected EstoqueDAO getEstoqueDAO() {
                return estoqueDAOMock;
            }
        };

        //Definindo o teste e executando
        Produto produto = new Produto();
        produto.setCodigo("123456");

        boolean estaDisponivel = logic.verificaDisponibilidade(produto, 10);
        assertTrue(estaDisponivel);

        boolean naoEstaDisponivel = logic.verificaDisponibilidade(produto, 2);
        assertTrue(naoEstaDisponivel);
    }
}

O método getEstoqueDAO() da classe EstoqueLogic foi sobrescrito para retornar o objeto estoqueDAOMock com as informações necessárias para o teste, ou seja, o comportamento das dependências foi simulado, possibilitando que o teste ficasse concentrado apenas da classe Estoque.

Elimine as dependências e teste onde os bugs estão!

Este padrão fornece apenas uma maneira de lidar com as dependências das classes para escrever testes. A dica aqui é manter o foco: defina apenas testes para as funcionalidades que estiver alterando e que exercitem pontos críticos e/ou regras de negócio. Então, refatore apenas as classes necessárias para simular e validar o fluxo destes testes, nem que seja apenas seus “contratos”. Não há necessidade de escrever testes muito granulares nem alterar todas as classes de um sistema legado.

No caso de classes com muitas dependências, o melhor é refatorá-la, separar as responsabilidades e testá-las individualmente. Para classes com dependências de Utils e/ou muitas chamadas à métodos estáticos, uma estratégia parecida pode ser utilizada. Mas estes são assuntos para os próximos posts. Acompanhem!

TPW - Testando Sistemas Legados: Automatizando O Build

| | Comments


Imagine o cenário: você caiu de para-quedas naquele projeto que todo mundo na empresa fez gambiarra deu manutenção e agora precisa implementar uma nova funcionalidade. Mesmo que tenha alguma documentação, vai ser inútil neste caso. Então você começa a vasculhar o código e encontra dezenas de classes com nomes parecidos, vários arquivos XML’s dos inúmeros frameworks utilizados anteriormente, TO’s, VO’s, Actions, Utils… ou seja, um lugar cheio de janelas quebradas.

O mais fácil neste caso seria fazer seu trabalho, quebrando mais algumas janelas caso necessário, e cair fora o quanto antes. Mas você, desenvolvedor ágil, sabe que além de ser falta de profissionalismo, você corre o risco de cair novamente no mesmo projeto. Então aproveite a oportunidade para fazer uma pequena faxina e preparar o projeto para escrever os testes das novas funcionalidades que irá desenvolver, garantido assim a qualidade, pelo menos, do seu trabalho.

Durante minha carreira fui obrigado tive a oportunidade de dar manutenção em diversos projetos “frankenstein” de onde adquiri certa experiência para poder “organizar a casa” e trabalhar decentemente no código. É claro que não estou falando em escrever testes para o projeto inteiro, mas pelo menos garantir a qualidade do código que desenvolvi ou irei desenvolver.

Há um certo padrão que todo software de qualidade deve seguir. Além dos padrões e boas práticas como organização do código em pacotes vs. responsabilidade, uma coisa essencial para o projeto é sua construção, ou seja, a forma que o software é “entregue”. Acredito que este seja o primeiro passo para começar a organizar a bagunça de um projeto.

A construção do projeto deve ser automática e desempenhada por uma ferramenta de build como o Ant ou Maven, com tarefas (tasks) e objetivos bem definidos. Normalmente, um build do projeto deve:

  1. Preparar o código e dependências

  2. Compilar os arquivos fontes

  3. Executar os testes

  4. Empacotar a distribuição

No exemplo abaixo usarei o Ant, que é a ferramenta de build (para Java) mais popular do mercado e muito simples de utilizar. O importante neste processo é ser pragmático: não perca o foco! Você poderia (e futuramente deveria) utilizar o Maven, mas adequá-lo a um sistema legado não é tão simples quanto parece.

Tendo os objetivos do build definidos, basta escrever o script do Ant. Isso deve ser feito no arquivo build.xml, no root do projeto. As tarefas são definidas pelas tags e podem ser dependentes para garantir a sequencia de execução. Em cada target são definidas as ações executadas, como rodar o compilador (javac), copiar um arquivo, rodar os testes, etc. Uma vez que as tarefas estão configuradas, basta executar o build pelo próprio IDE ou linha de comando.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<project name="frank" default="package">
  <path id="classpath">
      <pathelement location="build/bin"/>
      <fileset dir="src">
          <include name="*.java"/>
      </fileset>
      <fileset dir="lib">
          <include name="*.jar"/>
      </fileset>
  </path>
  <target name="clean">
       <delete dir="build"/>
        <mkdir dir="build"/>
  </target>
  <target name="compile" depends="clean">
      <javac srcdir="src" destdir="build">
          <classpath refid="classpath"/>
      </javac>
  </target>
  <target name="test" depends="compile">
      <junit>
          <classpath refid="classpath"/>
          <batchtest>
              <fileset dir="build" includes="*Test"/>
          </batchtest>
      </junit>
  </target>
  <target name="package" depends="compile, test">
      <war destfile="frank.war" webxml="web/WEB-INF/web.xml">
      <classes dir="build"/>
  </target>
</project>

Neste script estão definidas as tarefas necessárias para executar um build, conforme citei anteriormente. Por enquanto isto será o mínimo necessário para dar suporte as próximas etapas da sua missão. Mesmo que o projeto já tenha um build em Ant aproveite para revisá-lo. Tarefas bem simples e bem definidas são mais fáceis de entender e manter.

Com o build implementado, você não terá mais que se preocupar com o empacotamento do projeto. Agora comece a direcionar seus esforços para escrever os testes. Deixe que o Ant se encarregará de executá-los para você.

No próximo post vou apresentar alguns padrões e práticas de refactoring utilizados para possibilitar escrever testes que dependem de classes legadas do projeto.

TPW - Dicas Para a Qualidade Do Software

| | Comments


Desenvolvedores em geral sabem como é chato quando uma tela que fez ou alterou dá erro durante uma homologação ou até produção. No caso de um sistema Web, a raiva aumenta ainda mais se a causa for incompatibilidade de navegadores.

Antes de começar a apresentar o “the best of my rotina”, é bom deixar bem claro o meu cenário:

  • Trabalho sozinho no projeto, sou humano e faço pair programming com a cpu, que eu tenho certeza que é pogger!

  • O meu cliente, o que requisita correções e/ou novas funcionalidades, é um cliente interno e eu tenho acesso direto a ele.

  • O sistema não tem testes unitários, testes de integração e etc.

  • Muito código foi copiado, não somente na camada de negócio, mas também nas views. As páginas por aqui, também são conhecidas como business-view.

  • Tem mais complicações, mais acho que já tem o suficiente para entenderem o meu cenário.

O que já fizemos para começar a arrumar a casa:

  • Implantamos um bug tracker, conhecido como Redmine. Sabe aquele velho problema de planilha pra lá e pra cá e ninguém nunca sabia quem, e o que estava fazendo? Pois bem, este problema está quase resolvido aqui (quase porque ainda tem projeto faltando para migrar).

  • Implantamos um servidor de integração continua, com o Hudson. Apesar de eu não ter testes, havia um sério problema aqui para implantar novas versões em homologação e produção, e agora com o Hudson centralizando o build, ele mesmo já disponibiliza o war.

  • Por sinal, montar e começar a usar o war foi outro trampo também.

Sabendo que o meu contexto é diferente do seu, sinta-se livre para adaptar qualquer coisa. Tentei deixar as dicas o mais genérico possível.

1. Trabalhe com tarefas Curtas

Tarefas curtas são muito mais fáceis para desenvolver, testar e se livrar! Por exemplo, se tem que desenvolver aquele formulário com vinte telas, não tenha dúvida, quebre isto em pequenas funcionalidades. Para identificar as partes “quebráveis”, leve em conta o que a torna funcional, ainda no exemplo anterior, se das vinte telas, você fizer a primeira e a última são suficientes para um cadastro básico, está ai a sua primeira tarefa. Muitas pessoas não dão importância para isso, mas saber “extrair” as tarefas certas de um novo desenvolvimento ou manutenção, traz um leque de vantagens:

  • Testar uma funcionalidade curta é muito mais rápido e fácil do que testar uma gigantesca;

  • Fica mais dificil perder o foco.

  • Os prazos ficam mais “coerentes”.

  • Você pode retirar ou incluir novas funcionalidades, a “negociação” com o cliente fica mais simples.

2. Monte e use um roteiro de teste

Pra quem usa TDD, este passo pode pular. Pra quem trabalha com legados e ainda não tem testes (meu caso), eu costumo fazer um roteiro de testes antes de implementar a funcionalidade curta. Este roteiro costuma ser enxuto e abrangente, isto permite que eu descanse meu cerebro enquanto testo, pois com ele, acaba se tornando um processo mecânico. Vou colocar um exemplo recente de roteiro que usei:

Teste de Primeiro Acesso

  • Limpar a base, apagar os registros da tabela xpto e suas dependências.

  • Limpar os cookies.

  • Acessar o index.jsp da Aplicação (esta página simula um login via cookie).

  • A tela inicial só permite cadastrar os dados do perfil, os links “xxx” e “zzz” não ficam disponíveis.

  • Após o Teste de Restrições ao Editar o Perfil, verificar que os links “xxx” e “zzz” estão disponíveis.

  • Clicar em salvar novamente para verificar se o problema de “unique id” não ocorre.

Estes roteiros se tornaram um costume, eu perco pouquissimo tempo pra fazer e apesar de parecer besta, ele me ajuda muito na hora de executar um teste de sanidade por exemplo. O ideal seria transformar este roteiro num teste unitário ou até mesmo num script via Selenium, mas devido a estrutura (ou a falta dela?!) eu ainda não consegui esta automação tão sonhada. Apesar deste roteiro ser descartável e somente para ajudá-lo, uma idéia legal que venho fazendo é colocá-lo como comentário caso use um bug tracker.

3. Teste seu sistema num ambiente isolado

Estes últimos dois anos tenho usado linux no desktop para desenvolvimento. Infelizmente, todos nós sabemos que todo sistema web tem que ser testado nos IE*s e cia. É claro que durante o inicio do desenvolvimento, uso meu firefox local mesmo, mas assim que termino a funcionalidade, uso uma máquina virtual para averiguar a compatibilidade com os navegadores mais utilizados. Usando o Virtual Box e Multiple IEs mais o opcional roteiro de testes, consigo validar o sistema numa boa gama de navegadores. Para usar o Multiple IEs não tem segredo, é só atualizar para o IE7 e depois rodar o executável do mesmo.

4. Automatize o que for possível

Já ocorreu de você precisar preencher n campos, navegar em n telas e descobrir que você errou o nome de uma variável javascript e ter que fazer tudo de novo? Pois bem, comigo já aconteceu muito, e uma das soluções que venho usando é o Selenium Ide. Com o plugin do firefox, eu gravo scripts temporários (durante o desenvolvimento da tarefa) que preenche os n campos e navegam nas n telas, assim pelo menos este tempo de navegação eu só perco uma vez.

Finalizando …

Todas estas “técnicas” nada mais são do que uma retrospectiva minha, de uma tentativa (frustada por sinal) de Scrum Solo. Aqui estou colocando o que vem dando resultado, e se você achou besteira ou legal, gostaria muito do seu comentário. Sabe aquela frase da maça e conhecimento, então, minha única expectativa com este post é esta: Novas Idéias!

Valeu e feliz ano novo a todos!

Agilidade Cascateira

| | Comments


Atualmente as metodologias ágeis vêm aparecendo com cada vez mais freqüência nas empresas que desenvolvem software, introduzidas pelos próprios desenvolvedores (o que é mais comum) ou em alguns raros casos pela “cúpula” da empresa, na esperança de melhorar a produtividade e/ou o alto tempo de resposta do fracassado processo cascateiro. Porém, esta “fama” prematura dos métodos ágeis tem gerado mais resultados ruins do que bons. Sua aplicação na vida real, na maioria em muitos casos, ocorre de maneira equivocada, distorcida e desprezando-se os reais valores e princípios que apoiaram o surgimento desta filosofia.

Um exemplo claro de como os valores ágeis estão sendo desprezados distorcidos é o aumento constante de “cursos” e treinamentos de metodologias ágeis. Não é raro eu receber semanalmente vários spams e-mails de escolas de treinamento que ministram cursos de Scrum, XP, preparação para certificação ScrumMaster, técnicas de TDD, DDD, BDD, etc. Infelizmente o que estes cursos não ensinam (como todos os outros) é o verdadeiro significado de “ser ágil”. Fazer um curso de 20 horas de Scrum não o torna um ScrumMaster (você pode até ter um certificado, mas se você realmente é “ágil”, sabe que um certificado é um mero pedaço de papel sem valor).

E assim chegamos à “agilidade cascateira”, onde todos na empresa estufam o peito para falar que seguem práticas ágeis, desenvolvimento orientados à testes, utilizam Scrume para gerenciar os projetos, etc. Na verdade estão apenas praticando um waterfall incremental, cometendo os mesmos erros clássicos da cascata, valorizando os processos ao invés das pessoas, focando em soluções equivocadas ao invés de resolver os problemas dos clientes e assim, difamando e denegrindo a reputação e o propósito do AgileManifesto.

Esse é o cenário ideal para os guardiões cascateiros. É por estes e outros motivos que vemos “flames” oportunistas como The Decline and Fall of Agile começarem a fazer sentido na comunidade. Como disse o Guilherme Chapiewski, as pessoas estão querendo ir direto para a sobremesa e esquecendo de comer seus vegetais. Utilizar uma metodologia ágil não é desenvolver software de forma anarquista, existe muito conceito e experiência adquirida para sustentar esta filosofia.

Neste blog você já viu várias maneiras de como ser um verdadeiro cascateiro e de como não ser ágil. Já que estamos falando nisso, vamos tentar resumir alguns pontos e características que tornam um desenvolvedor realmente ÁGIL!

Estude, mantenha-se atualizado!

A principal característica de um agilista é sua sede por conhecimento, sua busca incansável por novas técnicas, linguagens, ferramentas, etc. O seguidor ágil lê artigos, revistas, livros e o faz como diversão. Se você não leu pelo menos um livro técnico nos últimos 6 meses, isto é um mal sinal. Faça laboratórios, testes de novos frameworks, bibliotecas, etc. Pet-projects também são uma maneira pragmática de aprender novas formas e técnicas de desenvolvimento. Finalmente, conheça e pratique os princípios e valores do AgileManifesto, tendo-os como seu mantra, seu guia filosófico e seu mentor profissional.

Entenda realmente o problema do seu cliente

Isto parece ser óbvio, mas na maioria das vezes não é. Existem vários perfis de clientes, e é claro que você deve lidar de maneiras diferentes com cada um deles.

Alguns são visionários sonhadores e sempre têm necessidades mirabolantes, sem sentido. Outros são simplistas demais e muitas vezes “ocultam” detalhes importantes. Também existem os pseudo-técnicos, que acham que sabem fazer seu trabalho e já vêm sugerindo como você deve implementar aquela nova funcionalidade.

Reação comum quando há um problema

Como verdadeiro agilista, saber identificar o perfil de seu cliente é o início para um relacionamento de confiança e transparência. Só assim você será capaz de concentrar esforços para resolver seu problema e agregar valor ao produto.

Não tenha medo de mudanças

A única maneira de criar, corrigir ou melhorar algo é com coragem E com mudança. O essencial para mudar algo é saber identificar o que está errado. Por exemplo, você sofre diariamente para fazer o deploy da sua aplicação para homologação. Identificado o problema e uma possível solução, por exemplo, fazer o deploy em .war, você tem duas soluções: ou deixa como está e coloca a culpa na aplicação ou no processo de desenvolvimento (conformismo) ou com muita coragem investe algumas horas e resolve de vez o problema (agilismo).

Quando bater a insegurança, repita: coragem! coragem! coragem!

Reflita e aprenda com os próprios erros

Existem várias maneiras de você evoluir seu conhecimento, e a maioria dos programadores utilizam somente uma: tomando na cabeça.

Prego só toma na cabeça!

Como um bom seguidor de práticas ágeis, reflita e aprenda com seus erros. Compartilhar seus problemas é a melhor maneira de escolher um solução adequada e ainda espalhar sua experiência entre a equipe para que outras pessoas não cometam o mesmo erro.

Errar é humano. Persistir no erro é burrice. Se você está com problemas, procure por pessoas que já tiveram um problema parecido e aprenda com ele. Não cometa os mesmo erros, e mais importante, não cometa os mesmo erros dos outros!

Resumo

Se tudo que você leu até agora não é novidade, parabéns! Caso contrário comece o quanto antes estudar e principalmente praticar estes conceitos no seu trabalho e na sua vida.

Seja responsável e comprometido com seu trabalho. Esforce-se para fazer o melhor. Faça valer o seu salário. E lembre-se: cuidado com os falsos agilistas!

Rails Summit Happy Hour!!

| | Comments


Bom pessoal, já faz um tempo que não escrevo, isso se deve um pouco pela falta de tempo, mas muito pela falta de vergonha na cara! Sempre tenho idéias, mas pouca atitude. Como muitos sabem, em outubro passado o 1up4dev esteve representado no Rails Summit Latin America por mim, pelo Roger Leite e pelo André Farina. Muita coisa aconteceu naquele evento, e isso com certeza ficou evidente em muitos posts por aí (post do shadow, akitaonrails e muitos outros). As palestras simplesmente foram inspiradoras, enriquecedoras e com certeza mudaram a cabeça de muita gente, não tem como não se empolgar ao ver caras como Chad Fowler e Obie Fernandez falando! Os caras arrasaram em todos os sentidos. O fato de poder entrar em contato com figuras da comunidade que muitas vezes você só acompanha via GitHub, e melhor, poder trocar uma idéia com essa galera é muito legal.

Com certeza todos ficaram com um gostinho de quero mais, e com uma imensa vontade de agradecer ao Fábio Akita e todos aqueles que tornaram este evento possível. Mas uma coisa que não vi ser muito falada foi o happy hour que aconteceu ao final do último dia. Você consegue imaginar como seria poder tomar uma breja com o cara que escreveu um de seus livros preferidos?! Ou o cara que mantém aquele blog que te inspirou a aprender ruby/rails? Melhor ainda. Imagine poder passar um momento falando besteiras e dando muita risada com esses caras?! Bom, eu passei por isso!! E até agora a ficha parece não ter caído, não consigo acreditar que passei por isso.

Bom, para organizar os fatos a coisa aconteceu mais ou menos assim. Depois do fim da palestra do Obie Fernandez toda galera correu para tiras fotos, pegar autógrafos e coisas do tipo, foi agitação total como era esperado. Feito isso, o pessoal da organização começou a servir espumante e cerveja no saguão e é claro que corremos para lá. Foi muito legal, pois nesse momento conseguimos conhecer mais gente e ainda presenciar Dr Nic mandando ver numa Skol gelada! Nesse momento começou um movimento revolucionário lutando por uma causa que eu considerei mais que justa, procurar um lugar para comer e beber mais cerveja (e depois algumas caipirinhas, como pode ser confirmado pelo próprio Dr Nic no video abaixo!). Surgiu a idéia de comer um sushi, e é claro que só podia ser no bairro da Liberdade.

Rails Summit Happy Hourt, chegada from miguel aranha baldi horlle on Vimeo.

Nesse momento todos se mobilizaram, e o pessoal da LocaWeb ainda deu uma força na logistica, e todos foram para um restaurante na Liberdade. Muitos pegaram carona (como eu!), outros foram na Van da LocaWeb, mas o importante é que depois de algumas voltas estávamos todos lá. Simplesmente lotamos o lugar, um monte de nerds loucos para comer e tomar umas cervejas, todos loucos depois de um evento como esse. A galera se organizou em várias mesas, e fiquei em uma mesa com o Ricardo Yasuda (shadow) e o Márcio Trindade. Junto com a gente estava Dr Nic e um argentino maluco (qual que não é?! huahauhua). Em outras mesas estavam Obie Fernandez, Chad Fowler, Chris Wanstrath, David Chelimsky! A galera do Phusion Passenger também estava lá, assim como Vinicius Teles, Juan Bernabó e muitos outros (Incluindo Fábio Akita!). Bom, o resto foi um misto de muita bebida, risadas, e claro, muito papo nerd. E o mais legal de tudo é que sobrou um pouco de bateria na filmadora e eu consegui filmar alguma coisa (com a ajuda do nosso amigo argentino, que se alguem lembrar do nome por favor me avise).

O mais legal de tudo isso foi poder conhecer muita gente legal, ter contato com meus ídolos e ver que estes são pessoas muito acessiveis. Certamente esse dia não vai sair de minha lembrança, um abraço pra galera que esteve lá, devido ao nível alcoolico do momento não me lembro do nome de todos, huahuahuaha. E fica a chamada pra galera, quem esteve lá nessa noite por favor se manifeste e comente aí, gostaria de saber o nome da galera. ;–)

Rails Summit Happy Hour, hino nacional from miguel aranha baldi horlle on Vimeo.

Observações: Conforme eu for subindo mais videos no Vimeo eu vou atualizando este post, portanto fiquem ligados! Tentei deixar os videos em uma boa qualidade para quem for baixar. Ainda tenho que editar a maior parte da filmagem que foi feita pelo argentino maluco, que logo no inicio pegou a camera de mim e não soltou mais até acabar a bateria!

Espero que mais eventos como esse aconteçam, e que a galera compareça e participe como participou neste evento, abraço à todos!

Foco No Problema

| | Comments


Desenvolver software é uma atividade muito gratificante pois sempre podemos (ou deveríamos) exercitar nossa criatividade para solucionar os problemas dos clientes. Isto, apesar de divertido pode ser perigoso e/ou catastrófico se estivermos com o foco errado. Num ambiente cascateiro, onde cada envolvido está comprometido apenas com o processo e não se preocupa verdadeiramente com os problemas dos clientes, não é difícil que isto ocorra. Quase sempre o foco acaba sendo direcionado para a solução ao invés do problema.

Mas qual a diferença entre foco no problema ou solução? Vamos a um exemplo:

Quando a Nasa enviou os primeiros astronautas ao espaço, descobriu que as canetas não funcionavam com gravidade zero. Para resolver esse problema, os engenheiros contrataram uma empresa especializada para projetar a caneta espacial. Dez anos e US$ 12 milhões depois, estava pronta a caneta que podia ser usada no espaço, em qualquer posição. Nem a temperatura poderia atrapalhar: a supercaneta funcionava bem fizesse frio ou calor. Os russos, que tiveram o mesmo problema, optaram por uma solução mais simples: passaram a usar um lápis.

A história acima é bem famosa e mesmo sendo falsa, demonstra muito bem o que acontece quando o problema não está em foco. Neste caso, o problema é a impossibilidade de escrever em gravidade zero. Uma das soluções seria uma caneta que escreva nessas condições. Veja que aqui a solução já está em foco. Outra solução para o problema seria utilizar algo que escrevesse em gravidade zero: um pedaço de carvão ou um giz já serviriam. Assim, o problema seria resolvido.

Outro exemplo de falta de foco no problema é esta história da fábrica de pasta de dente, onde ocasionalmente algumas caixas da pasta de dente eram entregues vazias. Para eliminar este problema, a empresa gastou investiu milhões para garantir que durante a fabricação, nenhuma caixa ficasse sem o tubo de pasta de dente dentro. Mas o problema foi realmente resolvido depois que um operário deixou um ventilador soprando as caixas vazias para fora da esteira de produção. Simples não?

Na área de desenvolvimento de software não é tão raro acontecer algo parecido, onde o foco está inteiramente na solução. Sabe aquele sistema meio capenga, que funciona e dá dinheiro para empresa mas não é “web 2.0” nem utiliza conceitos de “SOA”? De repente a diretoria decide que este sistema deve ser “migrado” para uma tecnologia da moda mais atual, que o permita “evoluir” mais facilmente.

Para atender esta necessidade, normalmente uma equipe nova é contratada, toneladas de documentos e diagramas são produzidos até que os programadores comecem a codificar. A esta altura, o prazo já está apertado e os “stakeholders” ainda não viram os resultados. Depois de muito tempo e dinheiro desperdiçados, um sistema feito às pressas, bonitinho mas meia-boca, é entregue com os mesmos defeitos do anterior. E o problema não foi resolvido…

Desenvolver software deve ser um investimento lucrativo, proporcionando algum ganho às partes envolvidas. Quando uma necessidade surgir, o primeiro passo é identificar o problema para então encontrar a melhor solução, ou seja, foco no problema. Neste exemplo da “migração”, o problema é que a manutenção do software atual é muito cara, porém “migrar” o sistema inteiro não vai resolver o problema, no máximo criará um novo.

Mas de quem é a culpa quando o foco está na solução? Eu respondo: a cascata! Apesar das metodologias ágeis estarem em alta e aos poucos serem adotadas pelas empresas, a maldição do waterfall ainda é está entre nós. Clientes continuam com a mania de pedir tudo no início do projeto. Ao exporem seus problemas, já estão pensando na solução. Fazem questão de engordar o escopo com coisas das quais não têm certeza da utilidade, mas querem que estejam lá pois podem precisar um dia. Os desenvolvedores também não estão isentos dessa culpa. Um legítimo analista cascateiro não se envolve com os problemas do cliente, apenas ouvem suas solicitações e transformam em casos de uso ou diagramas. É aí que uma simples necessidade se transforma numa bola de neve e a lenda da caneta da Nasa se repete…

Um verdadeiro desenvolvedor ágil deve se comprometer com o cliente, ouvir, entender e se envolver com suas necessidades para então sugerir uma solução simples, focada e que resolva o problema. Esta interação é muito importante e deve ser constante, pois o cliente passa a identificar o que realmente ele precisa, ou seja, o qual seu problema! Assim, começa a se concentrar em funcionalidades que realmente serão úteis e agregarão valor ao software e, consequentemente, ao negócio. Feedback é muito importante. O pessoal do Google sabe muito bem disso…

Arquiteto Cascateiro

| | Comments


Este post é uma homenagem aos Arquitetos defensores do waterfall/cascata.

Recentemente tive o desprazer de conhecer um arquiteto, é isso mesmo, aquele com certificado e tudo, com direito a broche da Sun em seu terninho. Aliás, certificado é um tema polêmico que eu não tenho uma opinião muito certa e/ou formada… bom, vou deixar esta parte para um próximo post, quem sabe.

Voltando ao assunto, hoje no fretado, comecei a pensar nas semelhanças que um arquiteto de sistemas (certificado que decorou patterns inutéis da Sun) tem com um arquiteto de obras. Só para deixar claro, na tabela abaixo estou usando dois estados: FAIL e Ok. Fail quer dizer que vai dá merda não vai dar certo e não tem jeito, caso queira uma definição mais formal, o wikipédia ajuda, agora se você prefere imagens, o Fail Blog também serve.

Exemplo de FAIL

Objetivos Cascateiro De Obras

Colocam as futuras “obras” no papel antes de começar.

FAIL

OK

Ainda no papel, colocam todas as necessidades do cliente, do início ao fim.

FAIL

OK

O cliente do Arq. de Obras sabe que depois que começar não pode mudar.

FAIL

OK

O arquiteto de Obras não define quais tipos de blocos, cimento e ferro a obra vai usar, o Cascateiro sim.

FAIL

OK

Parei a tabela por aqui pois já dá pra saber que o FAIL tende a infinito né. Pergunta: o que ambos arquitetos estão fazendo!?! Resposta educada: Estão fechando o escopo do projeto.

Arquiteto Cascateiro trabalhando ...

A resposta acima é uma frase chave pra você ter certeza que vive num projeto waterfall cascateiro. Fechar o escopo do projeto inteiro deve ser muito bom para o arquiteto de obras, já para um sistema, o efeito é contrário. Acredito muito na teoria que desenvolver software não é construir prédios. Livros de renome como Pragmatic Programmer citam isso.

Sei que este tema de construção civil já está batido. Comecei a escrever este post ao mesmo tempo que o Sr. Panachi publicou o anterior, e com a idéia de ficar menos repetitivo, já vou linkar as sugestões dos nossos incríveis leitores:

  • O Diego Carrion (grande peruano! :D) cita este link, que fala que a engenharia civil também consegue ser ágil em alguns casos.

  • O Witaro, fez um ótimo post “Desenvolvendo software como uma Rock Band” que quebra a barreira da analogia com a engenharia civil. Cara, continue escrevendo, porque a sua visão é muito legal!

Bom, agora que acabou o desabafo, vamos as possíveis soluções. O que fazer com o Arquiteto Cascateiro?

Acho que a primeira coisa seria conscientizá-lo de que ele não é o Oscar Niemeyer e que a primeira versão de seu software nunca será completa de uma vez. Você deve conversar sobre iterações com ele e mostrar que o software deve evoluir conforme o cliente também evolui nas descobertas das suas reais necessidades. Sei que o post já está cheio de links, mas este post do Phillip Calçado, Analista Pedreiro, resume bem o que quero dizer.

Arquiteto, este nome ou termo ou cargo ou seja-lá-o-que-for, é coisa de modelo waterfall/cascata. Numa equipe, não deve haver distinção desta maneira. Todos programam, modelam, configuram, trabalham no Banco de Dados quando necessário, ou seja, ninguém deve exercer um papel único. Papéis únicos, representam Guardiões que defendem somente seus interesses e não trabalham em pró da equipe/cliente/projeto.

O Arquiteto deve programar, colocar a mão na massa, assim como toda a equipe, pois UML, Caso de Uso, Diagrama de Sequência, etc. sempre compilam! Muito diferente na vida real, onde muitas vezes você é obrigado a implementar uma coisa diferente e torta para acompanhar estes documentos cascateiros. Caso você seja obrigado a gerar a documentação fútil acima, pense em algo que seja automatizado após você ter programado e testado, com certeza você será umas cinco vezes mais produtivo.

E por último e não menos importante, a equipe (inclusive o Arquiteto) tem que conhecer o negócio que implementa. Quando se inicia um novo projeto ou até mesmo decidem reestruturar um existente, o arquiteto cascateiro sempre prioriza novas tecnologias e frameworks, o que na maioria das vezes, não é necessário. Novos projetos ou refactoring em existentes, devem ter um único prioritário objetivo: KISS. Com esta prioridade em mente, novas tecnologias e frameworks serão escolhidos naturalmente, e não somente usar porque é a última moda no estilo SunTechDays.

E vocês leitores?! Sofrem ou já sofreram muito com Arquitetos Cascateiros!?!