segunda-feira, 17 de março de 2014

Métodos ágeis, arquitetura lerda

Hoje em dia, as técnicas chamadas de "Métodos ágeis" dominam completamente as áreas de desenvolvimento de software. Coisas como: Scrum, Kanban, XP e Planning poker, "pululam" as discussões sobre o assunto, com defensores cada vez mais estóicos. Porém, as equipes continuam utilizando as mesmas técnicas "mastodônticas", baseadas no "ecossistema" corporativo Java, que trazem uma enorme Complexidade Acidental embutida. Isto acaba criando conflitos e soluções ruins, pois, devido ao seu peso desproporcional, as arquiteturas "inchadas", baseadas nesse "ecossistema", acabam "guiando" a solução, o que, geralmente, força o projeto a entrar no ritmo de "tudo ou nada", quando os "Sprints" se tornam muito curtos para serem atendidos com qualidade. É necessário repensar a maneira como construímos aplicações, usando uma arquitetura mais diluída, se quisermos realmente sermos ágeis.




"Soluções que você não precisa, para problemas que você não tem"

Para mim, esta é a definição do "ecossistema" corporativo Java. Quando você resolve entrar de cabeça em uma "arquitetura corporativa" Java, usando: Container Java EE, JPA, JSF, XML e Soap, não tem mais saída. Você acaba se enrolando tanto no "emaranhado" de frameworks, que acaba padecendo da "Síndrome do Comprometimento":
Quando investimos muito tempo e esforço em determinada solução, podemos nos comprometer com ela de tal forma, que seu emprego passa a ser o nosso objetivo, ao invés de resolver o problema.
Aliás, existe um ditado de Robert Antony que descreve bem esse tipo de síndrome:
If you find a good solution and become attached to it, the solution may become your next problem.
Traduzindo: "Se você encontra uma boa solução, e se torna apegado a ela, então, a solução poderá se tornar seu próximo problema".

É o que acontece com os desenvolvedores corporativos Java. Outro dia, estava discutindo um novo projeto, com um colega de trabalho, e tudo o que ouvi foram marcas e nomes de frameworks. Eu ainda tentei (não sei por que insisto) argumentar, dizendo que outras soluções seriam possíveis, e que ele não deveria se "apegar" a um conjunto de soluções muito cedo, mas foi em vão. 

O "ecossistema" corporativo Java foi criado exatamente com essa intenção: Abstrair os problemas, envolver as pessoas e garantir a continuidade da Plataforma. É a mesma ideia de Dom Corleone, no filme The Godfather: "Vou fazer uma oferta, que ele não poderá recusar". Em troca de um monte de "alegadas" facilidades, você vende sua alma para a Plataforma. 

Métodos ágeis

A maioria das técnicas ágeis, especialmente as relacionadas com processo de desenvolvimento de software, como o Scrum e, mais recentemente, o Processo Kanban, se propõem a gerenciar equipes altamente coesas, com a menor burocracia possível, de modo a aumentar a quantidade e frequência de "entregas" de software pronto, o que diminui o risco (para o Cliente e para a Equipe) e ajuda a melhorar a satisfação geral. 

Ou seja, se você está usando um processo de desenvolvimento baseado em técnicas ágeis, então são esperados ciclos curtos de desenvolvimento, com várias entregas parciais. Isto exige um trabalho sobre os requisitos, de modo a dividi-los em pequenos pedaços, implementáveis em um tempo relativamente curto, e que gerem produtos realmente utilizáveis para o Cliente. Isso sim, ajuda a diminuir o risco. 

Os processos ágeis são iterativos, baseados em entregas incrementais, o que exige uma disciplina de trabalho conjunto jamais possível em outros tipos de processo. A ideia é sair do "domínio do problema" para o "domínio da solução" no menor espaço de tempo, criando "Sprints" pequenos e de baixo risco. Há pouco tempo para modelagem arquitetural e modelagem de projeto, forçando com que os desenvolvedores comecem logo a trabalhar no código fonte. 

Várias técnicas, como "Scrum" e "Planning Poker" estimulam a criação de ciclos curtos de desenvolvimento, No Scrum, por exemplo, um "Sprint" (uma rodada de desenvolvimento) deve durar algo entre 1 semana e 1 mês. Não é comum "Sprints" com três meses de duração, por que aí já é "Desenvolvimento em Cascata". No Planning Poker, as cartas são oferecidas em sequências (Fibonacci, por exemplo), e os números podem representar várias coisas, mas sempre tem um "infinito" ou uma interrogação, significando que a "história de usuário" é muito grande e deveria ser refatorada para posterior avaliação. 

Além do mais, as mudanças nos requisitos são bem vindas, e, geralmente, acontecem entre um "Sprint" e outro. Ou seja, é comum você criar em um "Sprint" e modificar em outro, e isto não deve ser visto como um problema. Afinal, em uma época tão febril como a nossa (tecnologicamente falando), a competitividade pode forçar as empresas a mudarem suas estratégias constantemente. A ideia por trás da adoção de métodos ágeis é exatamente essa: Diminuir o risco para as Empresas, através de entregas mais frequentes. 

É claro que não podemos esperar que todo "Sprint" gere algo de útil para o Cliente. Haverá casos em que mais de um "Sprint" é necessário ANTES de fazer uma entrega. Porém, não é fácil convencer o Cliente a esperar e pagar por 3 "Sprints" antes de ter algo entregue. Ele não aceitará, afinal de contas, nós lhe vendemos que usamos "Métodos ágeis", então, que agilidade é essa?

Em resumo, podemos dizer sobre as entregas:
  • Devem ser frequentes;
  • Seu produto deve ser útil;
  • Pode haver mudanças de requisitos entre as várias entregas;
  • Os vários produtos devem ser fáceis de integrar, mesmo com mudanças nos requisitos.
E aí, eu lhe pergunto: Isso é possível quando usamos o "ecossistema" corporativo Java?

Alma de papel higiênico

Você sabe o que é uma "alma" de rolo de papel higiênico? É aquele canudo duro, de papelão, que vem dentro dos rolos de papel higiênico, de modo a mantê-los na mesma forma, possibilitando que os rodemos em um suporte, o que facilita cortar as tiras em tamanhos apropriados. Sem a "alma", o rolo seria disforme e não rolaria facilmente, dificultando o uso em um momento especialmente crítico de nossas vidas. 

Bem, imagine que você encomendou 5.000 rolos de papel higiênico, a um fornecedor que usa "métodos ágeis". Então, no dia seguinte ele te entrega 5.000 "almas" de papelão, e diz que os rolos virão no próximo "Sprint". O que você faz com 5.000 canudos de papelão? É uma entrega inútil, certo? Mas o Fornecedor precisa faturar alguma coisa... E ainda tem o tempo para encaixar as "almas" nos rolos, porém o Fornecedor diz que será um "Sprint" bem rápido. Então, serão 3 "Sprints": Um com as "almas", outro com os rolos e um terceiro, para encaixar as "almas" nos rolos. 

Então, enquanto espera para ter os rolos, você descobre que o dono da quitanda ao lado, seu concorrente, comprou um papel higiênico Chinês, que custa metade do preço e que, ainda por cima, é mais macio do que o seu. Logo, os fregueses vão preferir comprar no seu concorrente, certo? Então, você liga para o Fornecedor e diz que quer rolos tão macios como os que o seu Concorrente comprou.

O Fornecedor muda um pouco as especificações, afinal, segue "métodos ágeis", e cria rolos mais macios. Só tem um problema: Eles não cabem mais nas 5.000 "almas" que foram entregues anteriormente... Então, para manter a solução (síndrome do comprometimento), ele propõe abrir os canudos das "almas", de modo a ajustar seu diâmetro. O canudo vai ficar aberto, mas vai encaixar até mais facilmente nos novos rolos de papel extra-macio. 

Todos ficam felizes, pois o prazo dos "Sprints" foi cumprido. Só que, como os rolos são extra-macios, e a "alma" é um canudo aberto, eles ficaram muito moles, e acabaram deformando no suporte, o que dificulta muito o uso. Quando vão puxar o papel, os Fregueses acabam rasgando as folhas em pedaços minúsculos, que não servem ao propósito. Então, você acaba com 5.000 fregueses furiosos, devolvendo os rolos de papel higiênico.

Usar arquiteturas pesadas é como entregar as "almas" antes dos rolos

Arquiteturas pesadas e inchadas, baseadas no Framework Java EE, ou em outros frameworks corporativos Java, não se prestam bem à divisão em entregas curtas, que é a base dos processos ágeis. Acabam comprometendo todas as vantagens do uso de métodos ágeis. 

Por exemplo, você já fez um mapeamento O/R com JPA e Hibernate? Certamente, o resultado fica lindo, não? Mas, isso é rápido de fazer? Não requer uma modelagem? Fazer um mapeamento sem a correta modelagem, é criar um baita problema para construir o código. E, como se trata de método ágil, o Cliente espera uma entrega útil. Então, eu lhe pergunto: Para que serve um belo mapeamento O/R, com classes JPA? O que o Cliente faz com isso? 

E tem mais! Não podemos supor que os requisitos ficarão imutáveis, pois tudo pode mudar entre uma entrega e outra. Então, teremos que pegar aquele belo mapeamento JPA e mudar tudo, ou então "acochambrar" para fazer funcionar, da mesma forma que o Fornecedor de papel higiênico fez, ao abrir as "almas".

Mas não é só com o JPA! E o JSF? Cara, eu fiz um sistema há uns dois anos. Usei o que havia de mais moderno na época: JSF 1.2 e usei a biblioteca Apache MyFaces. Agora, temos o JSF 2.0, e tudo mudou! O Facelets não é mais algo estanque, estando incorporado ao JSF. Tentei estimar o tempo para migração da solução, e desisti. 

Na minha humilde opinião, o JSF é mais um problema do que uma solução! A maioria dos Web Designers não o conhece, logo, precisamos pegar as páginas XHTML e rechear com "tags JSF" e expressões baseadas em EL, tornando-as praticamente irreconhecíveis! E se houver uma alteração nos requisitos, para a qual seja necessária mudar o layout e o visual das páginas? Todo o trabalho de "rechear o perú" que tivemos, será jogado fora... Você conseguirá convencer o Cliente a pagar por esse tempo novamente? E se, ao testarmos, houver alguma incompatibilidade com um ou mais navegadores Web? Eu já passei muitas vezes por esse problema...

E não são só os requisitos funcionais que podem mudar. Os requisitos não funcionais também, o que inclui a plataforma! Você acha que os Clientes não ouviram falar de HTML 5? Acha mesmo que eles vão ignorar a versão "mobile"? E o que vai fazer, quando descobrir que seus componentes JSF são incompatíveis com HTML 5? É claro que é possível adaptar e improvisar, mas isso é coisa para os "Marines" e não para desenvolvedores de software!

E a dupla maldita: XML e Soap? Essa maldição vem substituindo os tradicionais EJBs nas aplicações Java EE, sendo adotados em várias camadas. Porém, a criação de um Webservice Soap / XML em Java é algo, no mínimo, traumático. Especialmente se forem disponibilizados via Internet, para "Consumers" de várias plataformas. 

Todos esses componentes são pesados e representam um alto "Acoplamento de plataforma": 
É o que acontece quando o uso de determinadas soluções, nos induz a usar determinada linguagem, plataforma e outras soluções associadas. 
Nos métodos ágeis, quando passamos ao "domínio da solução", não temos muito tempo para ficar modelando coisas. É esperado que comecemos logo a programar, de modo a atender ao ciclo de entregas rápidas. O Cliente não vai ficar esperando 3 ou 4 "Sprints" até ter algo realmente utilizável, e, fracionar artificialmente as entregas poderá gerar a "Síndrome das almas de papel higiênico". Logo, usar arquiteturas e frameworks corporativos tradicionais é a melhor receita para o fracasso do seu projeto.

Arquiteturas diluídas são mais ágeis

Quando criamos uma arquitetura de software diluída, nós dividimos melhor as responsabilidades pelos vários elementos componentes, reduzindo o risco, o prazo e o custo do desenvolvimento. Eu já demonstrei isso na série de artigos sobre o assunto, quando mostrei uma aplicação moderna (microblog) totalmente feita de forma diluída e desacoplada. 

Precisamos diminuir o tempo de entrega, permanecendo o mínimo possível no estudo do "domínio da solução". Para isto, necessitamos de novas tecnologias, que sejam mais simples de usar, e, ao mesmo tempo, mais descartáveis. Assim, evitamos a "Síndrome do comprometimento". Por exemplo, no "microblog" eu usei um RESTful webservice Java, com JAX-RS e JSON, rodando com um Container Jetty embutido. Porém, a solução é tão simples, que posso converter o código em Javascript e usar Node.js, caso seja melhor. Ou posso substituir toda a camada de apresentação por uma aplicação Rails, ou, ainda mais: Posso substituir a minha camada de persitência por Javascript rodando dentro do próprio MongoDB. Há uma infinita maneira de substituir os componentes da minha arquitetura, sem correr o risco de usar "almas cortadas"!

Conclusão

Se você quer usar "métodos ágeis", criando um processo de desenvolvimento "lean", tem que aderir ao que ele se propõe, caso contrário, será apenas uma figura patética, tentando parecer "moderninho", enquanto segue um processo de desenvolvimento caótico. 

É preciso diminuir a passagem do "domínio do problema" para o "domínio da solução", além de poder fatorar sua solução, sem fracioná-la, atendendo a um cronograma de entregas rápidas e coerentes, e que seja flexível o suficiente para acomodar as constantes mudanças, exigidas pela competitividade dos tempos modernos. 

De que adianta usar um baita framework corporativo, cujo objetivo parece ser apenas o de perpetuar o uso de determinadas soluções? Essa porcaria vai acabar comprometendo todo o seu lindo Kanban, fazendo você e equipe passarem por "caozeiros".