Um cupinzeiro demonstra emergência

Nos lugares onde os aspectos arquiteturais são levadas a sério como imprecindíveis para o sucesso de qualquer projeto é cada vez mais consenso de que a maneira tradicional de arquitetar sistemas não está provendo todo o valor que deveria.

Por maneira tradicional entenda:

  • Um arquiteto ou um time deles planeja a arquitetura de um sistema, mas não atua desenvolvendo ou não está ao lado dos desenvolvedores full-time.
  • A arquitetura de um sistema é planejada totalmente no começo do desenvolvimento, com definições sobre diversos aspectos da aplicação, como as camadas físicas e lógicas, a forma de acesso a dados, e as tecnologias em geral.
  • Uma mistura dos dois também é muito comum.

É comum também a criação de documentos que pré-restringem as opções de tecnologias, padrões, metodologias, etc, muitas vezes feitos pelos próprios arquitetos. Tais restrições se justificariam em nome da padronização, e raramente levam em conta cenários. Um exemplo é: “aplicações devem utilizar o Entity Framework para acessar dados” ou “ASP.Net Webforms sempre deve ser usado quando o desenvolvimento for web”.

Ainda é assim que a maioria dos times de arquitetura trabalha. Temos obtido ganhos? Sem dúvida! Pensar na arquitetura é melhor do que não pensar. Mas quais os problemas?

Alguns dos problemas são código jogado fora, código criado e nunca utilizado (inútil), código que não faz o que indica (enganando o desenvolvedor), soluções com alta fricção, que congelam o código e/ou a criatividade do desenvolvedor, entre diversos outros (comente sua lista de problemas lá embaixo).

Viva a padronização, matando a produtividade. O interessante é que o maior argumento para a padronização é justamente a produtividade. Será que é possível ser produtivo sem padrões? Será que é possível ter padrões e ainda assim permitir a criatividade? Vamos ver.

Já tem quase 10 anos que umas pessoas declararam que responder a mudanças é mais importante do que seguir um plano, e que indivíduos e interações são mais importantes do que processos e ferramentas. Isso significa que podemos ter um plano, mas devemos mudá-lo sempre que as premissas sobre as quais eles se fundaram mudarem, ou quando eles não fizerem mais sentido. E que podemos ter ferramentas, processos, e padrões, mas que as interações entre as pessoas, e o que sai delas são mais importantes. Interessante, não? Parece que aplica ao que estamos discutindo.

De lá pra cá esses valores, além de mais alguns, tomaram o mundo. Chegou a hora de falarmos não só sobre o que é uma boa arquitetura, mas também como chegar lá. O processo tradicional, baseado em algumas pessoas determinando como outras vão trabalhar, e em documentos antigos e não focados no projeto, não promovem a interação entre o time que realmente cria os detalhes de um software (e é nos detalhes que está o perigo). Como eles não interagem entre eles, com o negócio e com TI, a solução arquitetural proposta pelos arquitetos (externos ao time) é a solução aceita e aplicada. Uma solução concebida desta forma é linear. As variáveis são analizadas, um catálogo é avaliado, as melhores soluções são propostas, comparadas com outras candidatas, e uma é escolhida. Parece bastante linear, não parece? Sabe qual o problema de ser linear?

O problema é que uma solução linear não reflete as necessidades do negócio, a criatividade do time, os problemas da empresa, o ambiente (físico e humano) onde o software vai rodar, as regras e regulamanentos, e outras influências não lineares que moldam um software além do momento em que foram concebidas. São, por definição, míopes. Todos essas características juntas formam um sistema complexo, e quando interagem começam a criar resultados não lineares. Eles começam a emergir. As necessidades e as soluções que emergem são tão profundamente ricas que nenhum time de arquitetos, por melhor que seja, conseguiria alcançar sozinho, por que estão presos a sua linearidade.

O risco em usar uma solução linear, que presume um comportamento previsível, em um sistema complexo, é que as previsões não vão se confirmar. Em arquitetura isso vai gerar os problemas que já conhecemos. O mais interessante é que, como o sistema é assumido como linear, muitas das variáveis não são sequer analisadas (ou até conhecidas), porque só aparecem muito mais tarde. E como influenciam o resultado de forma não prevista, o desenvolvimento do software começa a parecer ser caótico, aleatório, absolutamente imprevisível. E ele não é imprevisível, só não é previsível além de um período muito curto.

Como resolver esse problema? Pra começar devemos aceitar o fato de que desenvolver software é um sistema complexo, e isso inclui sua arquitetura. Por isso teorias que pregam previsibilidade podem ser abandonadas, já que somos incapazes de prever o estado em que o desenvolvimento do sistema estará em um curto período de tempo, geralmente alguns meses.

Em seguida precisamos saber lidar com um sistema complexo. Uma excelente maneira, é a utilização de um modelo de controle de processo que seja empírico. O Scrum é um deles. O Scrum diz que trabalha com um processo iterativo e incremental, e se baseia em 3 pilares. Segundo o Scrum Guide (em português e gratuito):

    • O primeiro pilar é a transparência
      A transparência garante que aspectos do processo que afetam o resultado devem ser visíveis para aqueles que gerenciam os resultados. (…)
    • O segundo pilar é a inspeção
      Os diversos aspectos do processo devem ser inspecionados com uma frequência suficiente para que variações inaceitáveis no processo possam ser detectadas. (…)
    • O terceiro pilar é a adaptação
      Se (…) um ou mais aspectos do processo estão fora dos limites aceitáveis e o produto resultante será inaceitável, ele deverá ajustar o processo ou o material sendo processado. Esse ajuste deve ser feito o mais rápido possível para minimizar desvios posteriores.

O Scrum também diz que um pedaço de funcionalidade deve ser entregue a cada iteração, e que só o time pode tocar e influenciar o código. O time é seu próprio gerente, e é auto-organizado.

E como surge a arquitetura? Assim como todo o resto, ela emerge. Ela é desenvolvida incrementalmente a cada iteração, conforme é necessária. É claro para o time que alguma funcionalidade deve ser entregue, e as entregas funcionais são mais importantes que as não funcionais, como as arquiteturais.

Também é comum que, dentro de uma iteração, um time Scrum faça uma rápida prova de conceito e avalie arquiteturas candidatas. Muitas vezes, também durante uma iteração (geralmente nas primeiras), o time desenvolve uma visão geral da arquitetura do sistema, mas sempre lembrando que o foco é atender o cliente e maximizar a entrega de forma sustentável.

Quando um time se preocupa com arquitetura ele está claramente preocupando com o custo total de propriedade (TCO), além do seu próprio prazer em codificar, e o desenvolvimento iterativo e incremental, que habilita uma arquitetura emergente, facilita o alcance destes objetivos.

Concluo resumindo alguns pontos chave. Para habilitar uma arquitetura emergente o processo de desenvolvimento precisa:

  • ser decentralizado;
  • possuir um time auto-organizado;
  • ser transparente;
  • promover inspeção e adaptação constantes;
  • ser evolutivo;
  • promover a presença da língua do negócio;

Uma arquitetura bem feita serve ao time, não é o time que trabalha para satisfazê-la. Isso se reflete no TCO, na felicidade do time e no sucesso do projeto.

Pra saber mais:

  1. eu já havia falado rapidamente sobre isso quando mencionei a criação de frameworks corporativos;
  2. o assunto também faz parte do curso de Professional Scrum Developer;
  3. este post do Brad Appleton traz diversos links sobre o assunto;
  4. o Fábio Akita falou bastante sobre sistemas complexos e agilidade no RailsSummit do ano passado.

Bom estudo e divirta-se. O assunto é muito interessante.