quinta-feira, 21 de fevereiro de 2013

Empresa inovadora...

O que é uma empresa inovadora? Como colocar a criatividade das pessoas a favor dos objetivos da empresa, gerando inovação que possa ser revertida em valor real?

Estas são algumas perguntas que parecem ser recorrentes e "esquentam" a cabeça do pessoal de recursos humanos nas organizações que se importam "em mudar o mundo". E aí está o primeiro fator que permite que um grupo de pessoas crie um ambiente inovador: um objetivo extraordinário.

Extraordinário é aquilo que não faz parte do "dia-a-dia", não é "mais do mesmo", não é comum, é excepcional, singular. É exatamente este o combustível da inovação. Fazer algo novo, nunca antes feito.

Mas não basta o objetivo extraordinário. É preciso mais duas coisas: pessoas e ambiente.

Não é possível fazer algo extraordinário sem pessoas extraordinárias. Pessoas que tenham curiosidade e se preocupem com os problemas das outras (afinal, inovação deve gerar valor). Pessoas que se comuniquem com maturidade para gerar conhecimento coletivo.

Muito provavelmente esta combinação Objetivo Extraordinário + Pessoas Extraordinárias já é suficiente para a criação de um produto ou serviço inovador. No entanto, existem vários exemplos onde mesmo estas duas combinações não foram suficientes para criar uma empresa perenemente inovadora, ou seja, que consiga continuamente criar novos produtos e soluções e que sempre surpreenda positivamente o mercado.

Para tornar este processo perene e, mais além do que isso, evolutivo, é preciso que exista um ambiente favorável à inovação. Não é, no entanto, uma tarefa trivial tentar definir como deve ser este ambiente e muito tem sido discutido sobre fluidez de comunicação, team building, etc. Jogos de vídeo-game, cafezinho, confraternizações frequentes. É difícil definir o quanto estas ações influenciam o ambiente permitindo que ele se torne inovador.

Apesar disso, existem alguns fatores que me parecem ser recorrentes em equipes com um ambiente inovador. Vou tentar explicitá-los abaixo:

Um ambiente que maximize a comunicação.

Neste caso, é primordial entender a comunicação como um processo humano e físico. Um ambiente onde as pessoas se encontrem fisicamente, com frequência e de forma amistosa (ou seja, não estou falando de reuniões). Contato virtual é relevante, mas não é suficiente para que idéias fluam.

Um ambiente que reaja positivamente a mudanças.

Existe uma tendência natural das pessoas à acomodação, em qualquer sentido. Faz parte do instinto humano. Um ambiente inovador precisa estar em constante mudança de forma que se torne natural para as pessoas se adaptar e reagir positivamente a estas mudanças.

Tolerância aos erros.

Um ambiente que não tolera os erros suprime idéias. É muito pouco provável que uma ideia inovadora surja sem que antes algumas idéias fracassem. É no fracasso que as idéias evoluem mais fortemente.

Punição da mediocridade.

A tolerância aos erros leva em alguns casos à simples tolerância à tudo. Mas o processo de evolução de uma ideia requer que os fracassos sejam fracassos referentes à visão de um produto que precisa ser ajustada, e não um fracasso na implementação da ideia. Um resultado medíocre é diferente de um resultado ruim, apesar de um resultado medíocre ser sempre ruim. Medíocre é aquilo que não gera valor, que não muda nada, que não permite nem o avanço nem o descarte de uma ideia.
Somente consegue ser continuamente inovadora uma empresa que pune a mediocridade sem punir erros. Mesmo que uma ideia muito ruim (a posteriori) seja implementada, ela deve ser implementada da melhor forma possível.
Enfim, uma ideia boa implementada de forma medíocre provavelmente levará a um resultado desastroso.

Autonomia.

Para aliar a punição à mediocridade e a tolerância aos erros é preciso que as pessoas tenham autonomia para decidir. Vale ressaltar que estamos falando de empresas inovadoras, que precisam de pessoas extraordinárias. Pessoas extraordinárias tomam boas decisões. Podem tomar algumas decisões ruins no meio do caminho, mas a busca pela excelência (que é o oposto da mediocridade) as leva a boas decisões no futuro.
No entanto, sem autonomia, não existem decisões tomadas pela equipe. Ou seja, uma equipe de pessoas extraordinariamente capazes de tomar decisões mas que não tomam nenhuma decisão. Se não quiser dar autonomia a sua equipe, simplesmente dispense as pessoas extraordinárias. É o melhor a se fazer...

quarta-feira, 29 de agosto de 2012

Avaliando a Qualidade de Software

Recentemente participei de algumas consultorias internas na Dextra e externas em clientes com o objetivo de validar arquiteturas e designs de software, tentando apoiar as equipes de desenvolvimento na evolução dos sistemas que estão sendo desenvolvidos. Este, no entanto, não é um trabalho que pode ser realizado sem que alguns conceitos sejam devidamente esclarecidos. Sempre que julgamos alguma coisa levamos em consideração, obviamente, sensações e sentimentos que não controlamos. Por isso precisamos entender este fenômeno humano tentando compreender quais são os conceitos mais essenciais que estão por trás daquilo que molda a nossa percepção à cerca do que estamos analisando. Esta percepção, após alguma reflexão, é o que quero relatar neste post.

Antes de continuar, vamos esclarecer algumas coisas:

Arquitetura = Design = Código-fonte

Como Guilherme Silveira esclarece em How to stop writing next years unsustainable piece of code, a arquitetura e o design de um sistema computacional só existem através de seu código-fonte. Ou seja, o código é a única fonte confiável para a análise da qualidade de um software.

Documentação
A documentação é um instrumento de comunicação que, a meu ver, é muito pouco eficiente (e, em geral, é pouco utilizado efetivamente por desenvolvedores e demais envolvidos no desenvolvimento). Por isso, nunca considerei a documentação do software na análise de sua qualidade. E assim como a arquitetura e o design a documentação não faz sentido se o código-fonte não implementar o que nela está escrito. Portanto, a fonte primária continua sendo o código-fonte.

O que é um bom software?

Ainda antes de identificarmos quais fatores precisamos analisar para avaliarmos um sistema computacional, é preciso alinhar o conceito de "bom software". Colocando sob a perspectiva do cliente, um "bom software" é aquele que evolui de forma rápida e segura, potencializando o ROI (Return Of Investment), ou seja, o retorno do investimento realizado em seu desenvolvimento. Vale ressaltar que o cliente nunca está preocupado com qualidade. Normalmente a qualidade é um item delegado para a equipe de desenvolvimento. Isto não significa que o cliente não queira um "bom software", mas apenas que ele não se preocupa com os detalhes que permitem a criação de um "bom software".

Existem alguns casos em que um "bom software" para o cliente não requer boas práticas de engenharia de software e, nestes casos, avaliar seu código-fonte não será efetivo. Por exemplo, o código-fonte de um software de uma campanha de marketing que durará duas semanas. Apesar de conhecer este exemplo, eu nunca vi um sistema que não precise de manutenção. Que possa ser, simplesmente, "jogado fora".

Existe ainda uma forma de medir a qualidade do software usando o ROI. Já que um "bom software" potencializa o ROI, por que não usar esta métrica para medir a qualidade do software. Esta, me parece, a melhor das alternativas. No entanto, existe um problema complexo de ser resolvido. O ROI está relacionado com mais algumas variáveis além da qualidade do software (mercado, concorrência, gestão interna, outros softwares, etc). A não ser através de um estudo matemático destas co-variáveis é muito difícil medir o quanto cada variável influencia no ROI e, portanto, é difícil tirar uma métrica da qualidade do software pela medida do ROI. Normalmente um ROI baixo é o motivador para a realização da análise da qualidade de um software, mas nem sempre indica um software ruim.

Como saber se um software é bom?

Partindo da premissa do que é um "bom software", precisamos compreender o que nos leva (desenvolvedores) a acreditar que um software é bom. Para isso, é preciso se colocar na posição de um desenvolvedor que, sem nenhum conhecimento prévio sobre o sistema em avaliação, tem que realizar alterações funcionais de diferentes níveis de complexidade neste sistema. É importante ressaltar que estas alterações devem ser realizadas de forma segura, ou seja, é preciso que seja contabilizado nesta análise o tempo para a realização de testes das funcionalidades afetadas pelas supostas alterações.

Nesta situação, existem essencialmente três fatores que podem ser facilmente avaliados para a qualificação do código-fonte de um sistema computacional:

Testabilidade
Quanto mais fácil e rápido é testar um software, mais rapidamente e de forma mais segura alterações podem ser realizadas nele. Testabilidade, em termos técnicos, tem a ver com desacoplamento, com gestão de dependências, com separação de camadas, com mecanismos de integração, etc. A pergunta a ser respondida é: Quão fácil e rápido é testar o software antes e depois da alteração realizada? Esta pergunta deve levar em perspectiva os testes de regressão sobre todas as funcionalidades potencialmente afetadas pela alteração em questão.

Aderência ao Negócio
Se, mesmo desconhecendo o código-fonte e o negócio envolvidos, ao conversar com um usuário (não com um desenvolvedor) sobre uma nova funcionalidade, eu puder rapidamente e de forma segura encontrar no código-fonte o local apropriado para realizar a alteração desejada, terei a percepção de que o código e o negócio são coerentes. Os termos usados pelos usuários estão representados no software, assim como as relações, conceitos, etc. Tecnicamente, esta questão reforça características como reutilização de software, organização de módulos / componentes, orientação a objetos, etc. A pergunta a ser respondida é: Eu consigo encontrar rápida e seguramente no código-fonte o local onde uma alteração deve ser feita após uma conversa com o solicitante de uma nova funcionalidade?

Adaptabilidade
Um sistema é adaptável se é possível alterar a arquitetura de uma parte deste software sem a necessidade de reimplementar um volume muito maior de funcionalidades do que o estritamente necessário. Tecnicamente, esta questão reforça questões como componentização e protocolos de integração. A pergunta a ser respondida é: Eu consigo alterar a arquitetura de uma funcionalidade para ganhar, por exemplo, escalabilidade, sem ter que alterar a arquitetura de todo o sistema ou de uma grande parte dele?

Esta é uma abordagem simples, prática e abrangente para a avaliação da qualidade do código-fonte de uma aplicação. O que acham? Existem outras variáveis a serem consideradas?

terça-feira, 21 de agosto de 2012

Learn by Example

Alguns anos atrás pude conviver um pouco com minha cunhada arquiteta enquanto viajávamos por algumas cidades do interior da Itália. Uma das coisas que me surpreendeu na viagem foi a atenção que ela dava aos detalhes das construções, tirando fotos de calhas, paredes, janelas, portas, etc. Enquanto nos preocupávamos com um mundo novo que conhecíamos, ela ficava atenta a cada detalhe.

Fiquei, obviamente, intrigado com o comportamento dela. E fiquei ainda mais intrigado após entender por que ela observava o trabalho dos outros com tanto afinco. Na arquitetura, o processo de criação leva em consideração a observação do trabalho dos outros arquitetos.

O processo de desenvolvimento de software também é um processo criativo. No entanto, parece-me que neste processo a observação do software desenvolvido por outras pessoas não tem um papel tão fundamental. Pelo menos não tem o papel que deveria ter.

Erich Gamma, Richard Helm, Ralph Johnson e John Vlissides (GoF) foram em um caminho parecido, ao utilizar a observação para identificar padrões de solução de problemas em software. Martin Fowler também é outro expoente deste tipo de observação e de sua aplicação na vida real. No entanto, a prática da observação realizada por estes grandes nomes da computação não foi absorvida pelos demais desenvolvedores (com exceções, claro). Apenas os resultados de sua observação é que se tornaram notáveis, e não o processo pelo qual estes resultados foram obtidos.

Os design patterns são exemplos de como a observação é efetiva. No entanto, o uso destes design patterns não é o benefício mais importante destes trabalhos. O benefício está no processo de observação e aprendizado. É este processo que precisamos exercitar constantemente e é nesta observação que devemos basear nosso aprendizado.

segunda-feira, 6 de fevereiro de 2012

Continuous Delivery - 1o passo

Se você almeja alcançar o continuous delivery, já deve ter se perguntado: por onde começar?

Os aspectos que envolvem a entrega contínua e a confiança de que cada commit é um candidato a ir para produção são pouco triviais e, em alguns casos, difíceis de serem implementados. Apenas após bastante aprendizado e experiência é possível alcançar a confiança necessária para o continuous delivery, sem esbarrar no perigo do holpeful delivery. Mas, para quem está iniciando a caminhada, o principal problema é saber por onde começar. Existe um caminho conhecido e seguro a trilhar?

Bom, continuous delivery é uma ciência ainda bastante nova, mas já surgem alguns exemplos de sucesso que podem servir de guia para as equipes que estão investindo neste caminho.

Enfim, para começar este caminho existe um passo que considero o mais essencial e que, apesar de ser uma prática pregada recorrentemente, é pouco usada de forma realmente efetiva e sua efetividade é essencial para o continuous delivery. Esta primeira prática consiste, basicamente, em "pensar evolutiva ou incrementalmente".

Mas por que esta prática é importante?

Ser ágil é muito mais do que usar postits para organizar as atividades. Ser ágil é mudar a forma como você enxerga as funcionalidades. Ser ágil é pensar sempre, à exaustão, de forma incremental. Como se você estivesse sempre desenvolvendo software para uma startup sem dinheiro. Não existe nenhuma funcionalidade que não possa ser escrita de forma incremental em atividades de, no máximo, uma hora.

Quando os desenvolvedores pensam de forma incremental eles realizam mais commits por dia, diminuindo o risco de cada commit. Cada acréscimo de funcionalidade deve manter o sistema consistente, mesmo que a funcionalidade não esteja completa. Ou seja, nunca deve "estourar" um erro para o usuário.

Para exemplificar o desenvolvimento incremental, imagine uma atividade bem comum e simples como desenvolver um relatório. Ou seja, em alguma tela do sistema deveremos acrescentar um botão que permita o download de um relatório em formato PDF com cálculos, sumarizações, etc. Vamos fazer incrementalmente?
  1. Inclua um botão que não faz nada na tela;
  2. commit;
  3. Faça este botão chamar algum serviço (JavaScript, JSF Action, Servlet, etc) que ainda não faz nada na tela;
  4. commit;
  5. Faça o botão retornar uma mensagem de erro informando que a funcionalidade ainda não foi implementada;
  6. commit;
  7. Implemente uma validação necessária e retorne a mensagem de erro adequada;
  8. commit; (retorne para o item 7 quantas vezes forem necessárias)
  9. Implemente a busca dos dados para a composição do relatório usando o filtro mais simples / padrão possível;
  10. commit;
  11. Monte o relatório usando as informações mais simples possíveis;
  12. commit; (retorne aos passos 9 a 12 incrementando a complexidade da consulta e do relatório gerado)
Todas estas iterações devem ser pequenas e rápidas. 15 minutos seria o ideal para cada incremento de funcionalidade, mas até 60 minutos é um tempo aceitável. Nenhum dos commits deve "quebrar" o sistema.

Claro que esta técnica é mais complexa do que parece neste exemplo simples, mas para se chegar ao continuous delivery é preciso que a equipe faça esse avanço obsessivamente incremental de forma natural. Um Dojo (RandoriKata) com um timeboxing bem curto (5 a 10 minutos) é uma ótima maneira de capacitar a equipe neste sentido.

domingo, 5 de fevereiro de 2012

JavaEE vai morrer???

Spring versus JavaEE é uma daquelas discussões que são eternas. Não quero me prolongar nas qualidades de uma ou de outra tecnologia, mas apenas em um fenômeno muito forte que vem ocorrendo e que deveria deixar a maior parte das organizações atentas. Este fenômeno chama-se PaaS (Plataform as a Service).

O PaaS surge como forma de tornar praticamente transparente a gestão da infra-estrutura de um sistema computacional, trazendo a escalabilidade de forma flexível e com pouco ou nenhum overhead. No entanto, as soluções mais recentes apontam para o uso de plataformas mais leves como Python, Ruby on Rails, JavaScript, .NET e Java / Servlets, deixando completamente de lado a plataforma JavaEE. E há uma razão para isso: ninguém precisa de JavaEE de verdade. JavaEE nada mais é que uma solução em busca de um problema a ser resolvido.

Neste sentido, ferramentas úteis aos desenvolvedores fornecidas na plataforma JavaEE podem ser obtidas, usando apenas programação declarativa, através do Spring Framework, que pode ser executado em qualquer plataforma que suporte Java puro.

Ou seja, desenvolva com Spring (ou Guice, ou não use nada para injeção de dependências) e possibilite a realização de deploy na nuvem (BeansTalks e GAE, por exemplo). Em um mundo onde a infra-estrutura se torna transparente, JavaEE não parece ter muito futuro.

sábado, 15 de outubro de 2011

Hopeful Delivery

Com as técnicas de continuous delivery em constante debate na comunidade de desenvolvimento, uma prática já bastante consagrada vem se tornando cada vez mais comum. Isso ocorre por que esta prática acaba sendo confundida com continuous delivery na medida em que as entregas ocorrem com mais frequência. A esta prática eu dou o nome de Hopeful Delivery.

O hopeful delivery implica em gerar uma versão de seu produto para colocar em produção que a equipe (e os demais envolvidos) tenham esperança de que funcione. Em alguns casos algumas pessoas chegam a confiar na entrega, mas esta segurança não é compartilhada por todos os membros da equipe ou pelos demais envolvidos, ficando somente na esperança.

Vale ressaltar que, se a confiança não é compartilhada por todos os membros da equipe, pelo cliente, pelos usuários e todos os demais envolvidos, então a entrega não é confiável. Entregar continuamente desta forma pode ser chamado de Continuous Hopeful Delivery.

Como fugir do Hopeful Delivery?

O primeiro e mais trivial sintoma do hopeful delivery é quando nenhum membro da equipe, ou quase nenhum, confia nas entregas que estão sendo realizadas. Neste caso, existe a possibilidade de a equipe estar desacreditada de seu próprio potencial ou de conhecer suas atuais limitações. Busque deixar transparentes as limitações da equipe (técnicas, recursos, comportamentos, etc), criando um ambiente onde a equipe se sinta confortável para aprimorar suas habilidades de forma a alcançar um nível de maturidade e qualidade em que a confiança comece a se tornar presente.

Um segundo e importante sintoma é a desconfiança ou insegurança de algum membro da equipe nos mecanismos (tecnológicos e comportamentais) criados pela equipe para garantir a segurança da entrega. Em geral, quando existe esta desconfiança é por que a capacidade técnica dentro da equipe não está nivelada ou existem conflitos entre seus membros. Em ambos os casos, problemas podem estar sendo mascarados e não existe transparência no funcionamento da equipe. Neste caso, será preciso resolver os conflitos na equipe e buscar disseminar o conhecimento necessário para que a equipe tenha um conhecimento avançado das técnicas e ferramentas necessárias para garantir a qualidade da entrega.

O terceiro e mais óbvio sintoma são os erros em produção. Erros em produção sempre acontecem, mesmo em entregas verdadeiramente confiáveis. O grande problema de entregas baseadas na esperança é o descontrole da equipe com relação aos erros que ocorrem em produção. Neste caso, é importante disponibilizar alguma forma de a equipe tomar conhecimento de forma direta sobre os erros que ocorrem em produção. Medir (em tempo real) os erros é importante e dar o feedback diário à equipe com relação aos erros pode ser a chave para trazer o comprometimento necessário na solução dos defeitos. Com a métrica em mãos, também pode-se definir metas e limites, onde o regime de trabalho (stop the line!) pode ser definido de acordo com estas métricas.

Finalmente, se o cenário do seu projeto implica:
  1. Falta de confiança na equipe
  2. Equipe trabalhando de forma pouco transparente, conflitos e desnivelamento de conhecimento muito acentuado
  3. Quantidade de defeitos em produção desconhecida ou não está sob o controle da equipe
você não está fazendo continuous delivery, mas hopeful delivery. Busque o continuous delivery de forma consistente, focando em confiança e comprometimento da equipe, pois esta busca pode ser a melhor forma de alcançar a solução para estes problemas.

segunda-feira, 10 de outubro de 2011

What about Continuous Delivery?

O emergente conceito de Continuous Delivery no desenvolvimento de software tem movimentado a comunidade de desenvolvimento com muitos questionamentos e controversas. Feature Branches, uma das técnicas que suporta a entrega contínua, divide a comunidade e desafia até as equipes mais experientes em desenvolvimento ágil. Mas o assunto suscita uma questão muito importante:

Será que existe necessidade para continuous delivery fora do contexto de produtos para a nuvem e startups?

Para responder esta pergunta é preciso compreender o que está por trás do continuous delivery e por que esta prática é tão controversa. Tecnicamente, continuous delivery refere-se, obviamente, à entrega contínua, ou seja, unificar as linhas de desenvolvimento de forma a permitir que todas as funcionalidades (inclusive as que ainda não estão concluídas) possam ser seguramente colocadas em produção a qualquer momento. Isso implica a entrega de todo o produto continuamente e coloca sob a responsabilidade da equipe (e não das ferramentas usadas por ela) toda a gestão de configuração.

Isto faz muito sentido quando se fala de uma startup que precisa ser muito ágil no desenvolvimento de novas funcionalidades assim como na correção de defeitos. Também faz sentido no desenvolvimento de produtos ou serviços baseados na nuvem, permitindo que as funcionalidades sejam disponibilizadas de forma particionada entre os usuários, por exemplo.

Mas e nas aplicações organizacionais? Aplicações de backoffice de um banco, por exemplo? Faz algum sentido este tipo de abordagem onde o processo de homologação do sistema dependa de questões legais, por exemplo?

Aparentemente a resposta a estas perguntas é um sonoro não! Mas existe ainda um outro ponto de vista a ser analisado:

O que é preciso para uma equipe de desenvolvimento alcançar o continuous delivery?

Ao analisar esta questão sob este ponto de vista, a primeira característica que me vem à mente é a confiança. Aliás, confiança ao extremo. Como a equipe adquire confiança para gerar uma versão estável a cada commit?

Ao olharmos para a história da engenharia de software podemos observar muitos processos que surgiram (gestão de configuração, homologação, testes automatizados, integração, etc) para gerar confiança, mas todas estas ferramentas não conseguem proporcionar a segurança  necessária sem a direta intervenção humana. O continuous delivery implica a ubíquação de algumas destas técnicas de forma a torná-las quase que imperceptíveis. Ou seja, se por um lado a confiança sempre foi necessária e nunca foi alcançada com as ferramentas que temos em mãos, por outro lado, estas ferramentas usadas à exaustão podem enfim garantir a confiança?

Mais uma vez a resposta é não! Isso por que a única forma de garantir que a entrega realizada, mesmo que feita continuamente, é confiável é a sensação que as pessoas têm sobre o produto entregue. Confiança é uma emoção humana e uma ferramenta não pode nos trazer "confiança de forma confiável". Por exemplo, uma suíte de testes extensa não pode garantir isso, pois precisamos confiar nas pessoas que escreveram esta suíte de testes para confiar na própria suíte. A confiança nas pessoas é que garante a confiança nas ferramentas por elas usadas.

Ou seja, a confiança é da e na equipe, não nas ferramentas. E só existe confiança se a equipe for muito boa tecnicamente e estiver totalmente comprometida. É impossível ou irresponsável ter confiança em uma equipe de baixa qualidade. É impossível ou irresponsável ter confiança em uma equipe que não está comprometida.

Com o continuous delivery, a execução exaustiva do processo de entrega faz com que a equipe tenha que evoluir continuamente para garantir a confiança na qualidade do produto entregue. Afinal, não existe continuous delivery se você não puder implantar uma versão em produção "tomando uma caipirinha na praia" (Jez Humble). E esta confiança deve ser refletida em toda a equipe e não apenas em um grupo de especialistas ou integradores, pois cada commit é um candidato à produção. Cada alteração deve ser auto-suficiente e não pode haver dependências de tarefas e funções dentro da equipe.

Desta forma, a conclusão a que podemos chegar é que o continuous delivery implica a busca pela confiança contínua e uniforme em toda a equipe. E esta busca implica a necessidade de aumento da qualidade da equipe e do seu comprometimento. Ou seja, o processo de chegar ao continuous delivery é mais importante do que entregar continuamente software em produção.

Enfim, se confiança é palavra-chave no seu negócio, continuous delivery é o processo que pode te levar até ela.