Arquitetura emergente

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.

  • Luciano

    Bastante interessante o texto, mas podemos refatorar a lista de pontos chave. O resultado é SCRUM (cinco primeiros itens) + DDD (último item). :D

  • http://lpalma.com/ Luciano Palma

    Ótima avaliação, Giovanni!
    O problema, no entanto, parece estar sempre na mesma variável: PESSOAS.
    Mais do que a questão de preparo (endereçável com treinamento), creio que o maior problema pode ser POSTURA. Para que o modelo funcione, é necessário:
    1. Gente que jogue realmente em time. O individualismo vem imperando há algum tempo, ainda mais num ambiente de egos grandes como a comunidade de desenvolvedores.
    2. Um gerenciamento que jogue realmente em time. Além de gerentes mais preocupados em suas promoções, é comum ver modelos de "incentivo" que ampliam ainda mais o individualismo do item 1 (com competitividade interna exagerada)
    3. Profissionalismo nos relacionamentos. O fim do "finge que paga / finge que entrega"
    4. Transparência e ética.
    Provavelmente haverá mais itens nessa lista… mas sem eles, não há metodologia que aguente!
    De qualquer forma, você está fazendo sua parte, e muito bem! ;)
    Grande abraço,
    Luciano

  • Luciano

    Pois é Luciano Palma, eu também costumo comentar isso entre meus colegas de trabalho. A variável mais crítica nesse sistema chama-se PESSOAS. Eu acho que esta é a parte mais sensível dos métodos ágeis. Alto acoplamento com essa variável. Infelizmente, não podemos implementar Inversão de Controle neste caso :D.

    Abraços,

  • Thiago Kuma

    Giovanni, muito interessante o tema. É engraçado como o tema Padrão é tratado, pois ele vem da recorrência. Quer mais recorrência do que mudanças no momento do desenvolvimento? Por isso acho que um modelo de controle empírico como Scrum deve ser considerado. As premissas devem ser mudadas quando não fazem mais sentido… esse valor é primordial.
    Muitas vezes a equipe nem sabe quais são as premissas a seguir, quanto mais avaliar se estão erradas. Onde foi parar a comunicação nesse caso?
    Minha briga de momento, mudanças não são fáceis de estimar… nem ao certo quais delas eu terei de fazer (ou em alguns casos fingir que não preciso), mas para isso preciso de uma equipe comprometida em colaborativamente propor/realizá-las e não somente criar e corrigir features por que isso reflete nos indicadores de produtividade
    Podemos fazer algo muito rápido, mas mantenha em mente que caso não esteja adaptável a próxima atividade cobrará o ônus e assim prossegue até que é mais fácil recomeçar do que manter. Para isso não somente a inspeção é importante, mas também a qualidade da inspeção.
    Abraços
    Thiago Kuma

  • http://unplugged.giggio.net/ Giovanni Bassi

    Palma, é parcialmente verdade. Há comportamentos que envolvem pessoas que não apresentam emergência. Toda vez que discutimos média aplicada a pessoas estamos tratando de um sistema simples. Pode até ser que seja uma visão simplista de um sistema complexo, mas se pode ser reduzida, é assim que trataremos ela até que seja necessário mudar.

    Thiago, comprometimento é fundamental. Por isso tenho estudado (e publicado por aqui) sobre motivação.

    Luty, mais ou menos. Não seja tão reducionista assim. A conclusão não contém as premissas ou o desenvolvimento. Ela é só a conclusão. O problema de ficar só na conclusão é não entendê-la e praticá-la errado. Está acontecendo muito com o Scrum atualmente.

  • http://blog.tucaz.net/ tucaz

    Giovanni,

    acho que estamos confundindo algumas coisas importantes aqui. Emergencia e auto-organizaçao são fundamentais. Isso é fato. No entanto isso não muda o também fato de que uma fatia importante da arquitetura é feita up-front em projetos de software.

    Usar Scrum não significa que eu vou escolher DI só na hora que precisar ou que vou implementar um pipelina WCF só na hora que for usa-lo.

    Nem tanto ao céu, nem tanto a terra.

  • http://unplugged.giggio.net/ Giovanni Bassi

    Oi Tuca,
    Eu disse:
    "Muitas vezes, também durante uma iteração (geralmente nas primeiras), o time desenvolve uma visão geral da arquitetura do sistema".
    O uso de WCF ou DI, como você citou, é decidido desta forma.
    A ideia é adiar a decisão até o last responsible moment.
    Qualquer outra coisa é cair no BDUF e no scrummerfall, IMO.

  • http://blog.tucaz.net/ tucaz

    Ah sim, mas é o que geralmente os devs sensatos fazem. Nenhuma big revolution até ai.

    Acho só importante deixar isso claro porque daqui a pouco desculpa do pessoal vai deixar tudo pra ultima hora, refazer o sistema inteiro o tempo todo e justificar dizendo que a arquitetura "esta emergindo".

  • http://unplugged.giggio.net/ Giovanni Bassi

    Preocupação justa!

  • Valdir

    Comentario perfeito do tucaz, acho que as coisas devem estar bem alinhadas com relação a arquitetura antes do inicio de codificação, pois por ai esta cheio de Frankstein que emergiram das profundezas de mentes brilhantes.

  • Pingback: Podcast 16: Arquitetura emergente « .Net Architects Podcast()

  • http://acazsouza.com/ Acazsouza

    Mas pode ser que a gente não saiba se vai precisar dos benefícios do DI por exemplo futuramente. Como faz?

    • http://blog.lambda3.com.br/L3/giovannibassi/ Giovanni Bassi

      Se nao precisamos de DI, nao usamos. Se no futuro for necessario, passamos a usar. Simples assim.

      • http://acazsouza.com/ Acazsouza

        e assim pode ser que cause uma grande manutenção não? digo, um enorme trabalho! mudança entre várias camadas por exemplo

        • http://blog.lambda3.com.br/L3/giovannibassi/ Giovanni Bassi

          DI é o tipo de coisa que percebemos logo se vamos precisar. Não precisa esperar vários meses pra alguém sugerir que é uma boa ideia inverter a dependência. Agora, aplicações pequenas e simples podem não ganhar tanto assim com uma abstração a mais. Aplicações maiores geralmente ganham em curto espaço de tempo.
          Já o uso de um conteiner é algo que pode ser implementado facilmente, se a DI já está em uso. Impactaria vários pontos, o que poderia causar problemas, mas nada que uma suite razoável de testes não pegue. Por isso que arquitetura emergente depende de código limpo.