Categoria: Processos

Integração Contínua

Objetivo

Recentemente, numa das listas de discussão que participo (.NET Architects), surgiu a discussão sobre integração continua. Fiquei um pouco surpreso. Apesar de integração contínua ser uma prática um tanto quanto antiga (a primeira referência que conheço do assunto é do livro do Kent Beck, de 1999), muita gente ainda se assusta ao falar do tema.

Essa foi minha motivação para escrever um pouco sobre integração contínua (CI – Continuous Integration) aqui.

O que é integração contínua

Primeiro vamos tentar entender o que “não é” integração contínua. Antigamente (assim espero), os desenvolvedores costumavam trabalhar em “silos”. Cada um pegava um pedaço do sistema pra fazer, fazia no seu canto e colocava-se um tempo de “integração” nos cronogramas. Esse tempo era para fazer os ajustes necessários para o lego todo se encaixar. Por exemplo: Um fazia a tela, o outro fazia o servidor, o outro as procedures de banco.

É claro que muita coisa dava errada. Nem sempre os contratos eram definidos em detalhes, muitos aspectos eram deixados de lado e na hora de integrar tudo, era uma longa dor de cabeça.

A proposta da prática de integração contínua é que ao contrário de segurar as alterações e subi-las somente no final do projeto e integrar tudo ao mesmo tempo, as pessoas devem constantemente integrar o seu trabalho ao restante do time. Lembro-me no livro original do Beck que ele tinha a proposta inclusive das pessoas fazerem o build numa máquina separada da sua máquina de desenvolvimento, justamente para evitar o famoso “na minha máquina funciona”, que gerou um dos posts mais divertidos sobre o assunto: The Works on My Machine Certification Program

Em resumo, a idéia da prática é (tradução das principais partes do wikipedia):

  • Use um repositório de controle de versão: Não, não vale uma pasta na rede compartilhada, um pen-drive com o código fonte. É um software de controle de versão que gerencie concorrência, mantenha histórico, permita que você administre branches, etc.
  • Automatize o Build: Sim, montar o seu pacote, exatamente como deveria ser entregue para seu usuário final deveria ser um processo de “um passo”. Apertar um único botão, e do outro lado deveria sair um pacote pronto, com todas as dependências resolvidas
  • Faça o build auto-testável: É uma excelente idéia juntar seus testes unitários ou mesmo de aceitação com o seu processo de build
  • Todo commit deve disparar um build: Cada vez que qualquer coisa é alterada no repositório de controle de versão, um build deve ser disparado, obviamente, disparando todo o processo de empacotamento e testes, e claro, se você já estiver neste nível de maturidade, deploy
  • Mantenha o build rápido
  • Todos devem ver o resultado do último build

Como implementar

Felizmente, hoje existem ferramentas open source fantásticas (em sua maioria melhores do que pagas) para implementar todo esse processo.

Para controle de versão, sugiro consultar a última pesquisa sobre controle de versão e também o post sobre gestão de configuração e versões.

Para a automação e criação do servidor de integração contínua, sugiro os seguintes passos:

Instale um servidor de integração contínua

Suba uma instância do seu servidor favorito. Os mais populares são:

  • Jenkins: Open-source, mais popular na comunidade Java, mas serve para buildar qualquer tipo de código fonte
  • Team city: Da JetBrains, free até uma certa quantidade de projetos. Ferramenta fantástica, muito intuitiva
  • CruiseControl.NET: Começou com a ThoughtWorks, agora parece que a comunidade open source assumiu. Foi meu favorito durante anos, mas ainda demandava muita configuração “na mão”

Existem outros também, como o próprio Team Foundation Server, Rational Team Concert, mas em geral não são tão simples e populares como os supra-citados, que suportam uma série de ferramentas de controle de versão. Aliás, esse é um ponto importantíssimo. Verifique se o servidor suporta o controle de versão que você usa.

Se você usa cvs, svn, git, garanto que não terá muito sofrimento em configurar qualquer um deles. Se você usa, TFS, VSS, RTC e outros, o máximo que posso dizer é: boa sorte. Esses controles de versão tem uma interface de linha de comando muito pobre, o que torna bem chato fazer qualquer tipo de automação.

Crie um script de build

Se você vem de plataforma Microsoft, usar o MSBuild será “natural” para você. Veja o post MSBuild in a nutshell sobre como criar os builds.

O ant é o irmão mais velho, da comunidade Java.

Esses “toolkits” de build nada mais são do que ferramentas para automatizar a execução de atividades de linha de comando. Se você não sabe trabalhar com linha de comando, aqui está uma excelente motivação para aprender. Será inevitável trabalhar direito com linha de comando para mexer com automação de build.

Os toolkits também permitem criar “tasks” customizadas, de forma que você pode utilizar todo seu conhecimento no seu framework favorito para fazer as maluquices mais improváveis em builds.

A dicas sobre automação de builds:

  • Comece de forma muito simples e depois vá tornando mais completo. Primeiro, faça o fonte compilar. Já dá para ter ganhos absurdos só fazendo isso
  • Mesmo que seu projeto não tenha testes, deixar a “infra-estrutura” pronta para receber os testes é uma boa. Por infra estrutura digo, a casca do projeto de testes e a mecânica para invocar os testes no build. A medida que o time percebe que nunca mais um teste ficará vermelho, porque o build quebra, a integração contínua pode ser uma forte aliada para alavancar os testes unitários
  • Empacotamento: O build não é somente compilar, ele também significa reunir todas as dependências necessárias para rodar a aplicação. Isso engloba: scripts de base de dados, binários externos, instaladores, etc.
  • Métricas: O MSBuildCodeMetrics é um projeto que comecei justamente com esse intuito. A idéia é chegar num nível de automação que se alguém commitar um método com mais e X linhas ou com complexidade ciclomática superior a Y, o build quebra.
  • Manutenção de numeração de versão: Quando se ganha experiência, o processo de criar as “tags” corretamente e carimbar as versões, pode ser todo feito no servidor de integração contínua. A série automatizando o versionamento no build (Parte 1 e Parte 2) falam um pouco sobre esta idéia.

Como os builds rodam server-side, é muito importante ser disciplinado na hora de montar o servidor de build. Eu por exemplo, não instalo Visual Studio em servidor de build, justamente para que os builds quebrem ao menor sinal de que alguma dependência “estranha” foi inserida na aplicação.

Notificação do build

Mais importante do que o build quebrar ou ter sucesso, é o time saber disso! Não adianta nada o build quebrar e ninguém corrigir. Por isso, é imprescindível instalar um notificador.

Os servidores de integração contínua, geralmente mandam e-mails. Infelizmente desenvolvedores em geral não dão muita atenção para e-mails corporativos.

Eu recomendo a instalação de um notificador associado ao “system tray”. O CruiseControl.NET tem o “CCTray”, que faz isso muito bem. O Jenkins tem o hudsonTracker ou o próprio CCTray que funciona no Jenkins (particularmente uso o CCTray).

Vale a pena sair instalando de máquina em máquina o notificador.

As etapas da implantação da integração contínua

Primeiro vem a etapa da negação. Os tipos de #mimimi mais comuns que você ouvirá serão:

  • A ferramenta de controle de versão fez merge errado
  • Na minha máquina funciona
  • O servidor de build está com problema

Paciência. Vale a pena pegar caso a caso e mostrar um a um o que o desenvolvedor fez de errado. Uma vez que ele entenda, ele não vai querer passar a mesma vergonha duas vezes.

Depois da etapa da negação, vem a etapa da aceitação. Nessa etapa, as pessoas não criticam mais a estabilidade e a necessidade do processo de build, mas também não contribuem. O build fica lá quebrado, e ninguém se interessa por arrumar. É nessa hora que vale a pena discutir um pouco sobre “propriedade coletiva de código”. Se o build quebra, é problema de todos.

É importante combinar algumas regras para fazer a prática pegar. Já vi castigos físicos (não recomendado, porque eu preciso ser politicamente correto num blog), colocar dinheiro num pote (Ex.: R$1 a cada quebra de build e o dinheiro é usado depois para comprar guloseimas) e em último caso a autorização para voltar qualquer commit que quebra o build. Quebrou o build? Alguém vai lá e volta o commit e o cara tem o trabalho de se virar para colocar as coisas no lugar.

Depois da fase da aceitação, vem a fase da dependência. Desligue o servidor de build por um dia. Se ninguém reclamar, você ainda não atingiu seu objetivo. Minha experiência mostra que uma vez que o time ganhe a maturidade para trabalhar com integração continua, ele não consegue mais trabalhar sem. É a regra básica para convivência no condomínio.

Vantagens e Desvantagens

Já fiquei me perguntando várias vezes as desvantagens de trabalhar com integração contínua, e não encontrei. Realmente é uma prática, na minha opinião, básica, essencial para qualquer projeto de desenvolvimento de software.

E as vantagens? São inúmeras. Algumas delas:

  • Você pode chegar todo dia para trabalhar, atualizar o código, tendo a certeza que o fonte vai compilar e você pode começar o seu dia
  • A automação de deploy se torna viável, pois você consegue construir sua aplicação, com qualquer versão, em qualquer momento do tempo
  • Suas dependências ficam mais fáceis de monitorar. Você conhecerá todos os binários de que depende, todas as ferramentas que precisa instalar para sua aplicação funcionar, e obviamente, se alguém quebrar a regra, descobrirá rápido (porque o servidor de build não tem o componente não-autorizado instalado)
  • Seu time vai aprender a subir código fonte somente quando as coisas estiverem minimamente estáveis. Os ganhos de produtividade nisso são enormes. Ninguém fica parado esperando o outro corrigir a besteira que fez no código
  • Você ganha um “evento” para fazer qualquer automação no momento que alguém subiu alguma alteração. Com isso, consegue fazer valer uma série de regras como: métricas, consistência de scripts de banco, formatação de código, e o que mais achar necessário

Era isso.

Controle de Versão – Parte 2

Introdução

Hoje recebi um e-mail do meu grande amigo e ex-colega de trabalho Godoy (@godoy42), mago supremo do tunning de queries e macumbas avançadas em banco de dados. Não acompanho de perto, mas fico imaginando o que ele anda aprontando na área de BI.

Ele viu os dados da pesquisa, baixou e montou dois gráficos muito bacanas com os resultados. Seguem abaixo.

Satifação com o sistema atual

Aqui, cada resposta com ferramenta atual igual a desejada, soma um ponto de satisfação, cada resposta diferente, um ponto de insatisfação. Resultado expresso em percentual:

GraficosGodoy1

Ferramenta desejada para substituição

GraficosGodoy2

GraficosGodoy3

Origem dos problemas por ferramenta

GraficosGodoy4

Controle de Versão – Resultados

Objetivo

Estou passando por um processo de avaliação de processos e ferramentas de SCM e ALM (pra variar um pouco, já que por praticamente todas as empresas que já passei, a discussão volta) e buscando referências sobre o assunto. Infelizmente a maioria das referências que encontrei falava somente sobre qual melhor controle de versão, sem comentar muito sobre tamanho de time, como organizar os branches, experiência da equipe, etc., além de não conter informações sobre algumas ferramentas mais novas.

Outra coisa que quis colocar na pesquisa é não só o que está sendo usado e como as pessoas trabalham atualmente, mas também o que elas gostariam de estar usando e como gostariam de trabalhar. Gostei do resultado.

De repente, pensei… por que não fazer uma pesquisa? Rapidamente consegui algumas respostas e informações bem interessantes que seguem abaixo. Os dados são os originais do Google Docs. Apenas não publiquei o link original, por que ao contrário da minha expectativa, a grande maioria se identificou com e-mail, que não acho correto republicar.

Perfil

No total, foram 140 respostas em uma semana de pequisa.

SCM2013-1

SCM2013-2

SCM2013-3

SCM2013-4

SCM2013-5

Freqüência de entrega e percepção de problemas

SCM2013-10

Ferramenta

SCM2013-6

SCM2013-7

SCM2013-11

SCM2013-12

Organização do repositório

SCM2013-8

SCM2013-9

Integração contínua e continuous delivery

SCM2013-13

SCM2013-14

SCM2013-15

SCM2013-16

Comparativo entre as ferramentas

SCM2013-17

  • Respostas válidas: Total de respostas diferentes de “Não conheço”.
  • Aprovação: Total de respostas “O melhor” e “bom” em relação às respostas válidas

Comentários da pesquisa

Durante a realização da pesquisa, surgiram alguns questionamentos que acho válido listar aqui.

Perfil de empresas

Colocar qual é o perfil da empresa que a pessoa trabalha (consultoria, fábrica de software, produto, etc), tamanho da empresa, etc.

Por que TFS está separado em várias versões?

Ao usar o TFS 2008 e conversar com pessoas que usam a versão 2012, muita coisa mudou, o que pode-se dizer que muda até o conceito da ferramenta (de lock para share, por exemplo). Por saber disso de antemão, separei as versões.

TFS é lock ou share?

Como o TFS tem uma idéia de lock “compartilhado”, deu essa confusão. No meu entendimento, se tem lock (mesmo compartilhado) e os arquivos ficam com aquele chatíssimo efeito de read-only pra poder usar (dizem que no 2012 isso foi melhorado), pra mim é lock. Por isso a pergunta é binária. Muitas pessoas consideraram share. Na próxima pesquisa, considero uma opção de “lock compartilhado”.

Opções entre bom e ruim

Optei por não manter, justamente pra fazer a pessoa sair do muro e a pesquisa ser mais assertiva.

Incluir cenários

Ótima idéia. Não tinha pensado nisso. Vou incluir nas próximas.

Razões para não mudar de ferramenta e organização

Essa eu mesmo achei que faltou, depois que mandei a pesquisa. Como vemos nos resultados, tem um gap muito grande entre o que as pessoas fazem e o que elas gostariam de fazer. Minha idéia é entender a razão deste gap: Política, Financeira (tempo/prazo), Preguiça, sei lá.

Incluir notas explicativas

Por incrível que pareça, muitas pessoas tiveram dúvidas sobre o que é integração contínua, continuous delivery, estressar um pouco as políticas de versionamento. É algo a melhorar.

Avaliar crashs

Incluir perguntas sobre ocorrência de quebras no controle de versão e a capacidade de recuperação de cada um deles.

Nível de conhecimento em cada ferramenta

Incluir se a pessoa se sente senior, junior ou pleno em cada ferramenta que avaliou. Gostei da idéia e vou incluir nas próximas.

ALM, critérios de gestão de releases (patch/full), etc.

Não pretendo incluir, não porque o assunto não merece, mas porque gostaria de manter essa pesquisa com a idéia apenas de controle de versão, porque acho que já tem assunto suficiente para debate aqui. Os outros, acredito merecerem tópicos só pra isso.

Links externos

Durante essa pesquisa, seguem alguns links que encontrei ou me enviaram (tks Beccari!) e acho válido compartilhar:

Dados

Caso alguém queira tirar/buscar outras conclusões, estou publicando o Excel com as respostas, sem os comentários e os e-mails. Segue o link: Controle de Versão-2013.

Agradecimentos

Meus sinceros agradecimentos a todos que participaram e contribuiram com a pesquisa. Não imaginava que conseguiria num tempo tão rápido um conjunto de respostas no mínimo representativo.

Pesquisa sobre Controle de Versão

Estou realizando uma pesquisa sobre o uso de controle de versão.

Peço 10 minutos do seu tempo para ajudar a melhor entender as ferramentas e práticas atualmente usadas. Peço que repliquem para seus amigos desenvolvedores para criarmos uma massa bem crítica de respostas.

Aceito sugestões!

Segue o link do Google Docs: https://docs.google.com/forms/d/1big0uigPO8sStHVRApOMptsnmLclIDaOWRWk5BsCXSQ/viewform

Enfim, Ágil

Introdução

Lembro a primeira vez que tive contato com alguma metodologia ágil, em 2004. Naquele momento, a primeira prática que mais me trouxe resultado foi a integração contínua, mas o XP também falava de uma série de outras coisas. No meu post sobre TDD, relatei as tentativas de incorporar esta prática e o tempo que levou até entender o real benefício dela (no meu caso, fui bem cabeça-dura).

Das práticas mais confusas, a parte de estimativas do XP talvez seja a mais revolucionária. Mudar a idéia que eu já tinha na na época de cronograma, planejamento, levantamento detalhado de requisitos era muito pra mim. Quando eu percebi que a metodologia não mais daria aquela “certeza” de que a coisa aconteceria no prazo, logo conclui que o mercado nunca iria aderir àquilo, pois o modelo de comercialização seria muito complexo de implementar. Mas sempre achei que a XP descreve o que melhor funciona no mundo de software.

7 anos depois

Um bom tempo depois, numa das empresas que trabalhei, houve uma tentativa de implementação de SCRUM. Eu tinha lido muito pouco sobre o assunto, dada a conclusão precipitada que tive sobre a dificuldade de comercialização do SCRUM. Como trabalhava numa empresa que tinha um viés de desenvolvimento de produto (apesar das customizações por muitas vezes fazerem a empresa funcionar como uma consultoria que vendesse projeto a preço fechado), havia uma preocupação com a qualidade e com o acompanhamento dos projetos.

Foi engraçado ver tanta parede com post-it pregado e diversas reuniões, mas não consegui ver o entusiasmo nas pessoas e uma mudança cultural profunda. Depois entendi o que aconteceu. Foi mais uma daquelas situações que um processo é totalmente personalizado pra encaixar na empresa, o processo não funciona e posteriormente a coloca-se a culpa no processo. No Scrum inventaram até um nome pra isso: Scrum, but…

E o cascata, funcionava?

Eu sempre fui um defensor de trabalhar com projetos em fases menores no cascata (entregas menores e mais frequentes) e de levantamento de requisitos exaustivos (meu post, levantamento de requisitos mostra isso) e de fato consegui alguns resultados interessantes, mas minha experiência me mostrava que algumas coisas não iam tão bem assim.

O custo para montar um cronograma completo no início do projeto era enorme. Era de semanas a meses pensando atividade a atividade, quem iria fazer. Não foram poucas as vezes que “desenvolvedores virtuais” aparecerem no cronograma, contando que em algum momento eles seriam contratados, treinados e entrariam no projeto funcionando e jogando.

Sempre que alguma mudança ocorria no meio do projeto (o que acontecia com frequência, porque em desenvolvimento de software, requisitos mudam!) era um esforço enorme pra replanejar.

Numa empresa que trabalhei, percebi uma das maiores falhas do levantamento de requisitos exaustivo no início do projeto. Eu trabalhava para capturar os requisitos, escrevia casos de usos detalhados e os usuários validavam. Quando apresentávamos o software, ficava uma discussão quase contratual, pois o cliente alegava que não era o que ele precisava e o desenvolvedor alegava que era o que estava escrito. O cliente desejava melhorias no que foi entregue, porém, não existia o “espaço” no cronograma para tais melhorias, e voltava a discussão ao cronograma. Os dois estavam certos. Nova mudança, novo replanejamento, o que significava outro ciclo infinito de reuniões para discutir o cronograma, alinhar expectativas.

De fato, foram semanas discutindo cronograma e o que fazer. O tempo de alinhamento versus construção era desproporcional. Perdia-se mais tempo discutindo o que fazer do que de fato fazendo. O resultado final foi uma equipe frustrada, a consequente debandada e a paralisação de uma série de projetos.

Enfim, ágil

Recentemente, após uma mudança de área, passei a trabalhar com a abordagem ágil. Começamos com mais um Scrum But, ou seja, aplicando o Scrum somente na fase de desenvolvimento do projeto, e aos poucos fomos mudando para um modelo de inserir o usuário nas reuniões, nas discussões e estimulá-lo a exercer um papel de product owner.

Confesso que eu comecei meio cético no projeto, remetia ao passado, à brincadeira de mexer post-its e não conseguia entender como isso ia me ajudar a fazer software melhor. Eu recebi um release planning praticamente pronto, e fomos para nosso primeiro sprint planning.

Foi um pouco assustador, um time, pela primeira vez junto, num projeto que poucos tinham contexto discutindo como as coisas seriam feitas. Não conhecíamos o método, não conhecíamos o projeto e fomos com a cara e a coragem. Discutimos as atividades, estimamos (de forma errada, pois não tínhamos as estórias estimadas e sim as atividades). Erramos nas estimativas das primeiras sprints, mas já começávamos a observar as dificuldades. Na retrospectiva, apontamos as dificuldades, melhoramos o processo e assim seguimos.

Oito sprints depois (sprints e 2 semanas), já trabalhamos como um time muito mais integrado, estamos acertando nas estimativas (usamos os dados históricos), estimamos as estórias e o time está bastante satisfeito com o design da aplicação. Estamos fazendo TDD, Integração contínua, pair programming pois conseguimos nos organizar para tal, e apesar de um “Scrum but”, a coisa vem caminhando muito bem. O que de fato mudou?

Aprendizados

Pessoas

Trabalhar em equipe não é uma coisa fácil. As cerimônias de sprint planning, daily meetings e retrospectivas promovem isso. É praticamente impossível chegar ao fim dessas cerimônias sem interagir. Os medos, dificuldades aparecem e a sujeira sai debaixo do tapete.

Inspeção

O Burndown Chart e o Kanban, são ferramentas fantásticas. Elas vão constantemente mostrando ao time o seu progresso. Como foi o time quem deu as estimativas e se comprometeu com a sprint, o incômodo é generalizado. Enfim, o processo promove uma forma de você visualizar o que realmente está acontecendo, ou seja, se o time irá conseguir atingir a meta ou não.

O Kanban, recomendo que seja físico. Ele exerce uma pressão psicológica violenta quando mostra o real andamento do projeto, além do fato de ajudar a definir o foco, ou seja, estar constantemente mostrando o que é prioritário e o que precisa ser feito.

Após essas sprints, adotei o Kanban como ferramenta de planejamento para outras atividades (não relacionadas a desenvolvimento de software). É muito mais fácil visualizar e ajustar prioridades movendo post-its do que num Excel, além do fato que o Kanban é compartilhado e evita aquele tipo de reunião em que a equipe fica batendo papo enquanto uma das pessoas fica digitando no Excel.

Empowerment

O processo do Scrum ajuda a equipe a obter compromissos que pode cumprir e a dar poder para o time trabalhar. Isso automaticamente faz com que o time busque os recursos para ser mais performático.

Daily Meetings

Os daily meetings são muito importantes. Primeira regra é realizá-los dentro do tempo (15 minutos). Os grandes benefícios do daily meeting pra mim estão no alinhamento e no “pega-lazy”. Quando existe um membro do time que não está jogando para o time, o daily meeting rapidamente mostra isso. A pessoa fica enroscada na atividade e não apresenta o impedimento no daily meeting durante, 3, 4, 5 dias. Geralmente no último dia vem com alguma desculpa do porque não conseguiu realizar a atividade.

Peer pressure

No Scrum, não existem adividades com “donos”. O time é dono das atividades, logo, o time atinge o objetivo ou não. Nesse cenário, começa a ocorrer a pressão entre os pares. No cenário que eu citei acima, do daily meeting, o próprio time começa a se mobilizar para expelir o descomprometido do time. Assim como na existência de um problema, o time começa a buscar os mecanismos para resolvê-lo, pois ninguém quer perder a meta.

Líder facilitador

Observamos que num ambiente ágil não cabe a figura tradicional do chefe. Com o time se auto organizando e entendendo seu papel, o líder passa a ser um facilitador. Ele precisa desenvolver grande habilidade para mediar conflitos, buscar recursos e criar condições para o time trabalhar.

Datas?

É interessante ver como a metodologia tradicional de gestão de projetos criou uma cultura de cravar datas na pedra e exercer cobranças até que a atividade saia no prazo (usando a qualidade para pagar o preço). O Scrum, quando transparece as atividades que precisam ser realizadas, o esforço estimado e a velocidade do time, começa a trazer mais ferramentas que ajudam a visualizar se o objetivo será ou não atingido.

Aquelas situações que visualizamos do gerente perguntar o percentual de conclusão da tarefa, e este percentual ser reportado na progressão: 50%, 75%, 90%, 91%, 92%, 93%, 93.5% perdem o sentido. Como disse anteriormente, o Scrum tira a sujeira debaixo do tapete.

O que começa a ficar evidente é que o responsável pelo projeto precisará de fato aprender a negociar prioridade, escopo ou recursos para a realização do projeto, invés de somente exercer cobranças.

Mudanças de escopo

Mudanças de escopo são bem-vindas. No Scrum, a priorização do backlog simplifica a inclusão de novas estórias e repriorização das mesmas, assim como simplifica a medição dos impactos causados pela mudança. Se você ainda tem uma data alvo, e as mudanças não param de acontecer, o Scrum sem dúvida irá ajudá-lo a mostrar as mudanças e repriorizações e também quando estas impedirão a data alvo de serem atingidas.

Exercício constante de valor agregado

O processo, quando começa a sensibilizar os envolvidos do que está acontecendo (transparência) e mostrar o real custo para se entre

Conclusão

Se você tentou implementar o Scrum em seu time e fracassou, certifique-se se você não entortou o processo. Minha experiência com TDD e com Scrum me mostram isso.

Apesar de ainda estar trabalhando com uma variação de Scrum, é muito interessante observar como o jeitão de trabalhar é muito mais alinhado com trabalho em time, o que nos mostra que a soma dos membros do time é muito maior do que a contribuição individual. Transparência também é um valor fortemente promovido pelo processo.

O processo é feito de uma forma que promove a melhoria contínua, o que me faz acreditar que ainda há muito o que aprender e aprimorar, mas os resultados imediatos são evidentes.

O processo obviamente não ensina as pessoas a desenvolver software. É importante se apoiar em outras disciplinas e processos de engenharia de software (como as práticas de XP) para obter bons resultados. Também não é a bala de prata e vai resolver todos os problemas, mas de uma coisa eu não tenho dúvida: o Scrum cria um ambiente muito mais favorável à resolução de problemas, ao trabalho em equipe e ao desenvolvimento de software de qualidade.

Outra coisa muito importante é que cada vez mais processos ágeis como o Scrum e o Lean estão sendo adotados para desenvolvimento de produtos e não só por empresas de software.

Parece que realmente o Scrum veio para ficar. A discussão ainda de qual processo é melhor, waterfall ou Scrum para gestão de projetos (não somente projeto de software) ainda será muito promovida, e até aqui minha opinião é muitos simples: Projetos com alto grau de certeza terão melhores resultados com waterfall. Projetos com alto grau de incerteza terão melhores resultados com ágil.

Fazendo as pazes com TDD (Test-Driven Development)

Introdução

A primeira vez que eu ouvi falar de TDD foi em 2004. Na época, trabalhava com Delphi ainda. Um colega da minha equipe trouxe o livro do Kent Beck, traduzido em português (acho que era esse: Programação extrema aplicada), sobre XP e estávamos querendo revolucionar como as coisas eram feitas.

Na época, principalmente em Delphi, pouco falava-se de design de software. Orientação a objetos, SOLID era uma coisa muito falada e pouco entendida. Foi um dos meus primeiros projetos que tentei fazer uma separação real de UI da lógica de negócio, criando objetos de domínio.

Foi um tempo muito divertido, e motivado pelas idéias do Beck fiz minha primeira implementação de integração contínua: um arquivo .bat, rodando um script no “want” (uma versão de ant para Windows, bem aderente ao Delphi. Não acho um link sobre isso mais!) no agendador da máquina (Windows) e no cron da máquina (Linux), pois o projeto era multi plataforma.

Outra coisa que aplicamos foram os testes associados ao build usando o DUnit.

A primeira experiência com testes

Neste projeto, conseguíamos testar os objetos de domínio, pois a UI estava totalmente desacoplada dele, porém, por um erro de design, a persistência não era desacoplada da lógica de negócios, o que automaticamente forçava os testes a dependerem de banco.

Usávamos então um setup que criava registros no banco e forçávamos os testes a executarem em ordem para que tudo passasse. Os testes foram muito úteis porque o projeto também era multi-banco e dessa forma, conseguíamos testar se nossa persistência funcionava em todos eles.

Não demorou muito para os testes começarem a ser abandonados, pois era trabalhoso demais criar os testes, eles eram muito lentos pra executar e praticamente todos orientados ao banco de dados (como era o pensamento que imperava na época).

Tive uma experiência negativa do processo.

As experiências posteriores

Dali pra frente (já em .NET), sempre adotei os testes como uma prática opcional. Quando tinha alguma regra de negócio mais complexa ou componentes de infraestrutura sempre criava os testes após o desenvolvimento. Como já tinha alguma experiência, tinha facilidade em visualizar o design up front.

Óbvio que depois os testes sofriam um viés muito forte daquilo que já estava desenvolvido. Ajudava bastante, mas sem saber estava praticando “design done by tests“.

Fazendo as pazes com TDD

TDD-280_largeRecentemente, resolvi prestigiar o trabalho do Maurício Aniche. Ele escreveu o livro Test-Driven Development: Teste e Design no Mundo Real. Confesso que eu comprei o livro porque eu conhecia o Aniche pessoalmente e queria prestigiar o trabalho de um brasileiro. Só não esperava que eu iria me deparar com um livro extremamente bem escrito e com um ponto de vista para mim novo sobre TDD: Os testes influenciam o design.

O livro me ajudou a entender que quando escrevemos os testes antes do código, o teste vai nos forçando a criar um bom design, vai forçando o SOLID a ser aplicado no nosso código.

Isso acontece porque se você está com dificuldade de pensar ou de criar o teste, é porque provavemente suas reponsabilidades não estão bem separadas, ou você não está invertendo as dependências corretamente.

O teste é quem vai te contando isso na prática. O grande problema é aprendermos a dar ouvidos ao que a prática nos diz.

Como funciona isso na prática?

Se eu de fato tivesse aprendido a aplicar o TDD corretamente na minha primeira experiência, teria percebido que se eu estou dependendo do banco de dados pra fazer um teste de regra de negócios, algo está errado. Esse é o tipo do sintoma que tendemos a ignorar por causa do apego que acabamos desenvolvendo ao nosso design.

O mesmo acontece com qualquer dependência externa. Um arquivo, um web service, qualquer coisa desse tipo pode ter suas dependências invertidas para ser corretamente testada. No código do MSBuildCodeMetrics, tive uma situação similar para testar as tasks sem depender do MSBuild.

Testes de integração não são ruins, mas se você não tem unidades, não consegue fazer testes de unidade. Esse é um dos grandes benefícios.

Se eu também tivesse lido um pouco mais e procurado na comunidade informações sobre como aplicar melhor o princípio, descobriria coisas importantes como a atomicidade dos testes. Os testes não podem depender de outros testes, o que tornou a manutenção dos mesmos muito difícil.

Documentação do Design

O TDD também nos ajuda a documentar a nossa “intenção” quando criamos um design. Esse é outro grande benefício. Um exemplo que eu gosto de dar é:


public Cliente localizarClienteComMaiorVolumeDeVendas(IList<Pedido> pedidos){
}

No método acima, qual o comportamento você espera quando nenhum cliente é encontrado (Ex.: lista de pedidos vazia)? Você espera que o método retorne null ou dê um throw numa Exception? Os testes conteriam essa resposta. E melhor ainda, se alguém mudar este comportamento no método, o teste quebrará, o que garantirá a evolução deste design no decorrer do tempo e evitar bugs indesejados.

Produtividade

Produtividade é um critério que sempre gera muita discussão na comunidade de desenvolvimento. Ela aparece em diversas discussões: arrastar componentes invés de criar código manualmente, utilizar ferramentas de migração de código e não podia ser diferente, nos testes. A grande pergunta é se o tempo que os desenvolvedores perdem escrevendo teste paga os benefícios ou não. É bastante intangível isto, apesar de existiram muitas pesquisas discutindo os benefícios, essa discussão aparece.

Após ler o Clean Code e o The Clean Coder, do Uncle Bob, eu me convenci facilmente que qualquer desenvolvedor profissional deveria praticar TDD, assim como me convenci que a grande dificuldade de falar sobre produtividade em software é que confundimos o custo do primeiro release com o custo do software.

Deixa eu tentar explicar melhor: sempre pensamos em produtividade no tempo que o produto demora pra ficar “pronto”, ir para o ar, subir e começar a trazer dinheiro ou resultado. Mas quanto custa evoluir este produto depois?

Sempre que o código apodrece (termo usado pelo Uncle Bob), o custo para mexer em qualquer coisa é exponencial. Começam a surgir bugs nos lugares mais improváveis e cada vez mais tendemos a querer jogar tudo fora e reescrever o software todo. Qual o custo disso?

A forma mais simples de entender essa questão da produtividade vem do gráfico abaixo. É um gráfico de produtividade em relação ao tempo:

Clipboard02

A idéia é que no começo, quando você não carrega nenhum código podre, sua produtividade é 100 e com o decorrer do tempo ela tende a nada. Minha experiência empírica me diz que isso é verdade.

As práticas de XP (TDD, Integração Contínua, Refatoração) são aliados importantes para ajudar o gráfico acima se tornar uma reta e não ter a cara de um logarítmo. Na partida, nos sentimos mais lentos, mas com o decorrer do tempo, a produtividade se torna constante.

Era isso!

MSBuild in a nutshell

Objetivo

Recentemente, quando estava escrevendo os artigos sobre integração, estava novamente me matando para organizar console applications, tratar uma série de parâmetros quando lembrei do MSBuild.

Já trabalhei com ele um bom tempo, mas nunca tirei um tempinho pra escrever sobre ele. Agora aproveitei que ia ter que explicar o meu código do outro post, e resolvi escrever.

Pra que serve o MSBuild?

O MSBuild é uma ferramenta de build (genial!). Serve para escrever scripts de build de aplicativos, encadeando uma série de rotinas referentes a apagar arquivos, realizar build, executar testes unitários, empacotar, gerar instalador, carimbar versão e qualquer outra coisa que se queira fazer.

Eu penso sempre em ferramentas de build como um belo canivete suíço para automatizar um monte coisas repetitivas que fazemos no dia-a-dia de desenvolvimento. Gosto muito da prática de escrever scripts de build, pois sempre pensamos: “já tenho uma solution que combina todos os meus projetos, não preciso disso”, mas na prática nem sempre as aplicações estão escritas numa única tecnologia, ou ainda, nem sempre estão em uma única solution, ou não depende somente de compilação (aqui está o grande erro).

Quando utilizamos uma ferramenta de build e criamos um script para realizar tudo aquilo que garante a qualidade da nossa aplicação associada a um servidor de integração contínua (Ex.: Cruise Control.NET), começamos a descobrir uma série de coisas sobre nosso código e nosso time.

Todas as vezes que implementei essas práticas pelas empresas que passei, descobri que nem todo mundo tinha o mesmo cuidado ao realizar a subida dos fontes para o controle de versão, ou ainda, nem todos executavam os testes unitários antes de subir os fontes. A dupla dinâmica ferramenta de build + servidor de integração contínua ajudam muito a criar essa cultura na equipe.

Nesse post, não vou falar de integração contínua, apenas uma rápida introdução sobre MSBuild que ajuda a dar um start nessa prática.

MSBuild na prática

O MSBuild é uma console application que vem distribuída junto da framework. Sozinha não faz absolutamente nada. No framework 4.0, ela fica no caminho: C:\Windows\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe

A referência completa dos parâmetros de linha de comando do MSBuild, você encontra no MSDN (MSBuild Command Line Reference). Não vou passar um a um aqui. Apenas os principais:

msbuild [ProjectFile] /t:[Targets] /l:[Logger] /p:[Name=Value] 
  • Project File é o xml na estrutura do MSBuild que possui todas a instrução de build
  • Targets é a lista de “Targets” a serem executados. Um target é um conjunto de atividades (tasks). Mais abaixo veremos como definí-los.
  • Logger é a classe utilizada para tratar o log do MSBuild. Veremos algumas opções também.
  • O /p permite a passagem de propriedades, ou seja, pares de nome e valor.

Para demonstrar a estrutura de um arquivo do MSBuild, vamos criar um arquivo MSBuildTests.build. Você pode usar o seu editor de textos favorito para editar o arquivo, geralmente pintando com sintaxe xml para facilitar a vida. Vamos criar com a seguinte estrutura:

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">	
	<Target Name="SaySomething">
		<Message Text="Hello world!" />
	</Target>
</Project>

O xml acima exemplifica a estrutura padrão do MSBuild. A tag “Target” define um target com uma única task Message que indica um texto a ser devolvido no log. Para executarmos isso, vamos criar no mesmo diretório um arquivo runmsbuild.bat, com o seguinte conteúdo:

C:\Windows\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe MSBuildTests.build /t:SaySomething
pause

O batch acima executa o msbuild, referenciando o projeto MSBuildTests.build e o /t: indica que o target a ser executado é o “SaySomething”. Executando o batch, você deve receber o resultado:

C:\Exercicios\MSBuild\build&gt;C:\Windows\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe MSBuildTests.build /t:SaySomething
Microsoft (R) Build Engine Version 4.0.30319.1
[Microsoft .NET Framework, Version 4.0.30319.261]
Copyright (C) Microsoft Corporation 2007. All rights reserved.

Build started 22/04/2012 19:08:21.
Project "C:\Exercicios\MSBuild\build\MSBuildTests.build" on node 1 (SaySomethin
g target(s)).
SaySomething:
  Hello world!
Done Building Project "C:\Exercicios\MSBuild\build\MSBuildTests.build" (SaySome
thing target(s)).


Build succeeded.
    0 Warning(s)
    0 Error(s)

Time Elapsed 00:00:00.03

C:\Exercicios\MSBuild\build&gt;pause
Pressione qualquer tecla para continuar. . .

Isso significa que tudo funcionou. Agora basta montar sua seqüencia de ações para montar o seu build.

Propriedades

Para simplificar a vida em relação a parâmetros, o MSBuild nos permite definir propriedades. Vejamos o exemplo:

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">	
	<PropertyGroup>
		<TextToSay>This is a property</TextToSay>	
	</PropertyGroup>

	<Target Name="SaySomething">
		<Message Text="$(TextToSay)" />
	</Target>
</Project>

Ao executarmos, veremos que $(TextToSay) é substituído pelo valor da propriedade definido no começo do arquivo. Também é possível sobrescrever o valor, passando parâmetros pelo arquivo batch:

C:\Windows\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe MSBuildTests.build /t:SaySomething /p:TextToSay="Novo valor"
pause

Realizando o build de uma solução

Para fazermos algo mais útil com o MSBuild, podemos utilizá-lo num processo padrão de build de uma solution do visual studio. Segue o exemplo:

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">	
	<PropertyGroup>
		<TextToSay>This is a property</TextToSay>	
	</PropertyGroup>
	
	<ItemGroup>
		<Binaries Include="$(MSBuildProjectDirectory)\..\MSBuildTests\**\*.dll" />
	</ItemGroup>

	<Target Name="SaySomething">
		<Message Text="$(TextToSay)" />
	</Target>
	
	<Target Name="Build">
		<Delete Files="@(Binaries)" />
		<MSBuild Projects="$(MSBuildProjectDirectory)\..\MSBuildTests\MSBuildTests.sln" />
	</Target>
</Project>

Aqui tem vários detalhes interessantes. O primeiro é que qualquer solution do Visual Studio é automaticamente reconhecida pelo MSBuild, ou seja, simplesmente executando a Task “MSBuild” numa solution, ela compila. É possível também passar parâmetros, definindo a configuração (Release, Debug) ou outras coisas que a solution permita.

O segundo detalhe interessante é que existem algumas propriedades “padrões” do MSBuild como a $(MSBuildProjectDirectory). No exemplo acima, para encontrar a solution eu uso um path relativo para ela, de forma que independente de onde estejam os arquivos do meu projeto, eles serão encontrados pelo build.

O terceiro detalhe é que eu usei o nome “Build” para a task, que é o mesmo que está no “DefaultTargets” na tag Project. Apenas removendo o /t:SaySomething do arquivo .bat, ela é automaticamente executada, porque foi especificada como default.

Agora um detalhe que sempre gera confusão é o ItemGroup. Neste exemplo, criei um item chamado “Binaries” e a máscara fornecida acima pega qualquer arquivo com extensão .dll em qualquer subdiretório abaixo de MSBuildTests. A idéia é apagar todos os binários antes de compilar (usei apenas como exemplo). Ao chamar a task Delete, todo o conjunto de arquivos encontrados que bate com aquela máscara será excluído.

Outro detalhe importante sobre o “ItemGroup” é que eles são avaliados no momento que começa a execução do projeto. Se você gera arquivos durante o build e quer considerá-los, use a task “CreateItem” para montar os grupos de arquivos.

Criando tasks customizadas

Existe uma série de tasks pré-definidas e sua referência completa pode ser encontrada no link: MSBuild Task Reference. Mesmo assim, é possível construir suas próprias para que você possa fazer suas maluquices.

Para construir uma task personalizada, basta criar uma class library (no meu exemplo, MSBuildTests.Tasks) e criar uma nova classe. É importante criar uma referência para os assemblies Microsoft.Build.Utilities.v4.0 e Microsoft.Build.Framework.

Segue o exemplo de código de uma task:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Build.Utilities;
using Microsoft.Build.Framework;
using System.IO;

namespace MSBuildTests.Tasks
{
    public class GenerateDumbFiles : Task
    {
        [Required]
        public string Directory
        {
            get;
            set;
        }

        [Required]
        public string Prefix
        {
            get;
            set;
        }

        [Required]
        public int Count
        {
            get;
            set;
        }

        public override bool Execute()
        {
            for (int i = 0; i < Count; i++)
            {
                FileStream fs = new FileStream(Directory + "\\" + Prefix + (i+1).ToString() + ".txt", FileMode.Create);
                using (fs)
                {
                    byte[] content = Encoding.UTF8.GetBytes("I'm a dumb file");
                    fs.Write(content, 0, content.Length);
                }
            }
            return true;
        }
    }
}

No exemplo acima, dado um prefixo e uma quantidade de arquivos, a task gera arquivos idiotas. Segue exemplo de como usá-la:

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">	
	<PropertyGroup>
		<TextToSay>This is a property</TextToSay>	
	</PropertyGroup>
	
	<ItemGroup>
		<Binaries Include="$(MSBuildProjectDirectory)\..\MSBuildTests\**\*.dll" />
	</ItemGroup>
	
	<UsingTask TaskName="GenerateDumbFiles" AssemblyFile="$(MSBuildProjectDirectory)\..\MSBuildTests\MSBuildTests.Tasks\bin\Debug\MSBuildTests.Tasks.dll" />

	<Target Name="SaySomething">
		<Message Text="$(TextToSay)" />
	</Target>
	
	<Target Name="Build">
		<Delete Files="@(Binaries)" />
		<MSBuild Projects="$(MSBuildProjectDirectory)\..\MSBuildTests\MSBuildTests.sln" />
		<MakeDir Directories="$(MSBuildProjectDirectory)\..\dumbfiles" />
		<GenerateDumbFiles Directory="$(MSBuildProjectDirectory)\..\dumbfiles" Prefix="DumbFile" Count="100" />
	</Target>
</Project>

O que inserimos de novidade aqui foi a criação do diretório dumbfiles e a tag UsingTask. Esta tag é quem diz para o MSBuild o nome da Task que estamos procurando e qual assembly ele deve carregar. Notem que o assembly é compilado e carregado em tempo de build. A task que está sendo usada dentro do build está sendo compilada em tempo de build.

A tag GenerateDumbFiles simplesmente executa o código da task que criamos, respeitando os parâmetros “Required”. Se não especificarmos nenhum, dá erro na execução da task, assim como se o assembly não for localizado, ou internamente dentro do assembly o nome da classe não bater com o TaskName especificado.

Logger

O MSBuild permite também que você “espete” classes de log específicas. É comum que com o tempo os builds fiquem bastante grandes e pra entender o que aconteceu dá um certo trabalho. Debuggar com as cores é bem mais legal e o logger default não suporta.

Aí você procura na internet e acha um cara legal que fez um logger em xml, como este: http://geekswithblogs.net/kobush/archive/2006/01/14/xmllogger.aspx. Você baixa o fonte dele, compila e pega a classe de logger.

No batch de execução do MSBuild, você coloca o seguinte parâmetro:

C:\Windows\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe MSBuildTests.build /p:TextToSay=”Novo valor” /l:XmlLogger,Kobush.Build.dll;msbuild-output.xml
pause

Isso indica que ele carregará a classe do Kobush de log, e o output será no arquivo msbuild-output.xml. Se executar, você verá o resultado. Ainda assim não estando satisfeito, você pode brincar mais ainda com o MSBuild, realizando uma transformação de xml para um formato mais legal.

Agora adicionamos também no nosso xml, um target:

<Target Name="TransformLog">
		<XslTransformation XmlInputPaths="$(MSBuildProjectDirectory)\msbuild-output.xml" XslInputPath="$(MSBuildProjectDirectory)\msbuild.xsl" OutputPaths="$(MSBuildProjectDirectory)\log.html" />
	</Target>

E alteramos nosso .bat para também executar este target:

C:\Windows\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe MSBuildTests.build /p:TextToSay="Novo valor" /l:XmlLogger,Kobush.Build.dll;msbuild-output.xml
C:\Windows\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe MSBuildTests.build /t:TransformLog
pause

O resultado final é um arquivo “log.html” com uma transformação do log num formato “bonitinho” para debug.

É claro que é possível também implementar seus próprios loggers. Mas não pretendo abordar isso neste post.

Código fonte

O código fonte está disponível no git hub: https://github.com/ericlemes/MSBuildTests

Conclusão

O MSBuild é uma poderosa ferramenta para nos ajudar a orquestrar diversas tarefas de automação de build. Toda a complicação de encontrar caminhos relativos, administrar parâmetros de execuções de pequenos aplicativos ou console applications é praticamente eliminado usando o MSBuild.

A própria prática de ter um “roteiro” para empacotar uma aplicação já adiciona muito valor ao processo de desenvolvimento, pois permite que cada rotina, biblioteca ou atividades realizadas para construir a aplicação esteja documentada e seja mantida junto com o build.

A Arquitetura Perfeita

O arquiteto de software

Recentemente venho acompanhando o aumento da procura pelo “Arquiteto de software”, principalmente em plataforma .Net. Há 5 anos atrás parecia que o mercado tinha uma séria dificuldade em entender o que faz um arquiteto. De repente, parece que ele está virando a bola da vez.

Um dos sintomas desta procura são artigos como este: Best Jobs in America 2010.

Parece que de uns tempos pra cá após inúmeros projetos que precisam ser completamente reescritos porque as decisões de projeto e/ou falta de processos os levaram ao caos, o mercado vem procurando profissionais que conseguem corrigir, minimizar ou mesmo prever e evitar tais catástrofes. Talvez esta seja a principal razão pela busca de profissionais.

Mas afinal, o que faz um arquiteto de software?

Essa pergunta tem várias respostas e desconheço uma definição muito clara sobre o papel. Tem aquela clássica analogia com construção civil, ou seja, da mesma forma que na construção civil o arquiteto é quem planeja e projeta a construção, o arquiteto de software é quem faz as plantas e toma as decisões sobre como o software deve ser construido.

Na prática, eu gosto muito da definição dada no livro Microsoft .NET – Architecting Applications for the Enterprise: Arquiteto é o responsável por tomar as decisões de tudo aquilo que é muito difícil de mudar no software.

Faz bastante sentido.

Software como negócio

Querendo ou não, cada vez mais vemos o software não sendo vendido como produto final. No início o modelo de negócio era muito simples. O software era desenvolvido, a licença de uso era vendida. Negócio perfeito. Ganho por venda e meu estoque é infinito.

Os tempos foram mudando. Hoje em dia é praticamente impossível vender uma licença de uso de um software. Tem praticamente tudo de graça. Sistema operacional, web server, instant messaging, suítes do tipo “office”. Acho que a única empresa que ainda ganha com este modelo é a Microsoft. E ela vem tentando novos modelos.

De resto, vemos empresas que utilizam-se do software para vender publicidade (Google e grande parte da Web), dependem de tecnologia para reduzir custos operacionais (bancos, manufatura), venda de mão de obra (ERP’s) e consultoria. Existem muito mais integradores do que criadores de software.

Cada vez mais os modelos apontam para cobrar pelo uso do software, por transação trafegada pelo sistema, pelo serviço fornecido pelo software. Cada vez menos licenças de uso, cada vez mais cloud computing ou software as a service – SaaS.

Seguindo essa linha de raciocínio, cada vez mais o software é uma atividade que gera outros negócios ou apóia outros negócios. Muito pouco se vê sobre vender software como atividade final.

A arquitetura perfeita

As vezes conversando nos forums, com colegas de profissão eu percebo que como profissionais técnicos, vejo muitos arquitetos estão sempre buscando a solução de software perfeita. Aquele único modelo de arquitetura que atende todos os casos, é perfeito e impecável. A solução tamanho único. A excelência técnica.

Essa corrente de pensamento é bastante contrária ao cenário da evolução dos modelos de negócio apoiados em software, que é bem mais complexa e envolvem diversos outros fatores. Para alegria de alguns e desespero de outros, cada vez mais a tecnologia existe para suportar outros modelos de negócio. E dentro dessa ótica, não é somente a excelência técnica que vai fazer do software um produto de sucesso (apesar dela ser extremamente importante).

É só lembrarmos de tantos exemplos que tivemos na história, o maior de todos talvez seja o próprio Windows, que mesmo com suas inúmeras telas azuis em suas versões 95 e 98 tornou-se o sistema operacional mais popular, mesmo existindo diversas alternativas comerciais e gratuitas. Quando essas alternativas tentaram estabelecer-se no mercado, o Windows já o tinha dominado completamente.

O diferencial

Se somente o conhecimento técnico não é suficiente, quais são os outros atributos?

Muitas das decisões técnicas dos projetos não são somente decisões técnicas. Envolvem fornecedores, custos, aquisições, propriedade intelectual e tantas outras complicações que somente uma área tão complexa, dinâmica e com tantos conhecimentos específicos e distintos pode nos proporcionar.

Muitas dessas decisões são extremamente complexas para um executivo que não tenha tido vivência em posições técnicas no passado, ou mesmo não conseguiu acompanhá-la no nível de detalhe necessário. A comunicação necessária para ponderar riscos, custos e qualidade depende de um profissional que saiba trafegar muito bem na fronteira entre pensamento estratégico e conhecimento técnico. O arquiteto de software tem sido um grande colaborador nesta lacuna.

Além de suas habilidades técnicas, pode contribuir com muitos pontos durante uma reflexão estratégica para conceber um novo produto ou negócio:

  • Time to market: O arquiteto pode ajudar a estabelcer a melhor qualidade possível do produto final garantindo que o mesmo esteja disponível a tempo de ser competitivo no mercado.
  • Dependência de fornecedores: O arquiteto pode ajudar a avaliar se os componentes e tecnologias de terceiro estão no nível de maturidade necessário, ou se existe tendência de continuidade, bem como avaliar se os serviços contratados de terceiros possuem os padrões de qualidade necessários.
  • Capacidade de evolução: O arquiteto pode ajudar a organizar o desenvolvimento de forma a prepará-lo para evolução sustentável.
  • Experiência da equipe: O arquiteto pode ajudar a aproveitar as melhores qualidades ou contornar deficiências das equipes de desenvolvimento e produção, estabelecendo padrões e tecnologias condizentes com a experiência do time. Deve levar em consideração também o momento do mercado de profissionais, visto que atualmente fala-se muito no “apagão de profissionais”.

Essa lista é extremamente extensa e não-exaustiva.

Tendo todos estes fatores em mente, chego a conclusão que é muito difícil estabelcer uma arquitetura perfeita.

A começar pela idéia de que se perguntarmos para 10 pessoas diferentes qual é a arquitetura perfeita, provavelmente teremos 10 opiniões diferentes, levando em consideração somente o fator excelência técnica.

Aqui está o principal diferencial do bom arquiteto: saber ouvir os principais stakeholders do projeto, compreender suas necessidades, ser colaborador atuante no processo de reflexão estratégica e conseguir levar estas decisões para o time técnico na linguagem apropriada e no nível de detalhe apropriado.

O primeiro passo para estabelecer uma arquitetura bem-sucedida é conseguir visualizar todos estes atributos e traçar os objetivos desejados, levando em consideração o momento da empresa, do mercado, da disponibilidade de mão de obra, dos fornecedores e da tecnologia em questão. Somente tendo este ponto de partida, é possível escolher os padrões e tecnologias que resultem numa solução equilibrada e num produto de sucesso.

The Joel Test

Um amigo postou internamente aqui o link para o “The Joel Test”, do Joel Spolsky. Eu realmente não conheço a fundo o trabalho dele, mas achei muito boa a métrica para saber a maturidade da equipe de desenvolvimento em 12 passos.

São eles:

  • Você usa controle de versão?
  • Você consegue fazer um build em uma etapa?
  • Você faz builds diários?
  • Você tem um banco de dados de bugs?
  • Você corrige os bugs antes de escrever código novo?
  • Você tem uma agenda atualizada?
  • Você tem uma especificação?
  • Os programadores possuem condições silenciosas de trabalho?
  • Você tem as melhores ferramentas que o dinheiro pode comprar?
  • Você tem testers?
  • Seus candidatos escrevem código em suas entrevistas?
  • Você faz teste de usabilidade de corredor?

Achei fantástico pela simplicidade. Doze etapas e resume tudo.

O original está em http://www.joelonsoftware.com/articles/fog0000000043.html