Construindo arquiteturas que evoluem

Este capítulo possui uma versão mais recente:

Há muito tempo acreditamos que, quando a taxa de mudança dentro de uma instituição se torna mais lenta do que a taxa de mudança externa, o fim está à vista. A única questão é quando.
Jack Welch

Software muda! Muitas vezes para atender novas necessidades do negócio, algumas vezes para acomodar evoluções tecnológicas. Boas práticas arquiteturais ajudam a “aceitar” melhor as mudanças, minimizando custo e riscos.

Apesar de nossos melhores esforços, o software se torna mais difícil de alterar com o tempo. Por uma variedade de razões, as partes que compõem os sistemas de software desafiam a modificação fácil, tornando-se mais frágeis e intratáveis com o tempo. 

Ford, Parsons e Kua

Com o tempo, a aplicação de mudanças gera, naturalmente, complexidades predatórias. Ou seja, resquícios de iniciativas ou decisões do passado que ficam no código ou em decisões que não foram adequadamente revertidas. As práticas da arquitetura devem mitigar essas complexidades de maneira contínua e disciplinada.

Complexity is anything related to the structure of a software system that makes it hard to understand and modify the system.

John Ousterhout

O ritmo das mudanças, tecnológicas e de negócios, está acelerado e está ficando cada vez mais acelerado. Aliás, essa é a característica que melhor justifica as atividades de arquitetura.

If I had to name one primary factor that influences architecture, I’d put rate of change at the top of my list.

Greg Hohpe

Por tudo isso, Evolvability é um importante atributo de qualidade para qualquer boa arquitetura, senão o mais importante.
0
Você concorda?x

Sempre inclua Evolvability entre os atributos de qualidade de seus projetos.

 

Fixing Problems

Definição: Evolvability

Atributo de qualidade relacionado a capacidade de um sistema “evoluir”, tanto para atender demandas de negócio como para “acomodar” novidades tecnológicas, sem comprometer objetivos do negócio, desrespeitar restrições ou romper os demais atributos, minimizando custo ou risco.

As leis de Lehman

Ao longo de décadas, Meir Lehman e László Bélády formularam, propuseram e aprimoraram diversas “leis” que, alegadamente, governam a evolução de sistemas de software. Essas leis ficaram conhecidas como “Leis de Lehman”.

As leis de Lehman

As “Leis de Lehman” direcionam o comportamento e o projeto das iniciativas para engenharia de software.


Nesse episódio, disponível em áudio e vídeo, explicamos essas leis.

Acessar episódio

As “Leis de Lehman” descrevem e ajudam a entender o sensível equilíbrio entre as motivações para a evolução de um software, por adaptações, e as causas para o aumento da complexidade (em consequência, do lead time para atender demandas do negócio) ao longo do tempo.

Complexity will still increase over time, in spite of our best efforts, but simpler designs allow us to build larger and more powerful systems before complexity becomes overwhelming.

John Ousterhout

As duas primeiras “leis” formuladas por eles, em 1974, foram a lei da “mudança contínua” e a lei da “complexidade crescente”. A primeira diz que, ao longo do tempo, um sistema de software precisa ser continuamente adaptado, recebendo novas “adaptações”, para se manter relevante e satisfatório. A segunda aponta que, enquanto essas “adaptações” são feitas, o software se torna mais complexo, exceto quando existam esforços explicitamente direcionados para mitigar essa complexidade.

Qual é a relação existente entre a imagem e o texto da charge? - Brainly.com.br

As duas leis, deliciosamente evidentes e conflitantes, levam a alguns desdobramentos preocupantes:

  • Projetos de software bem sucedidos estão “condenados” a demandarem trabalho para mitigar a a complexidade.
  • Times extremamente eficazes, mas exclusivamente focados em atender as demandas de negócio se tornam, eventualmente, menos produtivos, deteriorando sua capacidade de fazer entregas e, consequentemente, sua eficácia.
    0
    Você concorda?x
  • O esforço para combater a complexidade é imperativo para manter o software relevante no médio/longo prazo.
  • Times de negócio que não se sensibilizam para a necessidade de reduzir a complexidade do software, priorizando somente inclusão de features, se condenam a ter suas demandas atendidas em prazos cada vez maiores.
    0
    Você concorda?x

Dívida técnica

Dívidas técnicas surgem quando desenvolvedores de software, de forma deliberada ou não, abrem mão de boas práticas de desenvolvimento para ganhar algum tempo. Entretanto, acabam sofrendo, mais tarde, com os custos e tempos de manutenção mais altos.

Dissemine as leis de Lehman em sua organização.

Mudanças tecnológicas acontecem rapidamente e têm impactos imprevisíveis

O conjunto de tecnologias, técnicas, padrões e boas práticas para desenvolver software são dinâmicas e instáveis. Essa instabilidade, aliás, é um dos principais desafios para manter e evoluir sistemas.
0
Você concorda?x

A emergência de práticas como a utilização de contêineres, aceleradas por tecnologias como Docker, por exemplo, impactam a indústria de forma definitiva e, para os menos “antenados”, parece surgir de uma hora para outra.

Linguagens novas de programação, mais expressivas (pelo menos para alguns domínios) também surgem em ritmo cada vez mais acelerado. Recentemente, mesmo as linguagens consolidadas também passaram a receber atualizações mais frequentes. Em consequência disso, bases de código gigantes que geram sistemas em produção, parecem cada vez mais “legadas” em prazos cada vez mais curtos.
0
Você concorda?x

Frameworks Javascript parecem crescer em popularidade e se tornarem obsoletas em ciclos, muitas vezes, menores do que os necessários para o desenvolvimentos de alguns grandes sistemas. Em poucos anos, vimos o declínio de jQuery; a ascensão e a “morte” de AngularJS; a “provocação” de Backbone e Mustache; o progresso com Angular, React e Vue; propostas ousadas multiplataforma como Flutter e Electron; etc. É quase impossível dizer qual será a tecnologia dominante para elaboração de frontends de aqui dois anos.

Não conseguimos predizer quando mudanças impactantes do contexto de desenvolvimento irão ocorrer. Nem mesmo conseguimos antecipar quais serão “persistentes” (se é que essa palavra é aplicável), entretanto, sabemos que mudanças acontecem e o ritmo parece ser cada vez mais acelerado.
0
Você concorda?x
Determine qual a obsolescência tecnológica máxima admitida.

Adicionar evolvability como atributo de qualidade arquitetônica implica proteger os demais atributos conforme o sistema evolui.

Ford, Parsons e Kua

Explicitando princípios, requisitos e restrições

Boa arquitetura de software garante o atendimento dos objetivos do negócio, respeitando restrições e atributos de qualidade, minimizando risco ou custo. Para que isso aconteça, esses aspectos precisam ser conhecidos e modelados. 

Requisitos e restrições em projetos de software, emergem de princípios e diretrizes que, por sua vez, são derivados de objetivos associados a aspectos de interesse de algum stakeholder.  Geralmente, aspectos de interesse são “amparados” por conhecimentos prévios. É responsabilidade da arquitetura externar todos esses aspectos.

Para um exemplo tangível, podemos assumir “conversão em e-commerce” como um “tema de interesse” de um CMO. Poderia ser associado o “conhecimento prévio” de que “cada segundo de renderização de página impacta em 7% de conversões”, daí poderia ser desdobrado o objetivo de que “renderizar páginas em menos de 300ms”, que implicaria em uma série de diretrizes arquiteturais associadas – como restrições e atributos de qualidade.

Evolvability emerge de “práticas evolucionárias”

Evolvability, como atributo de qualidade arquitetural, emerge de práticas de engenharia e arquitetura, adequadas a este fim, executadas ao longo do tempo.

Building Evolutionary Architectures

As práticas de arquitetura evolucionárias foram consolidadas, primeiro, nessa excelente obra. Trata-se da referência mais qualificada para esse tema.

Acessar livro

Práticas arquiteturais evolucionárias se caracterizam por:

  • suportar mudanças incrementais, parte por parte, preservando a eficiência (tempo) na aplicação de mudanças futuras;
  • serem guiadas por fitness funcions, comprovando continuamente adequação a parâmetros de qualidade bem-definidos;
  • acomodar concerns em múltiplas dimensões.

A escolha da palavra “evolucionária” é bastante interessante. Ela se afasta, de certa forma, do conceito de “emergência”e de arquitetura emergente. Ou seja, não tem como lema desenvolver a arquitetura de maneira “desregrada”, simplesmente respondendo ao contexto de maneira desordenada. Assim, arquitetura evolucionária é algo muito diferente de “não-arquitetura”, ou da “Arquitetura Zeca Pagodinho” (🎶 deixa a vida me levar, vida leva eu! 🎵).
0
Você concorda com essa afirmação? Há algo a ponderar aqui?x

Building Evolutionary Architectures - Craft Conference 2019

Neil Ford compartilha nessa excelente palestra conceitos e insights fundamentais para o entendimento das práticas de arquitetura evolucionária. Uma verdadeira aula, de um dos criadores do conceito.

Acessar vídeo

Evolvability demanda suporte a mudanças incrementais

Sabendo-se que a necessidade de mudanças é uma constante, a arquitetura evolucionária preconiza elas sejam acomodadas de maneira incremental. De maneira ampla, sempre que possível, mudanças devem ser aplicadas aos poucos, sem grandes saltos ou descontinuidades. Dessa forma, o “custo da mudança” fica diluído causando “menos dor”.
0
Considerações?x

O “represamento” das iniciativas para modernização tecnológica é uma das maiores causas para a “morte” dos sistemas de software. Mesmo quando tecnologias não agregam “algo novo”, o afastamento da trajetória evolutiva das ferramentas, técnicas e práticas por um tempo prolongado aumenta de maneira exponencial o custo e risco para a mudança, apesar dos custos de oportunidade.
0
Você concorda?x

É fundamental tentar “conectar” a atualização tecnológica com um benefício tangível, seja para o atingimento dos objetivos do negócio, respeito as restrições ou atributos de qualidade, implicando, invariavelmente em ganho econômico objetivo e mensurável. A falta da noção clara dos ganhos de uma mudança, em pelo menos uma direção, é sintoma da falta de maturidade para implantar tal mudança. Aliás, raciocínio análogo deve ser aplicado a dívidas técnicas: elas importam apenas quando cobram juros.
0
Você concorda?x
Um sistema se torna legado quando nossa capacidade de pagar dívidas técnicas é menor que a necessidade de contrair novas.

Fernando Paiva

Estruture um “catálogo” das dívidas técnicas. Gerencie-as!

Evolvability demanda “governança arquitetural”

Como garantir que, frente as demandas do dia a dia, times de desenvolvimento de software se comprometam a preservar, sobretudo, atributos de qualidade? Restrições e objetivos de negócio, em geral, são mais fáceis de observar. Entretanto, atributos de qualidade, como disponibilidade e segurança são, certamente, bem menos evidentes. O “caminho”, entende-se, passa pelo estabelecimento de práticas de governança.

Governança

Conjunto de práticas e condutas pelas quais se busca certificar que “resultados planejados” serão realizados, respeitando condições e regras estabelecidas, sem prejuízo para nenhuma das partes.

O estabelecimento de governança arquitetural passa pela definição de guidelines guardrails que determinam um “jeito” de fazer as coisas e limites claros dentro dos quais há autonomia de atuação.
0
Considerações?x

Na prática, guidelines e guardrails são estabelecidos pela definição de padrões e decisões arquiteturais, amplamente comunicadas, e pela adoção de processos e ferramentas de verificação.

A evolvability é, em última instância, a principal conexão entre a arquitetura de software e a escrita de código e impedimento para que antigos erros sejam repetidos.

“Testando” a arquitetura

Há diversas ferramentas disponíveis para ajudar arquitetos a conduzir governança arquitetural de seus sistemas. Mais recentemente, começaram a emergir frameworks de testes automatizados visando ajudar nesse propósito.

Bibliotecas como ArchUnit (para Java) e ArchUnitNET (para .NET) permitem “representar em código” guardrails importantes, como, por exemplo impedir referências cíclicas.

Cycle

IArchRule rule = Slices().Matching("Module.(*)").Should()
                    .BeFreeOfCycles();

Evolvability Architectural Fitness Functions

Quando falamos em governança, devemos encontrar meios objetivos – fórmulas – que se observadas regularmente, demonstram a “aproximação” da solução arquitetural de um “ideal” – por isso, são identificadas como architectural fitness functions.

Definição: Architectural Fitness Functions

Architecture fitness functions são um tipo de função objetivo que é usada para resumir o quão perto uma determinada solução de arquitetura de software está de atingir os objetivos definidos.

Trata-se de um conceito derivado das fitness functions, comuns em algoritmos genéticos.

Architectural fitness functions podem ser holísticas – apuradas com base no software como um todo – ou isoladas, geradas automaticamente (o ideal) ou através de processos manuais, disparadas pelo processo automaticamente ou acionadas explicitamente (como “desempenho” em testes de carga), estáticas (mensuráveis a partir do código) ou dinâmicas (demandando software em execução)

Testes de unidade automatizados, por exemplo, ajudam a estabelecer uma “rede de proteção contra regressão” que, combinados com limites mínimos de cobertura, servem como indícios de evolvability.

Outro bom indicador é a ponderação das métricas de complexidade de um artefato conforme sua frequência de modificação. 

Na fórmula acima, sugere-se que a complexidade de um software inteiro pode ser determinada pela complexidade de uma parte (Cp) e a frequência de mudança dessa parte. Interessante observar que a frequência de mudança pode ser medida usando sistemas de controle de versão (que devem ser bem mais do que backup sofisticados)

A Philosophy of Software Design

A ideia de modularizar um sistema, isolando partes mais complexas com menor necessidade de modificações é a base desse maravilhoso livro.

Acessar livro

Outro bom exemplo, é análise de manutenabilidade a partir de indicadores de acoplamento e abstração (que veremos em detalhes no próximo capítulo).

Essas funções, bem aplicadas, governam a evolução do software, desde que incorporadas a pontos chaves do processo (como em liberação de versões e integração de commits)

The Checkilist Manifesto

O argumento central desse livro é o estabelecimento de procedimentos de verificação, rotineiros, para garantia da qualidade. Trata-se de uma forma de evitar que a “rotina” tire o foco de atividades que são fundamentais.

Acessar livro

Uma “architectural fitness function” deve proteger as diversas propriedades de um sistema de software na medida em que modificações, preferencialmente incrementais, são realizadas. De maneira objetiva, uma solução implementada deve ser submetida sob a perspectiva de diversas fitness functions para garantir que todas as adaptações realizadas não impactam no atingimento dos objetivos de negócio, restrições ou atributos de qualidade que suportam. Toda vez que uma fitness function indicar afastamento do objetivo, sabe-se que há um problema a analisar ou adaptação a rever na arquitetura.

Um exemplo de fitness function dinâmica são as medidas de response time de um serviço. Afinal, trata-se de expressão objetiva da performance (um dos diversos atributos de qualidade possível). Dependendo da “gravidade” a medição de fitness functions poderá ser realizada nos ambientes de desenvolvimento, homologação e produção.
0
Você concorda?x

A qualidade das integrações de um sistema pode ser avaliada com uma fitness function que avalie a quantidade de implementações realizadas contract models (uma medida estática), ou ainda, o respeito aos contratos estabelecidos (uma medida dinâmica).
Adequação jurídica das licenças dos softwares consumidos por um sistema de software pode ser determinada por uma fitness function que verifique, em cada atualização, se os contratos foram alterados e “acionando advogados” quando necessário.
0
Você concorda?x

Cada architectural fitness function consiste em uma decisão arquitetural importante, que precisa ser devidamente registrada em uma ADR.
0
Você concorda?x

Postergando decisões para o “último momento responsável”

Toda decisão implica em assumir riscos. Quanto antes uma decisão é tomada, maiores são os riscos associados a possibilidade dessa decisão representar um erro causando prejuízos.

O início dos projetos de desenvolvimento de software, onde tradicionalmente residem boa parte das “ações arquiteturais”, é, curiosamente, também, o momento onde se sabe menos sobre objetivos de negócio, restrições e atributos de qualidade.
0
Você concorda?x

The General Problem


Quanto mais tarde, em um processo de desenvolvimento, uma decisão é tomada, maior é quantidade de informações disponíveis para fundamentar uma decisão e, consequentemente, maiores são as chances de acerto e, proporcionalmente, menor é o risco.
0
Você concorda?x

As atividades de um arquiteto, em um contexto evolucionário, são o da busca constante da resolução de incertezas. Aliás, o grande inimigo é a incerteza! Isso não significa, entretanto que o arquiteto não deva ter, a todo momento, a “escolha-com-os-dados-de-agora”. Ou seja, documentos arquiteturais e discussões precisam revelar a “posição atual” da arquitetura, indicando, porém, onde estão os pontos de maior incerteza.
0
Você concorda com essa afirmação? Há algo a ponderar aqui?x

No início dos projetos, a principal preocupação dos arquitetos é explicitar a estratégia – padrões coerentes para tomada de decisão – que deve ser observada nas escolhas. Se possível, essa “estratégia” precisa ser objetiva e observável, expressa em architectural fitness functions. Arquitetura evolucionária não é emergente, nem baseada em palpites.

Arquiteturas evolutivas combatem as “origens” da complexidade

There are two general approaches to fighting complexity. The first approach is to eliminate complexity by making code simpler and more obvious. For example, complexity can be reduced by eliminating special cases or using identifiers in a consistent fashion. The second approach to complexity is to encapsulate it, so that programmers can work on a system without being exposed to all of its complexity at once.

John Ousterhout

A complexidade tem quatro origens genéricas distintas que devem ser combatidas. São elas: dimensionalidade, interdependência, influência do ambiente e irreversibilidade.

Quanto maior o número de variáveis envolvidas, maior será a dimensionalidade. Por isso, por exemplo, qualquer software com mais features se torna mais complexo. A cada novo processo na organização, menor a simplicidade. Toda exceção suportada aumenta o custo.

Operações interdependentes demandam, por exemplo, sincronização. Não raro, a indisponibilidade de um recurso impossibilita o uso de outro, aparentemente não relacionado. É bastante comum que uma performance mais pobre de uma parte de um sistema deixe ele todo “lento”.

Sistemas mais “sensíveis” ao ambiente também são mais complexos. Afinal, demandam planejamento de contingências e workarounds.

Finalmente, a irreversibilidade também demanda cuidados. Ações ou eventos cujo ocorrências resultem em consequências que não podem ser desfeitas implicam em custo maior de planejamento, nem sempre eficiente. Boa parte das estratégias modernas de desenvolvimento conta com o pressuposto de um “rollback” rápido. Este é o fundamento de iniciativas operacionais como DevOps.

Naturalmente, sistemas tendem para o incremento da dimensionalidade e da interdependência. Além disso, em ambientes cada vez mais abrangentes, é difícil controlar o impacto do ambiente, marcando, de forma irreversível impactos e prejuízos.  Se o empenho de um time for orientado a apenas manter os níveis atuais de complexidade, essa irá aumentar.

Sistemas que seguem a lei de Postel evoluem mais fácil

Lei de Postel — ou Lei da Robustez — é um princípio originalmente descrito como um guia para a transferência de dados entre softwares. Contudo, ela é bastante compatível com arquitetura.

A lei preconiza que sistemas sejam 1) conservadores no que enviam e ; 2) liberais no que recebem;

Standards

Toda grande jornada tem desvios, atalhos e … aprendizado

Os sistemas mais interessantes (e úteis) costumam começar com uma excelente direção, mas, raramente escopo claramente delimitado. Se há uma certeza é de que requisitos mudam, condições técnicas também.

Arquiteturas de software de qualidade são, acima de tudo, aquelas que permitem que mudanças de rumo sejam feitas com menos trauma possível. Quanto mais “fácil de mudar”, maior o espaço entre eventuais descontinuidades.

// TODO

Antes de avançar para o próximo capítulo, recomendo as seguintes reflexoões:

  • É possível expressar objetivos, atributos de qualidade e restrições do sistema em que está trabalhando de forma objetiva?
  • As métricas de qualidade interna estão orientadas a facilitar a manutenabilidade?
  • Quais partes do seu sistema demandam mais testes?
  • Qual o nível de acoplamento atual do frontend com lógicas de negócio?

Referências bibliográficas

FORD, Neal; PARSONS, Rebecca; KUA, Patrick. Building Evolutionary Architectures: support constant change. Gravenstein Highway North, Ca: O’Reilly Media, Inc, 2017.

MUNROE, Randall. Fixing problems. Disponível em: https://xkcd.com/1739/. Acesso em: 22 abr. 2021.

MUNROE, Randall. Standards. Disponível em: https://xkcd.com/927/. Acesso em: 22 abr. 2021.

MUNROE, Randall. The general problem. Disponível em: https://xkcd.com/974/. Acesso em: 22 abr. 2021.

HANSELMAN, Scott. Exiting The Zone of Pain: static analysis with ndepend. Static Analysis with NDepend. 2007. Disponível em: https://exco.me/ndepend Acesso em: 22 abr. 2021.

PAIVA, Fernando. Quatro práticas equivocadas que dificultam a modernização de sistemas corporativos legados. 2019. Disponível em: https://exco.me/legado. Acesso em: 22 abr. 2021.

WIKIPEDIA. Fitness Function. Disponível em: https://exco.me/fitness. Acesso em: 22 abr. 2021.

Compartilhe este capítulo:

Compartilhe:

Comentários

Participe da construção deste capítulo deixando seu comentário:

Inscrever-se
Notify of
guest
0 Comentários
Feedbacks interativos
Ver todos os comentários

Fundador e CEO da EximiaCo, atua como tech trusted advisor ajudando diversas empresas a gerar mais resultados através da tecnologia.

Mentoria

para arquitetos de software

Imersão, em grupo, supervisionada por Elemar Júnior, onde serão discutidos tópicos avançados de arquitetura de software, extraídos de cenários reais, com ênfase em systems design.

Consultoria e Assessoria em

Arquitetura de Software

EximiaCo oferece a alocação de um Arquiteto de Software em sua empresa para orientar seu time no uso das melhores práticas de arquitetura para projetar a evolução consistente de suas aplicações.

ElemarJúnior

Fundador e CEO da EximiaCo, atua como tech trusted advisor ajudando diversas empresas a gerar mais resultados através da tecnologia.

+55 51 99942-0609 |  contato@eximia.co

+55 51 99942-0609  contato@eximia.co

0
Quero saber a sua opinião, deixe seu comentáriox
()
x