A tradução do artigo foi preparada especificamente para os alunos do curso "DevOps Practices and Tools" .
Este artigo discute o relacionamento entre estrutura de código e estrutura organizacional no desenvolvimento de software. Discuto por que software e equipes não podem ser escalados com facilidade, quais lições podemos tirar da natureza e da Internet e mostro como podemos reduzir a conectividade de software e equipes para superar os problemas de dimensionamento.
Este artigo é baseado nos meus 20 anos de experiência na criação de grandes sistemas de software e na impressão do livro
"Acelerar: A Ciência do Software Lean e DevOps: Construindo e Escalando Organizações de Tecnologia de Alto Desempenho" (Nicole Forsgren, Jez Humble e Gene Kim), que evidências de pesquisa para fazer backup da maioria das minhas reivindicações aqui. Este livro é altamente recomendado para leitura.

Software e comandos não escalam
Muitas vezes, o primeiro lançamento, talvez escrito por uma ou duas pessoas, é surpreendentemente simples. Pode ter funcionalidade limitada, mas foi escrito rapidamente e atende aos requisitos do cliente. A interação com o cliente nesta fase é excelente, porque o cliente geralmente está em contato direto com os desenvolvedores. Quaisquer erros são corrigidos rapidamente e novos recursos podem ser adicionados sem problemas. Depois de um tempo, o ritmo diminui. A versão 2.0 leva um pouco mais do que o esperado. É mais difícil corrigir bugs, e novos recursos são fornecidos, não é tão simples. A resposta natural para isso é adicionar novos desenvolvedores à equipe. Embora pareça que cada funcionário adicional adicionado à equipe reduz a produtividade. Há um sentimento de que, à medida que a complexidade do software aumenta, ele se atrofia. Em casos extremos, as organizações podem achar que usam programas com suporte muito caro, quase impossíveis de fazer alterações. O problema é que você não precisa cometer nenhum “erro” para que isso aconteça. É tão comum que se pode dizer que essa é uma propriedade "natural" do software.
Por que isso está acontecendo? Há dois motivos: aqueles relacionados ao código e à equipe. O código e os comandos não são bem dimensionados.
À medida que a base de código cresce, torna-se cada vez mais difícil para uma pessoa entendê-la. Existem limites cognitivos fixos de uma pessoa. E, no entanto, uma pessoa pode ter em mente os detalhes de um pequeno sistema, mas apenas até que ele se torne mais do que seu alcance cognitivo. Assim que uma equipe cresce para cinco ou mais pessoas, torna-se quase impossível para uma pessoa estar ciente de como todas as partes do sistema funcionam. E quando ninguém entende todo o sistema, o medo aparece. Em um sistema grande e fortemente acoplado, é muito difícil entender o efeito de quaisquer alterações significativas, pois o resultado não é localizado. Para minimizar o impacto das alterações, os desenvolvedores começam a usar soluções alternativas e duplicação de código em vez de identificar recursos comuns, criando abstrações e generalizações. Isso complica ainda mais o sistema, reforçando essas tendências negativas. Os desenvolvedores não se sentem mais responsáveis pelo código que eles não entendem e relutam em refatorar. A dívida técnica está crescendo. Também torna o trabalho desagradável e insatisfatório e estimula uma "fuga de talentos" quando os melhores desenvolvedores saem, que podem facilmente encontrar trabalho em outro lugar.
As equipes também não escalam. À medida que as equipes crescem, a comunicação se torna mais complexa. Uma fórmula simples entra em jogo:
c = n(n-1)/2
(onde n é o número de pessoas e c é o número de conexões possíveis entre os membros da equipe)À medida que sua equipe cresce, suas necessidades de comunicação e coordenação crescem exponencialmente. Se uma determinada equipe é excedida, é muito difícil para uma equipe permanecer uma estrutura integral, e a tendência social humana natural de se dividir em grupos menores levará à formação de subgrupos informais, mesmo que a gerência não participe. A comunicação com os colegas se torna mais difícil e será naturalmente substituída por novos líderes e comunicações de cima para baixo. Os membros da equipe são transformados de colegas no sistema em trabalhadores de produção regulares. A motivação sofre, não há senso de propriedade devido ao
efeito da difusão da responsabilidade .
A gerência frequentemente intervém nesse estágio e aborda formalmente a criação de novas equipes e estruturas de gerenciamento. Mas, não importa formal ou informalmente, é difícil para as grandes organizações manter a motivação e o interesse.
Geralmente, desenvolvedores inexperientes e um gerenciamento deficiente culpam essas patologias de dimensionamento. Mas isso é injusto. Os problemas de escala são uma propriedade "natural" do crescimento e evolução de software. É o que sempre acontece se você não encontrar o problema em um estágio inicial, não entender o ponto de desvio e não fizer nenhum esforço para resolvê-lo. As equipes de desenvolvimento de software estão sendo constantemente criadas, a quantidade de software no mundo está em constante crescimento e a maior parte do software é relativamente pequena. Portanto, muitas vezes, um produto bem-sucedido e em desenvolvimento é criado por uma equipe que não possui experiência em desenvolvimento em larga escala. E não é realista esperar que os desenvolvedores reconheçam o ponto de inflexão e entendam o que fazer quando problemas de escala começarem a se manifestar.
Nature Scaling Lessons
Recentemente, li o excelente livro de
Geoffrey West ,
“Scale” . Ele fala sobre matemática de escala em sistemas biológicos e socioeconômicos. Sua tese é que todos os grandes sistemas complexos obedecem às leis fundamentais da escala. Esta é uma leitura fascinante e eu recomendo. Neste artigo, quero focar em seu ponto de vista de que muitos sistemas biológicos e sociais são surpreendentemente bem dimensionados. Olhe para o corpo de um mamífero. Todos os mamíferos têm os mesmos tipos de células, estrutura óssea, sistemas nervoso e circulatório. No entanto, a diferença de tamanho entre o mouse e a baleia azul é de cerca de 10 ^ 7. Como a natureza usa os mesmos materiais e estrutura para organismos de tamanhos tão diferentes? A resposta parece ser que a evolução descobriu estruturas ramificadas fractais. Olhe para a árvore. Cada parte parece uma pequena árvore. O mesmo vale para os sistemas nervoso e circulatório de mamíferos, pois são redes fractais ramificadas em que uma pequena parte de seus pulmões ou vasos sanguíneos se parece com uma versão menor do todo.

Podemos tirar essas idéias da natureza e aplicá-las ao software? Acho que podemos aprender lições importantes. Se pudermos construir sistemas grandes que consistem em pequenas partes que parecem sistemas completos, será possível conter as patologias que afetam a maioria dos programas à medida que crescem e se desenvolvem.
Existem sistemas de software que escalam com sucesso em várias ordens de magnitude? A resposta é óbvia - a Internet, um sistema global de software com milhões de nós. As sub-redes realmente parecem e funcionam como versões menores de toda a Internet.
Sinais de software fracamente acoplado
A capacidade de isolar componentes separados e pouco acoplados em um sistema grande é o principal método de dimensionamento bem-sucedido. A Internet, de fato, é um exemplo de arquitetura pouco acoplada. Isso significa que cada nó, serviço ou aplicativo na rede possui as seguintes propriedades:
- Um protocolo de comunicação comum é usado.
- Os dados são transferidos usando um contrato claro com outros nós.
- A comunicação não requer conhecimento de tecnologias de implementação específicas.
- O controle de versão e a implantação são independentes.
A Internet é escalável porque é uma rede de nós que se comunica através de um conjunto de protocolos bem definidos. Os nós interagem apenas por protocolos, cujos detalhes de implementação não devem ser conhecidos pelos nós que interagem. A Internet global não é implantada como um sistema único. Cada nó possui sua própria versão e procedimento de implementação. Nós individuais aparecem e desaparecem independentemente um do outro. O envio para protocolos da Internet é a única coisa que realmente importa para todo o sistema. Quem criou cada site, quando foi criado ou excluído, qual versão possui, quais tecnologias e plataformas específicas ele usa, tudo isso não tem nada a ver com a Internet como um todo. É isso que queremos dizer com software fracamente acoplado.
Sinais de uma organização fracamente acoplada
Podemos escalar equipes seguindo os mesmos princípios:
- Cada subequipe deve parecer uma pequena organização de desenvolvimento de software.
- Os processos internos e a comunicação da equipe não devem ir além da equipe.
- As tecnologias e processos usados para implementar o software não devem ser discutidos fora da equipe.
- As equipes devem se comunicar apenas em questões externas: protocolos comuns, funcionalidade, níveis de serviço e recursos.
As equipes de desenvolvimento pequenas são mais eficazes que as grandes, portanto, é necessário dividir equipes grandes em grupos menores. As lições da natureza e da Internet são que os subgrupos devem parecer pequenas organizações de desenvolvimento de software. Quão pequenos eles são? Idealmente, de uma a cinco pessoas.
O importante é que cada equipe pareça uma pequena organização de desenvolvimento de software independente. Outras maneiras de organizar equipes são menos eficazes. Muitas vezes, há uma tentação de dividir uma grande equipe em funções. Portanto, temos uma equipe de arquitetos, uma equipe de desenvolvimento, uma equipe de DBA, uma equipe de testadores, uma equipe de implantação e uma equipe de suporte, mas isso não resolve nenhum dos problemas de dimensionamento mencionados acima. Todas as equipes devem participar do desenvolvimento de um recurso e, frequentemente, de forma iterativa, se você deseja evitar o gerenciamento de projetos no estilo de uma cascata.
As barreiras de comunicação entre essas equipes funcionais estão se tornando um grande obstáculo à entrega eficiente e oportuna. As equipes estão fortemente conectadas porque precisam compartilhar detalhes internos importantes para trabalharem juntos. Além disso, os interesses de diferentes equipes não coincidem: os desenvolvedores geralmente recebem um prêmio por novos recursos, testadores de qualidade, suporte à estabilidade. Esses interesses diferentes podem levar a conflitos e a maus resultados. Por que os desenvolvedores devem se preocupar com os logs, se nunca os leem? Por que os testadores se preocupam com a entrega se são responsáveis pela qualidade?
Em vez disso, devemos organizar equipes para serviços vagamente acoplados que suportam funções de negócios ou para um grupo lógico de funções. Cada subcomando deve projetar, codificar, testar, implantar e manter seu próprio software. Muito provavelmente, os membros dessa equipe serão especialistas de amplo perfil, e não especialistas restritos, porque em uma equipe pequena será necessário separar essas funções. Eles devem se concentrar no máximo possível de automação de processos: teste automatizado, implantação, monitoramento. As equipes devem escolher suas próprias ferramentas e projetar a arquitetura para seus sistemas. Embora os protocolos usados para a interação dos serviços devam ser determinados no nível da organização, a escolha das ferramentas usadas para implementá-los deve ser delegada às equipes. E isso se encaixa muito bem com o modelo DevOps.
O nível de independência que uma equipe possui é um reflexo do nível de conexão de toda a organização. Idealmente, a organização deve cuidar da funcionalidade do software e, finalmente, do valor comercial que a equipe fornece, além do custo dos recursos da equipe.
Nesse caso, o arquiteto de software desempenha um papel importante. Não deve se concentrar em ferramentas e tecnologias específicas que as equipes usam ou interferir nos detalhes da arquitetura interna dos serviços. Em vez disso, deve se concentrar em protocolos e interações entre diferentes serviços e a saúde do sistema como um todo.
Lei invertida de Conway: a estrutura da organização deve modelar a arquitetura de destino
Como a coerência fraca do software e a coerência fraca da equipe se encaixam?
A lei de Conway declara:
"As organizações que projetam sistemas são limitadas a um design que copia a estrutura de comunicação desta organização."
Isso se baseia na observação de que a arquitetura de um sistema de software refletirá a estrutura da organização que o criou. Podemos "invadir" a lei de Conway revertendo-a. Organize nossas equipes para refletir a arquitetura desejada. Com isso em mente, devemos alinhar equipes fracamente acopladas com componentes de software fracamente acoplados. Mas deveria ser um relacionamento individual? Eu acho que idealmente sim. Embora pareça bom, se uma equipe pequena trabalhar em vários serviços vagamente acoplados. Eu diria que o ponto de inflexão da escala é maior para as equipes do que para o software, portanto esse estilo de organização parece aceitável. É importante que os componentes de software permaneçam separados, com versões e implantação próprias, mesmo que alguns deles sejam desenvolvidos por uma equipe. Gostaríamos de poder dividir a equipe se ela for muito grande, com a transferência de serviços desenvolvidos para diferentes equipes. Mas não podemos fazer isso se os serviços estiverem fortemente acoplados ou compartilharem um processo, versão ou implantação.
Devemos evitar o trabalho de várias equipes nos mesmos componentes. Este é um anti-padrão. E, de certa forma, ainda pior do que o trabalho de uma grande equipe com uma grande base de códigos, porque as barreiras de comunicação entre equipes levam a um sentimento ainda mais forte de falta de propriedade e controle.

A interação entre equipes fracamente acopladas, criando softwares fracamente acoplados, é minimizada. Veja o exemplo da Internet novamente. Geralmente, você pode usar a API fornecida por outra empresa sem comunicação direta com ela (se o processo for simples e houver documentação). Quando as equipes interagem, os processos internos de desenvolvimento e implementação da equipe não devem ser discutidos. Em vez disso, funcionalidade, níveis de serviço e recursos devem ser discutidos.
Gerenciar equipes fracamente acopladas, criando software fracamente acoplado, deve ser mais fácil do que alternativas. Uma organização grande deve se concentrar em fornecer às equipes metas e requisitos claros em termos de funcionalidade e níveis de serviço. Os requisitos de recursos devem vir da equipe, embora possam ser usados pela organização para medir o retorno do investimento.
Equipes fracamente acopladas desenvolvem software fracamente acoplado
A fraca conectividade no software e entre equipes é a chave para a construção de uma organização altamente eficaz. E minha experiência confirma esse ponto. Trabalhei em organizações nas quais as equipes eram divididas por função, nível de software ou até onde havia uma separação de clientes. Também trabalhei em grandes equipes caóticas em uma única base de código. Mas em todos esses casos, houve problemas com o dimensionamento, mencionados acima. A experiência mais agradável sempre foi quando minha equipe era uma unidade completa, envolvida independentemente na criação, teste e implantação de serviços independentes. Mas você não precisa confiar nas histórias da minha vida. Accelerate (descrito acima) possui evidências de pesquisa para apoiar essa visão.
Se você leu este material até o final, recomendamos assistir a uma gravação de um seminário on-line aberto sobre o tópico "Um dia na vida do DevOps" .