Conheça os Princípios de Engenharia da RD Station e porque eles são nossos diferenciais competitivos (um dos)

Os valores do nosso Culture Code estão para os RDoers, assim como os valores de Engenharia estão para o nosso código. No artigo a seguir abordo em detalhes como (e porque) esses princípios são um dos nossos diferenciais competitivos, tanto no nível de produtos, como em time de tecnologia.

Marcela Sisiliani
Ship It!
9 min readAug 23, 2021

--

Essa é uma versão traduzida do Playbook original de Engenharia, escrito em 2018 pelo Marcelo Uemura, em conjunto com a área.

Foto destaca a mão de uma pessoa segurando uma bússola antiga. Ao fundo é possível ver árvores, montanhas e um céu bem limpo. A imagem é apresentada com cores preto & branco e um filtro verde com transparência
Imagem de Pexels por Pixabay

Entendemos que complexidade é o primeiro desafio do nosso time de engenharia e produto. Além de ser uma fonte infinita de bugs (erros) e/ou incidentes, também impacta diretamente no nosso ritmo de desenvolvimento, seja de novas funcionalidades e produtos ou na manutenção dos nossos serviços existentes.

Complexidade + Alto Crescimento = Mais Complexidade

Gráfico em azul e vermelho, com tons de aquarela, ilustrando o vetor de crescimento da complexidade de um software, onde o eixo Y representa o tamanho de time e o eixo X a linha do tempo
Imagem da Software Explained

Como podemos ver no gráfico acima, a medida que a complexidade do software aumenta, o espaço para criar novas funcionalidades vai diminuindo, até não ter mais espaço para inovar, a não ser que você aumente o tamanho do seu time e o mantenha efetivo (quer saber mais sobre times efetivos, o Rodrigo Miguel te conta como neste post).

Com esse cenário em mente, entendemos que crescer é complicado (até para software hehehe) e que precisamos nos esforçar para que tudo não vire uma bagunça desgovernada. E foi a partir desse entendimento que nós projetamos nossos princípios de engenharia: para nos ajudar a manter a Complexidade sob controle. Mas antes de mergulhar nos nossos princípios, vamos estabelecer alguns conceitos importantes:

  1. O oposto de complexidade é simplicidade (e é isso que buscamos aqui na RD Station)
  2. Ser ‘simples’ não é o mesmo de ser ‘fácil’.

Nós acreditamos que esse segundo ponto é fundamental para entender porque o desenvolvimento de software em larga escala é difícil. Há um bom tempo a indústria vem valorizando soluções “fáceis” ao invés das soluções “simples”. Isso porque as soluções fáceis são muito mais rápidas de serem desenvolvidas e podem ser vendidas por um valor maior, em relação ao investimento da sua criação, do que as soluções simples (que demoram mais tempo para ficarem prontas, porém são mais sustentáveis no longo prazo).

O fato é: projetar soluções simples (na maioria das vezes) é super difícil, mas essa é a única forma de se manter um bom ritmo de desenvolvimento. Nós possuímos uma capacidade cerebral limitada para lidar com complexidade, e quanto mais complexo for o projeto, mais erros iremos cometer, e consequentemente o ritmo de desenvolvimento vai desacelerar ao longo do tempo.

Sobre esse tópico, recomendamos fortemente que você assista o vídeo Simple made Easy, do Rich Hickey, criador do Clojure (não achei um vídeo com legendas em português, se você conhece algum, deixa aí nos comentários pra gente 😉).

Para entender um pouco mais sobre o raciocínio baseado em princípios, dá uma olhada na entrevista do Elon Musk sobre First Principles. Embora nossos princípios de engenharia não sejam o que poderiam ser considerados “Primeiros Princípios” (por estarem um pouco mais focados em nossos desafios atuais), acreditamos que sejam necessários como ponto de partida para questionar o status quo. Assim como Elon Musk explica na entrevista, se usarmos o status quo como ponto de partida, vemos apenas inovação incremental, mas se raciocinarmos a partir dos “primeiros princípios”, isso pode realmente ajudar a ver o que as coisas realmente podem ser.

Com esse contexto em mente, confira a seguir o detalhamento dos nossos princípios de Engenharia aqui na RD Station:

#1 Baixo acoplamento, alta coesão

#2 Desenhe seu código para ser fácil de entender, não fácil de escrever

#3 Reduzir a complexidade global é mais importante que reduzir a complexidade local

#4 Automatize tudo

#1 Baixo acoplamento, alta coesão

Na imagem há dois exemplos de coesão e acoplamento. No primeiro exemplos há dois cubos, onde dentro de cada cubo tem vários pontos que estão conectados entre si, mas apenas um desses pontos se conecta com um ponto do outro cubo. Entendemos que esse é um bom exemplo, pois é baixo acoplamento e alta coesão. Já no segundo exemplo, temos um vários pontos do primero cubo, se conectando com o segundo cubo, causando alto acoplamento entre os dois cubos, e baixa coesão.

O primeiro princípio é a base para arquitetar soluções e desenvolver códigos simples. Talvez você possa pensar “Mas não são dois princípios separados?”, e te respondo que até poderiam ser, mas acreditamos ser importante mantê-los sempre em sincronia para criar projetos simples, por isso eles andam sempre de mãos dadas por aqui.

O que é acoplamento?

O acoplamento é um grau de interdependência entre os módulos de um software. Observe que, toda vez que você chama um método em uma classe diferente, você está acoplando seu código a ela. A verdade é que todo código sempre está acoplado a algo, mas se isso for verdade, por que então devemos nos preocupar com o acoplamento?

Embora seja impossível evitar o acoplamento, é possível escolher com o que você está acoplado.

Vamos a um exemplo: imagine que você escolhe o banco de dados MongoDB para sua aplicação. Se você usar o cliente MongoDB em todo o seu aplicativo, no futuro pode ser extremamente difícil de mudar para outro banco de dados. Por outro lado, se você criar uma camada de abstração simples sobre o cliente MongoDB, seu código será acoplado à sua abstração, e não a um cliente específico. E se a sua abstração for bem projetada, será muito mais fácil de mudar para uma nova tecnologia de banco de dados em um futuro.

Essa breve explicação nos leva a alguns aprendizados importantes. Primeiramente, a construção de um bom código deve considerar a escolha de seus acoplamentos de forma estratégica (e não orgânica). Em segundo lugar, para escolher o que não deve ser acoplado, você deve evitar:

  • Estar acoplado a coisas que têm uma chance provável de mudar em curto ou médio prazo. Seja flexível quanto à mudança.
  • Estar ligado diretamente a coisas que você não tem controle, como serviços externos ou tecnologias de terceiros, por exemplo, pode ser mais fácil escrever uma solução acoplada diretamente a um provedor de identidade, como Auth0, mas em uma situação em que você precise alterar o provedor de identidade de Auth0 para algum outro, pode dar bastante trabalho realizar essa mudança depois (acredite, já vivemos essa dor e ela é cara).

Projetar sistemas de baixo acoplamento, nos permite lidar com a complexidade das mudanças ao longo do tempo. Se você passou pelos princípios do SOLID ou sobre Arquitetura Limpa (Clean Architecture), já deve ter ouvido falar sobre isso antes.

O que é coesão?

Coesão é quando os elementos dentro de um módulo pertencem a outro módulo. Na imagem abaixo vemos um exemplo claro, onde no primeiro retângulo de cores, existe uma harmonia entre os tons. Já no segundo retângulo existe uma diferença absurda.

Mas vamos a outro exemplo, observe as seguintes listas:

  • Maçã, pera, pêssego
  • Maçã, doce, carne, algodão doce

A primeira lista tem uma coesão maior, pois todos os itens da lista tem relação com frutas. Já a segunda lista tem uma coesão muito menor, mas podemos definir como um agrupamento de alimentos. Agora vamos fazer o exercício de pensar em cada um dos itens que compõem ambas as listas. Na primeira lista lidamos apenas com frutas, que basta lavar e comer. Já na segunda lista, se você quiser fazer um lanchinho, um dos itens você só precisa lavar, mas outros vai precisar cozinhar, e alguns até de máquinas específicas você vai precisar para produzi-los.

Quando você lida com alta coesão, há um limite de quantidade de complexidade que seu cérebro tem que lidar em um determinado momento. Do contrário, quando há baixa coesão, você precisa lidar com muitos casos extremos e exceções (se a comida for carne, cozinhe primeiro). Em outras palavras, a baixa coesão leva ao aumento da complexidade que seu cérebro tem que lidar, o que leva invariavelmente a novos erros ;).

#2 Desenhe seu código para ser fácil de entender, não fácil de escrever

Na imagem aparece uma animação de um botão vermelho escrito easy, e uma mão aperta essa botão
Gif de Giphy

À medida que um sistema cresce, também aumenta o custo e o tempo gasto em sua manutenção. Passamos mais tempo lendo, do que escrevendo código novo, e consequentemente, mais tempo tentando entender o que ele faz antes de implementar qualquer mudança. Se não rolar de ter um entendimento completo, vamos acabar fazendo algo mais complexo do que o necessário ou, ainda pior, vamos criar novos erros (sim, de novo) e comportamentos indesejados no sistema.

Se você pensar com carinho sobre isso, praticamente todos os erros do sistema acontecem devido a uma compreensão incompleta do problema.

Então, chegamos ao nosso segundo princípio que é: sempre devemos preferir um código que seja mais fácil de entender do que um código que seja mais fácil de escrever. Sendo assim, em vez de ter muito comportamento implícito, sempre prefira um código que descreva o que está fazendo de maneira explícita. Aquele tipo de código que conta uma história, entende? Aprendi essa com meu amigo @Antonio Muniz :)

Por exemplo, vamos supor que adicionamos um callback (que é um trecho de código que funciona como um gatilho, ou seja, sempre que um trecho de código é executado esse gatilho também é) a um modelo ActiveRecord que será acionado sempre que esse modelo tiver uma atualização. Isso é algo muito fácil de fazer. Temos várias maneiras de configurar um retorno de chamada no ActiveRecord, podemos fazê-lo através de callbacks, concerns, meta programação, bibliotecas de terceiros, etc. Quanto mais ‘oculto’ for este comportamento, mais difícil será saber sobre ele.

Mas sendo bem direta ao ponto, entendemos que um código mais fácil de entender é um código que segue duas diretrizes:

  • É explícito sobre o comportamento.
  • Possui alta coesão.

#3 Reduzir a complexidade global é mais importante que reduzir a complexidade local

Esse valor é da hora porque deixamos de olhar apenas para o escopo do nosso domínio e, como um bom time, passamos a ter uma visão ampla da arquitetura da solução da empresa. Por exemplo, por mais que eu desenvolva aplicações super simples e seja preocupada em fazer o que é simples nos domínios em que meu time é responsável, por vezes posso aumentar a complexidade geral das soluções da RD Station se essa nova aplicação não for coesa e alinhada com o restante do sistema.

É por isso que precisamos priorizar o alinhamento entre componentes em vez de fazer o que é melhor para um único domínio. Por exemplo, pode ser que determinado provedor de nuvem tenha a melhor solução para um problema específico. Mas se isso significa adicionar outro provedor de nuvem à solução, deve-se considerar a complexidade adicional (e acidental) para construir, implantar e manter esse novo provedor, gerenciamento de COGS, contratos e faturamento, treinamento extra necessário para as pessoas que lidam com isso no dia a dia e assim por diante. E daí a solução linda e fácil que encontrei para o meu domínio cai por terra, se considerarmos o tanto de complexidade que traz na bagagem para a empresa como um todo.

Resumindo: sempre que nos deparamos com a escolha de fazer o que é simples localmente contra o que é simples globalmente, escolhemos o último.

#4 Automatize tudo

Gif de Giphy

Por último, mas bem longe de ser o menos importante, vem o nosso valor “Automatize tudo”. É muito claro pra RD Station que, como uma empresa de alto crescimento, não podemos nos dar ao luxo de trabalhar nos mesmos problemas continuamente porque, se dobramos a cada ano, também estamos dobrando os mesmos problemas todos os anos, e a escala não é resolvida apenas adicionando mais pessoas ao time.

Entendemos que precisamos trabalhar de forma inteligente, não árdua, então a ideia por trás do quarto princípio é automatizar tudo o que pudermos para minimizar o trabalho e reduzir a complexidade adicional causada pelo crescimento de uma empresa.

O que sempre repetimos por aqui: os computadores são muito melhores que nós para fazer trabalho repetitivo, então bora se aproveitar disso e focar em criar e desenvolver produtos criativos!

Curtiu conhecer um pouquinho mais sobre a Engenharia da RD Station, e entender como guiamos nossas decisões técnicas no dia a dia através dos nossos princípios? Deixa nos comentários o que você achou, e bora trocar uma ideia ;)

E se você estiver procurando novos desafios para sua carreira e um ambiente bacana para se desenvolver, chega mais que nós temos várias oportunidades abertas, cada uma com um desafio diferente :)

--

--