#239 - 4 mitos em engenharia de software com Edu Matos
Resumo
Neste episódio solo, Edu Matos aborda quatro mitos recorrentes na engenharia de software. O primeiro mito é que “uma linguagem X é lenta”. Ele argumenta que, embora benchmarks mostrem diferenças de velocidade entre linguagens, na prática essas diferenças são menos relevantes em ambientes de produção, especialmente para aplicações web que são tipicamente IO-bound. A otimização das operações de I/O (como consultas a banco de dados e chamadas HTTP) geralmente traz mais ganhos de desempenho do que a simples troca de linguagem.
O segundo mito discutido é que “microsserviços são melhores do que monolitos” (ou vice-versa). Edu explica que a escolha depende do momento da empresa e das necessidades específicas. Monolitos são mais simples para começar e oferecem maior velocidade de desenvolvimento inicial, enquanto sistemas distribuídos (microsserviços) podem oferecer melhor estabilidade e escalabilidade em cenários específicos, mas com aumento de complexidade. A recomendação é começar com monolitos bem estruturados que facilitem futuras separações.
O terceiro mito é que “bancos de dados SQL não escalam”. Ele desmonta essa ideia mostrando várias técnicas para escalar tanto leitura (índices, cache, réplicas, desnormalização, data warehouses) quanto escrita (batching, diluição no tempo, concorrência) em bancos relacionais. A chave é entender especificamente o que precisa escalar (leitura, escrita, número de conexões) antes de considerar mudanças radicais.
O quarto e último mito é sobre “trunk-based development” como solução ideal. Edu reconhece os benefícios de entregas pequenas e frequentes para reduzir riscos, mas critica o uso excessivo de feature flags para quebrar funcionalidades grandes em pedaços que só fazem sentido juntos. Ele argumenta que isso pode poluir o código com complexidade desnecessária e que o verdadeiro desafio está em criar escopos menores de valor do lado do negócio, não apenas em técnicas de versionamento.
Indicações
Educational_Resources
- Escola Forja — Uma escola para formação de líderes na área de tecnologia, com treinamentos, workshops, masterclasses, estudos de caso e palestras. Edu Matos a recomenda e menciona que diversos conteúdos são gratuitos.
Linha do Tempo
- 00:00:00 — Introdução aos quatro mitos da engenharia de software — Edu Matos apresenta o episódio solo sobre mitos na área. Ele anuncia que vai discutir quatro crenças comuns que se tornaram “verdades” mas que precisam ser questionadas. O primeiro mito será sobre linguagens de programação serem consideradas lentas.
- 00:00:32 — Mito 1: Uma linguagem X é lenta — Edu aborda o mito de que certas linguagens (como JavaScript ou Python) são inerentemente lentas. Ele reconhece que benchmarks mostram diferenças, mas argumenta que essas diferenças são menos relevantes em produção, especialmente para aplicações web IO-bound. A otimização de operações de I/O (banco de dados, chamadas HTTP) geralmente traz mais ganho do que trocar de linguagem.
- 00:08:30 — Mito 2: Microsserviços são melhores que monolitos — Edu discute a falsa dicotomia entre microsserviços e monolitos. Ele explica que a escolha depende do contexto: monolitos oferecem velocidade inicial e simplicidade, enquanto sistemas distribuídos oferecem estabilidade e escalabilidade com maior complexidade. Recomenda começar com monolitos bem estruturados e evoluir para microsserviços apenas quando houver dor real (custo, dificuldade de escala).
- 00:17:07 — Mito 3: Bancos de dados SQL não escalam — Edu desmonta o mito de que bancos relacionais não escalam. Ele detalha técnicas para escalar leitura (índices, cache, réplicas, desnormalização, data warehouses) e escrita (batching, transações, concorrência). A chave é definir o que significa “escalar” (leitura, escrita, conexões) antes de buscar soluções complexas, pois muitas vezes o SQL pode ser otimizado.
- 00:37:14 — Mito 4: Trunk-based development como solução ideal — Edu analisa o trunk-based development, método que prega branches de curta duração e integração frequente na main. Ele concorda com o benefício de entregas pequenas para reduzir risco, mas critica o uso excessivo de feature flags para quebrar funcionalidades grandes, pois isso polui o código. O verdadeiro desafio, segundo ele, é criar escopos menores de valor do lado do negócio.
- 00:46:48 — Conclusão e convite para a Escola Forja — Edu encerra resumindo os quatro mitos discutidos e pergunta se os ouvintes gostaram do formato. Ele convida para conhecer a Escola Forja, uma escola para formação de líderes em tecnologia, e encerra o episódio.
Dados do Episódio
- Podcast: Tech Leadership Rocks
- Autor: Eduardo Matos
- Categoria: Technology
- Publicado: 2025-07-13T13:21:47Z
- Duração: 00:47:42
Referências
- URL PocketCasts: https://pocketcasts.com/podcast/2670a500-d4f6-0138-e77e-0acc26574db2/episode/e209cbfe-19bd-4a7c-913b-cb6c48d9e25f/
- UUID Episódio: e209cbfe-19bd-4a7c-913b-cb6c48d9e25f
Dados do Podcast
- Nome: Tech Leadership Rocks
- Tipo: episodic
- Site: https://escolaforja.com.br/podcast/tech-leadership-rocks
- UUID: 2670a500-d4f6-0138-e77e-0acc26574db2
Transcrição
[00:00:00] Olá, Edu Matos aqui para mais um episódio do podcast Tech Leadership Rocks.
[00:00:05] Dessa vez eu estou sozinho aqui de novo, então mais um episódio solo.
[00:00:09] E dessa vez eu estou trazendo aqui o que eu considero, pelo menos, quatro mitos da engenharia de software.
[00:00:15] Tem muita coisa que a gente ouve falar por aí, que às vezes se torna meio que uma verdade,
[00:00:20] mas não são tanto uma verdade assim.
[00:00:23] Então eu vou trazer quatro que eu considero que, para mim, são quatro grandes mitos.
[00:00:27] O primeiro deles é que uma linguagem X é lenta.
[00:00:32] Então a gente já cansou de ouvir falar coisas desse tipo.
[00:00:34] Ah, não, tal linguagem é lenta.
[00:00:35] Geralmente alguém fala que JavaScript é lento, que Python é lento,
[00:00:39] que algumas outras linguagens são lentas, enquanto outras são linguagens que são consideradas rápidas.
[00:00:45] Esse mito eu diria que tem até um certo fundo de verdade.
[00:00:49] Então eu vou colocar até aqui na tela, caso você esteja assistindo a versão em vídeo,
[00:00:54] um benchmark que ficou bem famoso, ele viralizou aí,
[00:00:57] de comparações entre linguagens, de um bilhão de iterações em diferentes linguagens,
[00:01:03] em Python, em JavaScript, enfim, em C, em Rust, por aí vai.
[00:01:10] E claramente algumas delas são, de fato, mais rápidas do que outras para rodar um bilhão de iterações.
[00:01:15] Mas tem alguns problemas quando a gente começa a olhar para esse tipo de benchmark,
[00:01:19] que é, beleza, será que uma aplicação rodando em produção, ela de fato, vamos dizer assim,
[00:01:25] se relaciona com a performance nesse tipo de benchmark?
[00:01:29] A resposta é que provavelmente não, tá bom?
[00:01:31] Porque quando a gente pensa em uma aplicação rodando no ambiente de produção,
[00:01:34] a gente pensa em aplicações que fazem os mais diversos tipos de processamento ali.
[00:01:39] Então desde operações de I.O.U. até operações mais de CPU, enfim,
[00:01:43] a gente vai buscar algo em memória, vai ler do disco, por aí vai.
[00:01:47] Então tem muitas coisas que a gente faz ali que vão além de somente rodar iterações.
[00:01:51] Então não dá para simplesmente a gente se basear nesse tipo de benchmark,
[00:01:54] ou pelo menos esse especificamente.
[00:01:55] Que eu coloquei aqui para a gente se basear, se uma linguagem é mais lenta ou mais rápida.
[00:01:59] Mas de fato, algumas linguagens são mais rápidas do que outras de maneira geral.
[00:02:03] Se a gente comparar ali, talvez, enfim, um tempo que ela leva para rodar uma função
[00:02:08] ou algo nesse sentido, uma linguagem vai ser mais rápida.
[00:02:11] Então sim, a gente tem diferença entre linguagens.
[00:02:14] Mas o meu principal ponto aqui é que essas diferenças, em geral,
[00:02:18] quando a gente vai olhar para o ambiente de produção, elas não são tão relevantes, tá bom?
[00:02:22] Por que elas não são tão relevantes?
[00:02:24] Primeiro, deixa eu dar um passo atrás aqui e explicar um conceito que vai ser fundamental
[00:02:28] para a gente nessa comparação aqui, tá?
[00:02:30] Que são basicamente aplicações que estão em duas categorias diferentes ali.
[00:02:34] Elas podem se misturar eventualmente, mas geralmente a gente consegue separar
[00:02:37] aplicações em duas categorias.
[00:02:39] A primeira são aplicações que são CPU bound e a segunda aplicações que são IO bound.
[00:02:45] O que isso significa?
[00:02:48] CPU bound é basicamente quando uma aplicação faz uso intensivo de CPU
[00:02:54] em suas operações.
[00:02:54] Então um exemplo típico disso é processamento de vídeo.
[00:02:57] Então pensa, por exemplo, quando a gente vai fazer upload de um vídeo lá no YouTube.
[00:03:01] Então ele tem que processar esse vídeo.
[00:03:03] Ele faz o que a gente chama de transcoding, né?
[00:03:05] Então ele coloca ali em diversas resoluções, diversas qualidades, enfim,
[00:03:09] de acordo para o usuário baixar de acordo com a capacidade de rede dele, da internet.
[00:03:16] Então esse processamento de vídeo é extremamente intensivo em CPU.
[00:03:20] Então o CPU está trabalhando ali 100% do tempo para conseguir fazer aquilo.
[00:03:24] Já existem outras aplicações que são IO bound.
[00:03:27] O que isso significa ser IO bound?
[00:03:30] Em resumo, são aplicações que acessam bastante a rede.
[00:03:33] Então, por exemplo, acesso a banco de dados, acesso a disco local, talvez uma chamada HTTP,
[00:03:39] pegar uma mensagem de uma fila ou coisas nesse sentido.
[00:03:42] Então quando a aplicação tem muito dessas interações, então são aplicações que são IO bound.
[00:03:49] Geralmente a gente consegue separar essas duas categorias.
[00:03:52] Então aplicações que são mais…
[00:03:54] Vamos dizer assim, intensivas em CPU, outras aplicações são mais intensivas em IO.
[00:03:59] Quando a gente pensa em aplicações web, é que eu estou falando muito do meu background, tá bom?
[00:04:02] Talvez não seja o seu, mas pelo menos no meu background, aplicações web são extremamente intensivas em IO e não tanto em CPU.
[00:04:09] Apesar de eventualmente ter um outro processo que é mais intensivo em CPU.
[00:04:13] Mas em geral, as aplicações web, elas focam muito na parte de IO.
[00:04:18] Então é pegar a mensagem de uma fila, é fazer consultas de banco de dados, seja de escrita ou de leitura, não importa tanto.
[00:04:23] Então a gente…
[00:04:24] Geralmente está muito focada no IO.
[00:04:26] E quando a gente pensa em aplicações focadas mais em IO, vamos dizer assim, o desempenho da linguagem, ela passa a ser quase que irrelevante
[00:04:35] quando a gente considera essas interações com, por exemplo, banco de dados ou pegar a mensagem de uma fila, fazer uma requisição HTTP.
[00:04:42] E como essas interações com, vamos dizer assim, com IO, com aplicações que estão fora da nossa aplicação principal,
[00:04:50] elas acabam se tornando gargalo, então o desempenho da linguagem, ela deixa de ser tão…
[00:04:54] Relevante.
[00:04:54] Então para a gente ganhar desempenho na nossa aplicação, o foco talvez não seja mais tanto em ter uma linguagem que seja mais rápida.
[00:05:01] E sim a gente conseguir fazer essas interações de IO da melhor maneira possível, da forma mais otimizada possível.
[00:05:06] O que pode envolver a gente, sei lá, fazer otimizações no banco de dados, por exemplo, ou a gente fazer algumas operações em batch.
[00:05:13] Então, por exemplo, ah, então ao invés de fazer uma requisição HTTP, se eu conseguir agrupar essas chamadas HTTP em uma chamada só,
[00:05:21] provavelmente eu vou ter um desempenho melhor.
[00:05:23] Então o ganho que a gente vai ter trabalhando nessas operações de IO especificamente, vai trazer um desempenho muito maior para a nossa aplicação
[00:05:31] do que se a gente simplesmente focar na simples troca de linguagem, tá?
[00:05:35] Mas é bom ter em mente aqui que linguagens diferentes vão trazer benefícios diferentes ali.
[00:05:40] Quando eu falo isso, eu estou me referindo muito mais a que algumas linguagens, elas facilitam que a gente tire proveito de concorrência.
[00:05:48] Então, por exemplo, Go é uma linguagem que facilita bastante o uso de…
[00:05:53] operações concorrentes, usando as Go Routines.
[00:05:56] Em Python, historicamente, Python nunca foi uma linguagem lá muito boa para isso, apesar de ter threads, enfim,
[00:06:01] mas threads em Python não são lá uma ferramenta que normalmente é muito usada.
[00:06:06] Mas recentemente a gente tem a SyncIO em Python, que ajuda bastante nessas operações de IO.
[00:06:12] Em JavaScript, a gente tem, por exemplo, as Promises, ou JavaScript de maneira geral, na verdade ele já é uma linguagem,
[00:06:19] ou Node, não é uma plataforma que consegue dar bastante suporte a trabalho.
[00:06:23] Então, Node, naturalmente, já é bom para isso.
[00:06:27] Mas agora, quando a gente pensa, por exemplo, numa aplicação mais CPU-bound, então Node, provavelmente, JavaScript, no caso,
[00:06:35] não vai ser uma opção muito boa, porque JavaScript, ou Node, ele é single-threaded, assim como Python também é single-threaded.
[00:06:42] Em tese, a gente poderia até usar worker threads ali em JavaScript, ou usar threads em Python, mas não vai ser, talvez, o melhor uso da linguagem.
[00:06:50] Go, nesse caso, ele se encaixaria muito melhor.
[00:06:52] Então, de fato, a gente…
[00:06:53] A gente tem algumas diferenças de linguagens que conseguem nos ajudar em uma ou outra situação, mas, em geral, pensando em aplicações web,
[00:07:00] o que é importante a gente ter em mente aqui é que, geralmente, a parte que interage com a rede, de novo, uma escrita no banco,
[00:07:09] uma leitura no banco, pegar uma mensagem de uma fila, fazer uma requisição HTTP, uma chamada RPC, pode ser até usando GRPC,
[00:07:16] não importa tanto aqui, tanto protocolo.
[00:07:17] O que importa é, essas chamadas externas, elas geralmente são muito mais relevantes.
[00:07:22] Elas são independentes da linguagem, tá bom?
[00:07:24] Então, se a nossa linguagem, ela consegue, vamos dizer assim, ajudar a gente a lidar com essas chamadas de I.O.,
[00:07:30] então, ela, provavelmente, vai ser rápida o suficiente em relação ao tempo que a gente, naturalmente, levaria em I.O.
[00:07:35] Então, por isso que essa diferença de desempenho de linguagens acaba não fazendo tanta diferença, assim, no ambiente de produção, tá?
[00:07:43] Tem casos que, realmente, vai fazer alguma diferença, mas, no geral, não vai ser tão relevante.
[00:07:48] Então, por isso que eu considero como um mito, né, que linguagem tal é lenta.
[00:07:51] Provavelmente, a lentidão está muito mais relacionada à forma como a gente está fazendo essas chamadas I.O.
[00:07:57] e à forma como a gente está estruturando a nossa arquitetura, de maneira geral, do que a linguagem em si.
[00:08:02] Então, é por isso que eu considero como um mito essa simples comparação entre linguagens.
[00:08:06] Uma é mais lenta, outra é mais rápida, tá bom?
[00:08:08] Apesar de, na prática, algumas serem mais rápidas e outras serem mais lentas, de fato.
[00:08:12] Mas, geralmente, isso não vai ser tão relevante quando a gente pensa em aplicações rodando no ambiente de produção,
[00:08:17] que são ambientes mais complexos ali, onde a gente interage com vários outros sistemas,
[00:08:21] enfim, faz operações mais complexas.
[00:08:23] Então, por isso eu considero esse ponto um mito.
[00:08:25] Então, esse é o primeiro ponto.
[00:08:28] Segundo ponto que eu considero como um mito.
[00:08:30] Microsserviços são melhores do que monolitos.
[00:08:33] Ou, ao contrário, mais modernamente, ultimamente, o pessoal tem falado que,
[00:08:36] não, monolitos são melhores do que microserviços e tal.
[00:08:39] Então, eu considero isso como um mito porque, assim, por bastante tempo, vamos dizer assim,
[00:08:45] eu considerei bastante como monolitos sendo melhores do que microserviços.
[00:08:50] Eu considero mais simples, de maneira geral, e tal, e, de fato, tem um fundo de verdade nisso.
[00:08:56] Mas a verdade mesmo é que vai depender muito de como a gente vai precisar estruturar a nossa aplicação
[00:09:03] para resolver os problemas em produção.
[00:09:05] A gente precisa ter em mente que o papel de engenheiro de software é basicamente dividido em duas partes.
[00:09:12] A primeira parte é a gente conseguir criar as nossas soluções o mais rápido possível para conseguir resolver os problemas de negócio.
[00:09:19] Então, velocidade aqui.
[00:09:20] E o segundo ponto, o segundo pilar de um engenheiro de software, aquele que a gente precisa se apoiar, é em estabilidade.
[00:09:29] Então, aquilo que a gente entrega precisa gerar valor em produção de forma contínua e, de preferência, ininterrupta pelo maior tempo possível.
[00:09:38] Ou seja, a qualidade vai fazer diferença e tal.
[00:09:40] Mas, no geral, a palavra estabilidade, ela descreve melhor esse pilar.
[00:09:45] Então, velocidade por um lado e estabilidade por outro.
[00:09:48] Então, quando a gente…
[00:09:50] Quando a gente pensa em resolver um problema, a gente tem que pensar nesses dois pilares ao mesmo tempo.
[00:09:54] Então, é importante a gente ter uma certa velocidade de entrega e também uma certa estabilidade no ambiente de produção.
[00:09:59] E, a depender do que a gente estiver criando, a gente consegue ganhar mais velocidade se a gente tiver o código mais autocontido,
[00:10:07] no mesmo lugar, seguindo talvez uma regra mais simples, enfim.
[00:10:10] Então, talvez, nesse caso, monolitos vão ajudar muito a gente.
[00:10:13] Então, geralmente, inclusive, a gente dá preferência a usar monolitos quando a gente está no começo, enfim, de vida de uma aplicação.
[00:10:20] Então, a gente está criando ali do zero, talvez uma startup que está começando agora.
[00:10:23] A gente cria com monolito, que geralmente é mais fácil começar por ali.
[00:10:27] Agora, ao longo do tempo, a gente pode se deparar com problemas, com dificuldades ali,
[00:10:31] que naturalmente vão jogar a gente para a gente usar, enfim, mais o conceito de microserviços,
[00:10:37] ou até, de maneira geral, nem gosto tanto do termo microserviços.
[00:10:40] Eu prefiro mais falar sobre sistemas distribuídos.
[00:10:43] Então, a gente vai acabar sendo jogado para o lado de criar sistemas distribuídos,
[00:10:48] porque ele vai ajudar a gente a ter uma estabilidade.
[00:10:50] Melhor, porque a falha, em um lugar, não necessariamente vai parar o sistema todo.
[00:10:54] A gente não vai ter, necessariamente, um ponto único de falha.
[00:10:57] Então, a gente vai ganhando alguma, alguns superpoderes, vamos dizer assim, né?
[00:11:00] Seguindo para os sistemas distribuídos, em detrimento ao nosso monolito.
[00:11:04] Mas, ao mesmo tempo, a gente vai aumentar a complexidade do sistema como um todo e tal.
[00:11:08] As interações que antes aconteciam localmente, agora elas vão ter que passar pela rede.
[00:11:13] Então, a gente talvez precise, sei lá, se comunicar por filas, ou por eventos, ou por arquivos, dependendo do caso.
[00:11:19] Então…
[00:11:20] Isso pode tornar a arquitetura mais complexa, processos que antes eram rápidos, eles passam a se tornar lentos.
[00:11:26] Então, existem, vamos dizer assim, trade-offs de um e de outro.
[00:11:29] Geralmente, para a gente começar, é mais fácil começar com monolito.
[00:11:32] Mas, é muito interessante que a gente já faça esse monolito, se preparando para uma eventual separação no futuro.
[00:11:39] Não de uma forma exagerada, mas se a gente conseguir minimamente isolar os componentes
[00:11:44] e criar contratos entre esses componentes dentro do nosso monolito, já facilita bastante.
[00:11:50] Para a gente poder evoluir esse sistema para microserviços, ou para sistemas distribuídos, mais tarde.
[00:11:55] Então, não é que um seja melhor do que o outro, é que, na verdade, isso depende muito do momento de empresa que a gente está,
[00:12:02] do nível de escalabilidade que a gente precisa, talvez, numa parte específica do sistema e tal.
[00:12:08] Eu vou dar um exemplo aqui de uma empresa que eu passei, obviamente, não vou falar qual empresa foi e qual sistema foi,
[00:12:15] mas eu passei por uma empresa onde, nessa empresa, a gente tinha um monolito gigante,
[00:12:20] gigantesco, e, basicamente, assim, boa parte da empresa, ou quase toda a empresa,
[00:12:25] estava apoiada em cima desse monolito, em um banco de dados também.
[00:12:29] Então, é uma instância do banco de dados, que vem com réplica e tal, mas é um banco de dados centralizado também, e por aí vai.
[00:12:36] E, em algum momento ali do ano, isso acontecia anualmente, a gente precisava lançar um serviço,
[00:12:44] que esse serviço, ele era extremamente acessado, então, vamos dizer assim, a gente sofreu uma carga muito grande
[00:12:50] de acessos durante um período curto de tempo, e, com isso, a gente colocando, vamos dizer assim,
[00:12:56] esse endpoint novo dentro desse monolito, o que acontecia é que a gente precisava escalar,
[00:13:02] e escalar significava gastar muito mais dinheiro, porque o monolito era tão grande, mas tão grande,
[00:13:07] que qualquer nova instância que a gente fosse subir, isso gerava um custo enorme para a empresa.
[00:13:12] Então, nesse caso, a gente tinha um caso típico que a gente ouve falar de dificuldade de escala, não porque era necessariamente difícil escalar,
[00:13:20] mas porque era muito caro a gente escalar. Então, para esse caso específico, talvez, olhando em retrospecto,
[00:13:25] fazia muito mais sentido, ou faria muito mais sentido a gente criar um serviço separado, pequeno,
[00:13:30] que fizesse aquela operação específica, do que necessariamente colocar esse serviço dentro do nosso monolito.
[00:13:36] Claro que a gente poderia usar técnicas aqui de caching, de talvez desnormalização dos dados, enfim,
[00:13:43] talvez separar os dados desse endpoint em outro banco de dados, enfim, que fosse um pouco mais otimizada
[00:13:50] para o uso, mas eu não vou entrar tanto nesse mérito. O ponto aqui é, talvez, nesse caso, a gente tivesse muitos benefícios
[00:13:54] em separar essa parte específica do sistema em um serviço separado, ou em um, entre aspas, microserviço, vamos chamar aqui.
[00:14:01] Então, existem benefícios, de fato, a gente usar serviços separados ali, a depender da nossa aplicação.
[00:14:08] Mas, de maneira geral, é interessante a gente começar com monolitos que sejam estruturados de uma forma que minimamente facilitem a separação no futuro,
[00:14:17] mas que a gente consiga tirar proveito também dos microserviços mais para frente, dos sistemas distribuídos, de maneira geral, mais para frente.
[00:14:25] O que eu recomendo, de maneira geral, é comece com o monolito, tá? Se for uma aplicação simples, se você entender que ela vai ter um nível de escala,
[00:14:32] que você consegue rodar isso no monolito, massa, começa com o monolito, e conforme você for sentindo dor, ou a empresa, os engenheiros
[00:14:39] forem sentindo dor de trabalhar naquele monolito, que, de fato, esse monolito vai sendo quebrado ali em serviços menores.
[00:14:46] Então, na minha visão, precisa ter uma dor associada para a gente fazer esse tipo de mudança.
[00:14:51] Porque, em geral, quando a gente migra, ou a gente transaciona, ou evolui para microserviços, isso significa, quase que necessariamente, que a gente vai ter uma complexidade maior no sistema como um todo.
[00:15:03] Então, é muito mais fácil a gente fazer uma chamada local de uma função do que a gente, por exemplo, ter que fazer N chamadas HTTP para uma API, um endpoint que está separado ali,
[00:15:12] vai ter que acessar a rede, vai ficar muito mais lento.
[00:15:14] A confiabilidade da chamada vai ser maior.
[00:15:16] Vai ser menor, porque eu vou estar acessando a rede.
[00:15:18] Então, algumas chamadas vão dar falha ali, muito mais do que, por exemplo, acontecer se eu simplesmente chamasse o banco de dados ou uma função local.
[00:15:25] Então, é algo que a gente precisa ter em mente.
[00:15:27] A complexidade aumenta conforme os sistemas ficam mais distribuídos, mas a gente também tem alguns outros benefícios, especialmente a parte de escalabilidade.
[00:15:35] Em alguns casos, vai ficar mais fácil.
[00:15:37] Ou então, o nível de serviço tende a aumentar, dependendo de como esses serviços estiverem estruturados.
[00:15:43] Enfim, a gente tem alguns benefícios ali também.
[00:15:46] Então, é muito pensar em que momento você está, que a sua aplicação está, e se faz sentido ela estar numa arquitetura mais microserviços ou mais de monolito.
[00:15:56] Então, não é que uma está errada e a outra está certa, mas é muito mais na linha de como que eu faço para estruturar o meu sistema para resolver melhor os problemas de negócio
[00:16:06] do ponto de vista de gerar mais velocidade de entrega, gerar uma velocidade de entrega boa, ao mesmo tempo que eu consigo manter uma estabilidade boa do sistema como um todo em produção.
[00:16:15] Porque a gente precisa ter o tempo todo em mente.
[00:16:17] A otimização, ela precisa estar em velocidade de desenvolvimento e estabilidade no ambiente de produção.
[00:16:23] Então, esse é o grande resumo, vamos dizer assim, da responsabilidade de engenheiros de software.
[00:16:29] E é nisso que a gente tem que se apoiar quando a gente vai tomar uma decisão ali, enfim, vai escolher algum trade-off em relação a qual metodologia a gente vai usar para desenvolver uma aplicação.
[00:16:38] Então, por isso que eu considero como um mito de microserviços serem melhores do que monolitos, ou ao contrário, monolitos serem melhores do que microserviços.
[00:16:45] Uns são mais complicados que outros em algumas situações e está tudo bem.
[00:16:48] A gente vai escolher o que faz mais sentido para cada situação, dando preferência, se possível, para começar com aplicações mais próximas de um monolito.
[00:16:58] Então, esse é o segundo mito que eu considero, tá bom?
[00:17:03] Terceiro mito, bancos de dados SQL não escalam.
[00:17:07] Então, a gente provavelmente já ouviu falar bastante isso aí ao longo da carreira.
[00:17:11] Não sei se aconteceu contigo, mas eu já ouvi falar bastante sobre isso.
[00:17:15] Isso é uma meia-verdade também, vamos dizer assim, né?
[00:17:18] Então, existe um fundo de verdade, de fato, nisso, mas não é uma verdade necessariamente absoluta e tal.
[00:17:24] O que eu vejo muito acontecer é o uso de banco de dados SQL e, para ser bem específico aqui, quando eu falo de banco de dados SQL, eu estou falando de banco de dados tradicionais, relacionais.
[00:17:33] Então, poxa, iria mais SQL, geralmente, quando a gente fala ali, ou MariaDB, vai, quando a gente pensa ali em aplicações usando soluções open source.
[00:17:42] Então, geralmente, essas são as escolhas ali.
[00:17:45] Eu vou pensar de mais SQL e não ser mais open source, mas não vou entrar muito nesse mérito.
[00:17:48] Mas, geralmente, essas são as nossas escolhas ali.
[00:17:51] Então, por que a galera fala que bancos de dados não escalam?
[00:17:55] Pelo menos, o que eu tenho visto mais ultimamente, né?
[00:17:58] Geralmente, isso é muito falado, porque bancos de dados SQL, geralmente, dependem, obviamente, de algum tuning ali do nosso lado.
[00:18:07] Então, talvez a gente esteja fazendo, por exemplo, uma consulta e essa consulta não está indexada.
[00:18:11] Então, por isso que ele não está tendo um desempenho bom.
[00:18:14] Tudo bem, faz parte da estrutura do banco de dados.
[00:18:16] A gente precisa, minimamente, otimizar esse banco de dados para que a gente consiga usar.
[00:18:20] Então, antes de falar que não escala, é importante a gente ter noção de, será que eu estou otimizando a solução que eu estou criando para o meu caso de uso?
[00:18:29] Enfim, acho que esse é o primeiro ponto para a gente levar em consideração.
[00:18:33] Um outro ponto, até dando um passo atrás aqui, que, às vezes, a gente não pensa tanto quando a gente está falando é, o que significa escalar do meu ponto de vista?
[00:18:43] Então, beleza, não escala, mas o que significa não escalar aqui?
[00:18:47] É não escalar escrita? É não escalar leitura?
[00:18:50] É não escalar, talvez, para eu tenho muitas requisições dentro de um curto período de tempo, eu preciso responder isso rápido e ele não está escalando para isso?
[00:18:58] É não ser rápido escalar? O que significa não escalar aqui nesse contexto?
[00:19:02] Porque a resposta para essa pergunta vai dizer muito se a gente consegue solucionar isso com o mesmo banco de dados relacional que a gente está usando,
[00:19:11] ou não.
[00:19:12] Ou se a gente vai precisar de uma nova solução de banco de dados, ou se a gente vai precisar de alternativas ali para ajudar a gente.
[00:19:18] Então, a resposta para essa pergunta é muito importante.
[00:19:21] Então, não é simplesmente falar não escala, porque isso é muito abrangente.
[00:19:24] A gente precisa ser mais específico no que exatamente aquilo não escala.
[00:19:28] Então, o que significa não escalar na nossa situação específica?
[00:19:32] Então, essa é uma pergunta importante para ser feita.
[00:19:35] Dito isso, existem várias coisas que a gente pode fazer em um banco de dados relacional,
[00:19:41] como LCL, MyLDB, Postgre, enfim, por aí vai, para a gente conseguir escalar.
[00:19:45] Então, um caso bobo aqui, mas que faz muita diferença, é a gente ter, por exemplo, um connection pool.
[00:19:51] Porque só o fato da gente estar o tempo todo tendo que fazer conexão com o banco para fazer a consulta e tal.
[00:19:56] Então, imagina, todo acesso ao banco eu vou ter que fazer a conexão, faço a consulta, depois eu fecho a conexão, depois abro a consulta.
[00:20:02] Isso aí gera um overhead muito grande. Então, se a gente tem um simples pool de conexões, isso já ajuda bastante.
[00:20:09] Pega a conexão, já faço a consulta, então eu tenho menos overhead.
[00:20:14] Então, algo tão bobo quanto isso já pode ajudar bastante em termos de desempenho.
[00:20:18] Outras coisas que a gente pode fazer, aqui muito do ponto de vista da leitura, em primeiro lugar.
[00:20:23] Primeiro, criar índices. Então, se a minha leitura está lenta, será que eu tenho todos os índices que eu deveria para conseguir fazer essa consulta?
[00:20:30] Será que eu estou analisando correto?
[00:20:32] Se a gente, por exemplo, pedir para o próprio banco de dados explicar aquela consulta para a gente, existem comandos em cada banco de dados para a gente conseguir fazer.
[00:20:39] A gente consegue entender se a gente poderia estar usando um índice ou se aquele índice que a gente criou está sendo usado naquela consulta que a gente está fazendo.
[00:20:46] Então, se a gente tem uma consulta de leitura que é lenta, a primeira coisa que a gente deveria estar olhando é para índice.
[00:20:51] Cara, será que essa busca, eu estou usando o índice para conseguir fazer isso?
[00:20:55] Porque se eu não estou, pensa que o banco de dados tem que passar por todos os registros para a gente conseguir encontrar aquele registro que a gente estava buscando dentro da nossa consulta.
[00:21:04] Mas agora, se estiver indexado, a chance de que a consulta seja muito maior.
[00:21:09] Ou seja, que a consulta seja mais rápida, em ordens de magnitude mais rápida.
[00:21:11] Então, a primeira pergunta que eu devo me fazer é, será que eu estou indexando tudo como eu deveria indexar?
[00:21:15] Então, esse é o primeiro ponto que ajuda em termos de leitura.
[00:21:18] O segundo é algo tão simples quanto um cache.
[00:21:22] É importante a gente ter em mente aqui que caches são importantes em termos de ganho de desempenho.
[00:21:28] Então, quando eu falo em cache, esse cache pode até estar no banco de dados, mas nesse caso eu estou considerando o cache fora do banco de dados.
[00:21:34] Eles podem ser interessantes.
[00:21:38] O problema do cache é que os dados, eles não necessariamente vão estar quentes ali.
[00:21:42] O que significa que talvez algo tenha mudado no banco de dados e isso não tenha sido refletido no cache ainda.
[00:21:48] Então, existe um certo risco quando a gente vai usar o cache e obviamente a gente precisa levar isso em consideração quando a gente está criando a nossa aplicação.
[00:21:56] E qual pode ser o tamanho do problema para a gente estar usando um cache?
[00:21:59] Mas, de maneira geral, existem dados ali que mudam com pouca frequência.
[00:22:04] Então, para esses dados, pelo menos para eles, a gente em tese conseguiria usar um cache.
[00:22:08] Para buscar o resultado direto no cache, ao invés de ter que fazer consultas o tempo todo no banco de dados.
[00:22:13] Porque, geralmente, quando a gente fala de cache, a gente está falando de cache em memória.
[00:22:17] E acessar a memória é muito mais rápido do que a gente acessar o disco no banco de dados.
[00:22:21] Até porque ele vai ter que analisar query, fazer consulta em disco, então ele vai ter que acessar.
[00:22:25] Mesmo que seja um SSD, ainda assim, a consulta ela tende a ser muito mais lenta quanto do overhead do banco de dados,
[00:22:32] do que a gente fazer uma consulta usando chave-valor num Redis, por exemplo, ou enfim, alguma outra ferramenta.
[00:22:38] Para a gente salvar em cache.
[00:22:40] Então, cache ajuda demais.
[00:22:43] Então, onde der para a gente usar cache, a gente poderia usar para a gente evitar o overhead de usar o banco de dados.
[00:22:48] Isso já vai dar, talvez, performance suficiente para a gente entregar para o nosso usuário na ponta.
[00:22:53] Então, cache é uma segunda opção aí, caso a gente precise, entre aspas, escalar leitura do banco de dados.
[00:22:59] Apesar de a gente não usar direto o banco, mas é como se estivesse usando.
[00:23:03] Então, a gente está pensando em escalar leitura aqui, especificamente, não necessariamente pegar o dado mais quente,
[00:23:08] mas o dado possível.
[00:23:09] Então, essa é uma segunda forma da gente conseguir ter um ganho aí, em termos de leitura.
[00:23:15] O terceiro, que é pouquíssimo falado, é a desnormalização.
[00:23:20] Então, um dos problemas, uma das dificuldades que a gente tem quando a gente está fazendo consultas de leitura
[00:23:25] em banco de dados relacional, é que a gente faz uma quantidade razoavelmente grande de joins ali em algumas consultas.
[00:23:31] Então, fazendo joins, a gente está pegando dados de várias tabelas diferentes.
[00:23:35] Isso pode tornar a consulta mais lenta.
[00:23:38] Se os dados estejam indexados e tal, é claro que os índices vão ajudar.
[00:23:41] Mas, ainda assim, as consultas podem ficar mais lentas, a depender da quantidade de joins que a gente faz.
[00:23:47] Então, para evitar tantos joins, a gente pode desnormalizar.
[00:23:51] Então, a gente tem essa possibilidade no banco de dados.
[00:23:53] Então, a gente pode, por exemplo, pegar dados que estavam em tabelas diferentes e colocar na mesma tabela no banco de dados.
[00:24:00] Talvez isso possa ser interessante para a gente.
[00:24:02] Ou a gente pode, por exemplo, criar uma view materializada, agregando os valores,
[00:24:07] para facilitar a nossa consulta depois.
[00:24:10] Eu não sinceramente recomendo que a gente faça isso com frequência, com muita frequência,
[00:24:15] mas é uma alternativa que a gente pode considerar.
[00:24:17] Eu já vi sendo usada isso em produção e funciona.
[00:24:19] Funciona relativamente bem no ambiente de produção a gente fazer algo desse tipo.
[00:24:23] Isso ajuda também a escalar leitura no nosso banco de dados.
[00:24:27] Então, é uma alternativa que a gente pode levar em consideração.
[00:24:30] Mais uma alternativa para a gente também levar em consideração no ambiente de produção.
[00:24:34] Eu acho que, inclusive, a gente deveria usar isso com uma certa frequência, que é o uso de réplicas.
[00:24:39] Então, do mesmo jeito que a gente vai ter um banco de dados ali, que vai ter, vamos dizer assim, uma instância de escrita,
[00:24:44] a gente pode ter N réplicas de leitura.
[00:24:47] Isso facilita bastante o ganho de desempenho, porque agora a gente não está mais centralizado em uma instância
[00:24:55] para a gente conseguir fazer todas as leituras de lá.
[00:24:57] A gente pode distribuir essas leituras em N instâncias diferentes.
[00:25:01] Então, pensa que os dados vão ser escritos,
[00:25:04] em uma instância.
[00:25:05] Então, todas as atualizações e inserções vão estar em uma instância específica e remoções também.
[00:25:13] E esses dados vão ser replicados para as réplicas.
[00:25:17] Então, as leituras vão ser feitas nas réplicas.
[00:25:19] Claro que aqui a gente pode ter, por exemplo, existe um trade-off aqui.
[00:25:23] Então, isso não é de graça, não.
[00:25:24] E o trade-off é o tempo de propagação desses dados, vamos dizer assim, da instância que é líder para as réplicas.
[00:25:31] Então, a gente tem um replication lag aí, que ele pode ser curto,
[00:25:34] pode ser um pouco maior.
[00:25:35] Hoje em dia, geralmente, a gente tem um bom desempenho com isso,
[00:25:39] mas a gente pode ter uma diferença aí entre eu inserir agora
[00:25:43] e o tempo que, de fato, esse registro vai estar disponível para mim nas minhas réplicas.
[00:25:48] Então, pode ser que eu faça, por exemplo, a leitura em uma réplica
[00:25:51] e eu conseguir pegar o dado, mas se eu fizesse a leitura de outra réplica,
[00:25:54] eu não pegaria ele mais atualizado, porque eu não conseguir replicar os dados para lá ainda.
[00:25:58] Então, existe um trade-off aí quando a gente fala de réplicas,
[00:26:01] mas réplicas ajudam demais a gente a ganhar desempenho.
[00:26:04] Em relação à leitura no banco de dados,
[00:26:06] porque a gente para de concentrar leitura e escrita em uma só instância
[00:26:09] e a gente distribui isso de alguma forma.
[00:26:11] Distribuir as leituras, aqui no caso, a escrita ainda não,
[00:26:13] ainda vai estar centrada em uma instância só.
[00:26:16] E uma última forma aqui, só para simplificar, para a gente conseguir escalar,
[00:26:21] nesse caso, leitura, é a gente usar alguma solução de data warehouse.
[00:26:25] Aqui eu já estou falando de usar um banco de dados diferente, vamos dizer assim.
[00:26:28] Então, enquanto em produção a gente está usando, por exemplo, um Postgre,
[00:26:32] talvez a gente esteja usando uma outra solução,
[00:26:34] como o Data Warehouse, como por exemplo, sei lá, Snowflake, existem N soluções.
[00:26:38] O Google BigQuery, enfim, existem N situações aí, N opções de banco de dados,
[00:26:42] onde a gente poderia usar como Data Warehouse.
[00:26:45] São bancos específicos para, vamos dizer assim, consultas analíticas,
[00:26:49] aquelas consultas que são lentas, que demoram, sei lá, meia hora para rodar,
[00:26:53] uma hora para rodar, que pegam dados de muitas tabelas diferentes, enfim.
[00:26:59] São soluções específicas para isso.
[00:27:01] Então, se a gente, por exemplo, tiver muitas pessoas ali na empresa
[00:27:04] fazendo consultas analíticas no banco de dados de produção, ainda que seja em uma réplica,
[00:27:09] talvez seja melhor usar uma solução para, enfim, buscas analíticas, especificamente,
[00:27:14] que é um Data Warehouse, alguma solução de Data Warehouse.
[00:27:17] Então, tudo isso ajuda a gente a escalar, vamos dizer assim, entre aspas,
[00:27:21] a depender do que a gente está considerando como escalar aqui, leituras em banco de dados,
[00:27:25] e que provavelmente vão ser o suficiente para a maior parte das aplicações que a gente cria.
[00:27:30] Aí, beleza, aí talvez você esteja pensando assim, ah, não, tipo,
[00:27:33] talvez o banco de dados relacionais, o problema deles não é tanto a leitura,
[00:27:37] mas é mais a escrita e tal, então é difícil escalar a escrita em banco de dados relacionais.
[00:27:41] E, de fato, existe uma certa complexidade da gente escalar a escrita no banco de dados relacional.
[00:27:47] O primeiro motivo para isso é que, geralmente, quando a gente fala de banco de dados relacional,
[00:27:51] um Postgre, uma SQL, uma RDB, a gente está falando de uma instância que a gente vai ter de escrita, tá bom?
[00:27:58] Então, a gente vai ter um líder. Até é possível a gente ter bancos de dados distribuídos,
[00:28:03] enfim, com vários líderes, mas a gente começa a entrar numa seara aqui de uma complexidade que é relativamente grande, tá bom?
[00:28:10] Então, eu não necessariamente recomendo que você faça esse tipo de coisa.
[00:28:13] Você pode até fazer, existe essa possibilidade, mas, em geral, não é o que é feito.
[00:28:17] Quando a gente fala de banco de dados relacional tradicional, vamos dizer assim,
[00:28:20] a gente pensa em uma instância que vai ser a líder.
[00:28:23] E, claramente, ela vai ser uma instância que vai trazer alguma dificuldade ali em termos de escalar a escrita,
[00:28:29] por conta de I.O.U. também. Então, existe um limite que o disco suporta
[00:28:33] de escritas ali nele. Então, existe essa dificuldade aí que pode acontecer.
[00:28:39] Então, a gente pode ter essa dificuldade de I.O.U. O segundo motivo é gestão de índices.
[00:28:43] Então, a gente pode ter, por exemplo, uma quantidade, talvez, relativamente grande de índices,
[00:28:49] ou talvez uma tabela que tem, talvez, até poucos índices, mas uma tabela que eu tenho muitas escritas nela.
[00:28:55] O que significa que esses índices vão ser recomputados frequentemente.
[00:28:59] E existe um custo para o recálculo desse índice. E esse custo vai afetar
[00:29:03] o desempenho na escrita que, claramente, vai dificultar também em termos de escala desse banco de dados.
[00:29:10] Então, existe esse custo ali. E o terceiro são as constraints.
[00:29:14] Bancos de dados relacionais, um dos grandes benefícios, inclusive, dos bancos de dados relacionais,
[00:29:19] são as constraints. Então, se uma coisa muda de um lado, eu garanto que ela vai mudar do outro também.
[00:29:25] Então, existe essa relação forte entre registros diferentes, tabelas diferentes, talvez até na mesma tabela.
[00:29:30] Eu tenho uma constraint ali de unique, por exemplo, um índice unique, alguma coisa assim,
[00:29:34] onde eu não posso criar o mesmo dado ali duplicado.
[00:29:38] E, enfim, esse é um grande benefício dos bancos de dados relacionais, de bancos de dados SQL.
[00:29:44] E isso dificulta também em termos de escalar a escrita, porque eu tenho que, toda hora, estar verificando
[00:29:49] se eu estou ferindo ou não alguma constraint. Ou, em outras palavras aqui, toda a parte de acid ali do banco de dados,
[00:29:55] ela dificulta, até certo ponto, a escrita também em escala.
[00:30:01] Então, de fato, escrita em escala, em bancos de dados relacionais, são um pouco mais complicadas.
[00:30:06] Porém, existem formas de a gente tentar contornar isso aí, a depender da escala que a gente está falando.
[00:30:12] Então, até um certo nível de escala, a gente consegue usar relativamente bem um banco de dados relacional.
[00:30:18] Talvez, a partir de um certo ponto de escala, vai ficar muito difícil realmente.
[00:30:22] Mas, por exemplo, algumas alternativas que a gente pode ter para escalar escritas em um banco de dados relacional.
[00:30:28] Uma coisa que a gente pode fazer, por exemplo, é usar o conceito de batching.
[00:30:34] Então, é muito mais, por exemplo, custoso para um banco de dados fazer várias escritas individuais
[00:30:40] do que a gente fazer, talvez, várias escritas de uma vez só. Então, fazer uma inserção de, sei lá, 100 registros ao mesmo tempo.
[00:30:48] Então, é muito mais fácil fazer uma inserção com 100 registros simultâneos, ao invés de fazer 100 inserções, uma de cada vez.
[00:30:54] Então, essa é uma forma que a gente consegue otimizar.
[00:30:58] Outra forma é a gente espalhando isso ao longo do tempo.
[00:31:01] Então, por exemplo, a gente pode pensar naquele cenário de
[00:31:05] Ah, será que eu preciso fazer todas as inserções ao mesmo tempo aqui?
[00:31:10] Vamos dizer que um usuário mandou gerar, sei lá, um relatório ou alguma coisa assim.
[00:31:14] Cara, será que eu preciso fazer inserção disso aí? Vamos dizer que são várias inserções do banco.
[00:31:19] Preciso fazer todas as inserções agora ou eu posso, talvez, colocar isso para ser feito diluído, vamos dizer assim, ao longo do tempo.
[00:31:26] Colocar isso em uma fila e, aos poucos, ir processando essa escrita no meu banco de dados.
[00:31:30] Porque se eu conseguir fazer isso, cara, excelente. Então, eu faço isso para conseguir diluir essa escrita ao longo do tempo.
[00:31:35] Então, a gente consegue alternativas ali para ajudar, enfim, em relação a escalar a escrita em um banco de dados relacional.
[00:31:42] Acho que não só no relacional, mas nesse caso, especificamente, no relacional.
[00:31:45] Mas eu vou colocar um cenário aqui para a gente, aos pouquinhos, entender como que a gente consegue melhorar o desempenho aqui de um cenário…
[00:31:55] Não vou dizer que é tão típico assim, mas é um cenário que pode acontecer.
[00:31:58] Então, imagina que a gente vai processar um arquivo e, nesse arquivo, tem um milhão de linhas.
[00:32:04] Então, talvez um parceiro me passou, uma empresa externa e tal, estou consumindo de alguma fonte ali, um arquivo com um milhão de linhas nele.
[00:32:11] E cada linha dessa vai gerar uma inserção no nosso banco de dados.
[00:32:15] Então, eu vou fazer um insert lá numa tabela para cada linha que está nesse arquivo.
[00:32:18] Então, vamos imaginar esse cenário aqui, cenário hipotético.
[00:32:21] Beleza, como que a gente consegue fazer isso funcionar ali no mente de pessoas?
[00:32:25] De produção, vai.
[00:32:26] Uma forma talvez ingênua da gente começar, uma forma simples da gente começar é…
[00:32:31] Eu vou abrir esse arquivo, eu vou pegar uma linha desse arquivo.
[00:32:35] Talvez eu abra esse arquivo, vamos dizer assim, de pouco em pouco e tal, porque pode ser um arquivo muito grande.
[00:32:38] Não vou entrar tanto nesse mérito, enfim, de como a gente consegue otimizar essa parte ainda.
[00:32:41] Mas vamos dizer que eu abro esse arquivo, pego uma linha, peguei essa linha.
[00:32:44] Eu vou fazer um loop para acessar todas as linhas do arquivo.
[00:32:48] Para cada linha que eu acesso, pego essa linha, faço uma query no meu banco de dados de escrita e salvo esse dado no meu banco.
[00:32:54] Beleza.
[00:32:55] Então, essa é, vamos dizer assim, uma forma da gente conseguir fazer.
[00:33:00] Provavelmente, esse processo vai ser um pouco custoso para o banco de dados.
[00:33:05] Então, a gente vai ter escrita o tempo inteiro ali no banco.
[00:33:08] Como que a gente conseguiria otimizar, vamos dizer assim, essa escrita dessas linhas do arquivo do banco de dados?
[00:33:14] Uma segunda forma é, ao invés de eu inserir linha por linha no banco de dados,
[00:33:18] se eu conseguir usar o conceito de batching aqui, que eu acabei de comentar, eu posso agilizar.
[00:33:24] Ao invés de inserir uma linha por vez, eu insiro, sei lá, 100 linhas por vez, por exemplo.
[00:33:28] Então, eu acumulo 100 linhas ali, talvez em memória, enfim.
[00:33:31] E faço uma consulta para o banco de dados, inserindo essas 100 linhas ao mesmo tempo.
[00:33:35] Massa.
[00:33:36] E, provavelmente, assim já tornaria, vamos dizer assim, esse processo muito mais rápido do que o processo anterior, inserindo um por vez.
[00:33:42] Mas será que tem como a gente otimizar ainda mais isso aqui?
[00:33:45] Sim, tem como a gente otimizar.
[00:33:46] Então, vamos pensar, por exemplo, pegando um conceito de transações aqui de banco de dados.
[00:33:51] Quando a gente faz escritas de banco de dados dentro de transações,
[00:33:54] ou múltiplas escritas dentro de transações,
[00:33:57] essas escritas tendem a ser mais rápidas do que se a gente fizesse essas escritas individualmente.
[00:34:03] Então, nesse caso, eu estaria inserindo 100 registros por vez, por exemplo.
[00:34:07] Pegando ali do arquivo e tal, enfim, 100 linhas, enfim,
[00:34:10] fazendo 100 inserções dentro de uma mesma consulta, de um mesmo insert no banco de dados.
[00:34:15] Mas se eu colocar dentro de uma transação, talvez, 10 agrupamentos dessas inserções,
[00:34:19] isso vai ser mais rápido do que executar 10 inserts em sequência.
[00:34:24] Então, se eu colocar dentro de uma transação, já tem um ganho aí, mais um ganho de desempenho, tá bom?
[00:34:29] Fazendo essas escritas de banco de dados.
[00:34:31] Beleza. Tem como otimizar ainda mais do que isso?
[00:34:34] Provavelmente tem, a depender aqui muito um pouco da linguagem que a gente estiver usando, tá bom?
[00:34:39] Algumas linguagens facilitam um pouco mais, outras, enfim, apresentam um pouco mais de dificuldade.
[00:34:44] Aí, talvez volte para o primeiro ponto que eu comentei aqui, no primeiro mito.
[00:34:47] Como que a gente conseguiria otimizar isso ainda mais?
[00:34:50] Então, por exemplo, usando golang, usando goroutines, né?
[00:34:54] Do golang, da linguagem Gol.
[00:34:56] Mas, enfim, existem alternativas aí em outras linguagens também.
[00:34:59] A gente poderia, por exemplo, usar ali uma forma de concorrência para, ao invés de eu fazer uma transação por vez, né?
[00:35:08] Com as inserções ali dentro da transação.
[00:35:10] Eu poderia abrir goroutines separadas, para cada goroutine processar ali, sei lá, cada uma processa uma transação separada.
[00:35:17] E eu posso ter, sei lá, 10 goroutines rodando concorrentemente.
[00:35:21] Porque pensa aqui, que eu estou falando de operações de I.O., tá bom?
[00:35:23] De operações de I.O.
[00:35:24] Então, eu tenho uma certa espera quando eu mando a requisição para o banco, até ele me responder o sucesso.
[00:35:30] Então, eu consigo usar concorrência aqui muito bem.
[00:35:32] Então, no caso, gol me ajudaria muito com goroutines.
[00:35:35] Mas, o mesmo poderia ser feito com Python, usando assim que I.O., com Node, né?
[00:35:39] Usando as prompts do Node.
[00:35:41] A gente só vai precisar de alguma forma de semáforo aqui para ajudar, para limitar essa concorrência, tá?
[00:35:46] Porque a gente não vai querer uma concorrência infinita aqui, porque senão a gente pode sobrecarregar muito banco de dados.
[00:35:51] Mas, enfim, a ideia se mantém.
[00:35:53] Então, aqui, a gente consegue usar algumas técnicas ali que ajudam a gente a conseguir ganhar desempenho de escrita no banco de dados.
[00:36:00] Então, não é porque um insert está lento que, necessariamente, isso significa que a gente vai ter que mudar de banco de dados.
[00:36:09] Talvez não seja necessário.
[00:36:10] A gente consegue usar técnicas aqui para conseguir tornar essas escritas mais rápidas, enfim, no banco de dados.
[00:36:17] E continuar usando esse banco, ao invés de partir para uma solução que provavelmente vai ser mais complexa usando um banco de dados.
[00:36:23] Que não seja SQL.
[00:36:25] Não é que a gente não deva usar outros bancos de dados, mas que existem vantagens de usar o banco de dados SQL.
[00:36:29] Então, se a gente conseguir manter, tendo um desempenho bom para a nossa aplicação, então por que a gente não manteria esse banco?
[00:36:35] Então, vale considerar essas alternativas aqui que eu comentei.
[00:36:37] E existem várias outras alternativas que eu não vou entrar tanto no mérito aqui, mas que esse vídeo não é sobre isso.
[00:36:43] Já gastei bastante tempo aqui falando sobre possibilidades de a gente ganhar desempenho ali em bancos de dados relacionais.
[00:36:52] Tanto em relação à leitura, quanto em relação à escrita.
[00:36:55] Então, enfim, para fechar esse mito aqui.
[00:36:57] Banco de dados, SQL ou relacionais não escalam.
[00:37:00] Sim, escalam, mas a gente precisa entender exatamente o que é escala.
[00:37:03] E quais são as alternativas que a gente tem para a gente conseguir escalar essas leituras e ou escritas no nosso banco de dados.
[00:37:10] Beleza?
[00:37:11] Então, enfim.
[00:37:12] Esse é o terceiro mito.
[00:37:14] E o quarto e último mito, esse talvez seja um pouco menos popular.
[00:37:18] Mas que eu entendi, assim, que quase é que se lembra.
[00:37:22] Que se tornou uma verdade já na nossa área.
[00:37:24] Que eu acho até um pouco lamentável, para ser bem sincero.
[00:37:27] Aquele famoso conceito de trunk-based development.
[00:37:31] O que seria esse conceito de trunk-based development?
[00:37:33] Deixa eu explicar aqui.
[00:37:34] Basicamente, quando a gente está lidando com versionamento de código, a gente pode ter várias ramificações ali.
[00:37:41] Várias branches, enfim.
[00:37:42] Para desenvolvimento de funcionalidades.
[00:37:44] Tem gente que usa por ambiente e tal.
[00:37:46] Então, uma branch para produção, uma branch para staging, por aí vai.
[00:37:49] A ideia do trunk-based development é que a gente…
[00:37:52] Simplifique tudo isso.
[00:37:54] E que a gente foque somente na branch que eles chamam de trunk aqui.
[00:37:58] Que seria a branch principal do nosso versionador.
[00:38:01] No caso, hoje em dia, a branch main do Git.
[00:38:05] Antigamente era a branch master do Git.
[00:38:07] Enfim, por aí vai.
[00:38:08] Então, a ideia é a gente conseguir centralizar tudo ou quase tudo nessa branch.
[00:38:14] O que não significa que a gente não vá ter outras branches.
[00:38:16] A gente pode ter outras branches.
[00:38:18] Mas essas branches, elas deveriam ter tempo de vida muito curto.
[00:38:22] E aqui começa a entrar um ponto onde talvez exista…
[00:38:26] Talvez uma…
[00:38:27] Não vou dizer uma discordância.
[00:38:29] Mas uma concordância não tão grande entre os pontos de vista sobre trunk-based development.
[00:38:33] O que significa uma branch que tem um tempo de vida curto?
[00:38:37] Para mim é muito claro que se uma branch dura seis meses ou mais…
[00:38:42] Cara, essa branch está muito longa.
[00:38:44] Mas agora, se ela dura uma semana, isso é curto o suficiente?
[00:38:47] Ou se ela dura dois dias, é curto o suficiente?
[00:38:50] Ou um dia, é curto o suficiente?
[00:38:52] Então, começa a existir uma certa diferença de visões aqui, tá bom?
[00:38:57] Acho que um ponto importante para a gente ter em mente é que a grande ideia da gente ter branch de curta duração
[00:39:03] é para a gente evitar, por exemplo, dificuldade com conflitos quando a gente for mergear.
[00:39:09] Ou dificuldade, por exemplo, da gente se distanciar muito da branch principal.
[00:39:12] Então, imagina que eu, sei lá, estou há seis meses desenvolvendo alguma coisa em uma branch.
[00:39:16] Se eu não pego os conteúdos da branch principal e trago para a minha branch, cara…
[00:39:20] A diferença provavelmente vai estar muito grande em relação à branch principal,
[00:39:23] porque outras coisas vão acontecendo ao longo do tempo, mais código vai aparecendo nessa branch principal.
[00:39:28] Então, essa é uma grande dificuldade que é relatada em relação à branch que tem longo tempo de duração.
[00:39:35] Inclusive, eu já passei por isso no momento da carreira.
[00:39:38] Isso foi na primeira equipe que eu trabalhei como engenheiro de software.
[00:39:41] Na época, a gente tinha uma branch de teste e uma branch de produção.
[00:39:46] E, de fato, ao longo do tempo, elas divergiram tanto, mas tanto,
[00:39:49] que já não era mais tão confiável a gente simplesmente começar um código a partir da branch de teste.
[00:39:55] Então, a gente precisava começar a partir da branch de produção, que eu já considero uma boa prática, inclusive.
[00:39:59] Mas, de qualquer forma, a gente tem essa desvantagem de poder ter essa divergência e tal, problemas de conflito depois.
[00:40:09] Uma outra dificuldade é quando a gente tem uma branch que dura bastante tempo, vamos colocar aqui, sei lá, um mês como bastante tempo.
[00:40:17] Eu não acho que um mês é tanto tempo assim.
[00:40:19] Mas vamos considerar que seja bastante tempo.
[00:40:21] Então, a gente tem essa branch que está ali há um mês.
[00:40:24] Quando a gente colocar esse código em produção, provavelmente a gente vai colocar bastante código em produção e não só um pouquinho.
[00:40:30] E existe, vamos dizer assim, quase que um consenso que quanto mais código a gente coloca ao mesmo tempo em produção, maior a probabilidade daquele código dar problema.
[00:40:39] Porque a gente está mudando muita coisa ao mesmo tempo.
[00:40:42] Do outro lado, olhando o lado oposto, se a gente coloca código, pouquinho código em produção, a chance de dar problema individualmente é menor.
[00:40:49] Porque a gente está colocando menos código em produção.
[00:40:51] Então, o risco é menor quando a gente faz mudanças menores.
[00:40:55] Então, talvez o principal ponto por trás do Trunk Based Development é justamente isso.
[00:40:59] A gente fazer pequenas entregas no ambiente de produção para a gente reduzir o risco dessas entregas e aumentar a estabilidade do nosso sistema de produção.
[00:41:07] Então, essa é a grande ideia.
[00:41:09] Agora, eu tenho a minha visão que talvez seja um pouco diferente disso.
[00:41:15] Primeiro, falando um pouquinho sobre a parte de conflitos.
[00:41:18] Tem muito tempo que eu não vejo conflitos que sejam, pelo menos nas equipes onde eu trabalhei.
[00:41:23] Conflitos que tenham sido relevantes a ponto da gente perceber que é muito ruim ter uma branch que dura tanto tempo aqui, porque os conflitos são muito grandes.
[00:41:31] Em geral, isso não é tanto um problema, porque na branch que a gente está trabalhando ali em paralelo, a gente pode pegar o que aconteceu na branch principal e trazer para a nossa branch.
[00:41:40] E se acontecer algum conflito, são pequenos conflitos ali que a gente vai resolvendo ao longo do tempo.
[00:41:44] Isso independente do tempo que a branch leva.
[00:41:46] Pode levar uma semana, um mês, um ano, não interessa tanto.
[00:41:50] Se a gente pegar essas mudanças e trazer para a nossa branch, então a gente corre muito menos esse risco de ter dificuldades de conflito.
[00:42:01] Então, conflito eu não acho que é um problema relevante, sendo bem sincero.
[00:42:04] Agora, um outro ponto que esse sim é mais relevante é, de fato, o ponto da gente colocar muito código em produção ao mesmo tempo e isso aumentar o risco daquela funcionalidade quebrar.
[00:42:14] Enfim, ou de alguma coisa quebrar no ambiente de produção.
[00:42:16] De fato, isso é uma verdade.
[00:42:18] Então, o que que, vamos dizer assim, proponentes da Trunk Based Development sugerem?
[00:42:22] Façam pequenas, ou branch que tem um curto tempo de duração, porque se ela tem um curto tempo de duração, a gente tem pouco código ali.
[00:42:28] E se tem pouco código ali, a chance dele quebrar em produção é menor.
[00:42:31] Mas se eu tenho pouco código, então talvez aquela funcionalidade que dependa de mais código, como que eu vou fazer para botar aquela funcionalidade em produção?
[00:42:39] Então, tem uma certa dificuldade.
[00:42:41] O que que é recomendado nesse caso?
[00:42:43] Se eu tenho uma funcionalidade que ela é relativamente grande, isso vai alterar bastante o código.
[00:42:47] Então, ao invés de você subir essa funcionalidade de uma vez para a produção, você faz pequenas alterações.
[00:42:53] Coloca essas pequenas alterações por trás de Feature Flags e você vai depoiar essa Feature Flag em produção desligada.
[00:43:00] Então, você vai ter um pedaço da funcionalidade rodando em produção desligada.
[00:43:06] Em princípio, essa ideia parece muito boa.
[00:43:09] Qual é a ressalva que eu tenho com essa ideia?
[00:43:11] Quando a gente começa a tirar muito proveito de Feature Flag, isso provavelmente vai tornar o nosso código mais complexo.
[00:43:19] Então, ao invés de a gente ter simplesmente o código que faz alguma coisa, a gente vai ter um monte de if e else espalhados no código,
[00:43:25] para um monte de Feature Flags que a gente vai colocar no código, até que aquela funcionalidade inteira esteja pronta.
[00:43:31] Para mim, isso coloca como um risco também.
[00:43:34] Eu vejo a galera, em geral, desconsiderando esse ponto.
[00:43:38] É como se Feature Flag fosse de graça.
[00:43:40] Não é de graça. Feature Flag tem um custo. Vai tornar o código mais complexo, mais difícil de ler.
[00:43:45] Qualquer coisa que você for fazer vai ter que mexer em duas partes do código ao mesmo tempo.
[00:43:50] Talvez você não saiba que tem que mudar em duas partes, então você vai mudar em uma só.
[00:43:53] Vai criar um bug futuro, que é um bug que não vai acontecer naquele momento, vai acontecer, sei lá, um mês depois.
[00:43:58] Porque é quando a funcionalidade como um todo vai entrar em produção e a gente vai ligar a Feature Flag.
[00:44:02] Então, tipo, existe complexidade no uso de Feature Flag aqui.
[00:44:05] Então, de maneira geral, eu considero Feature Flags como uma ideia muito interessante.
[00:44:10] Para a gente desacoplar entrega de release, tá?
[00:44:15] Então, entrega é o engenheiro terminou o código, botou em produção, isso é uma entrega.
[00:44:20] Release é a entrega para o usuário final.
[00:44:23] Então, a entrega é a responsabilidade do engenheiro.
[00:44:26] A release é a responsabilidade da pessoa que está do lado do negócio.
[00:44:29] Ela escolhe quando aquilo vai ser lançado.
[00:44:31] Mas o código já vai estar lá em produção, pronto para aquilo ser rodado.
[00:44:35] Então, a gente consegue… Feature Flag é excelente para isso.
[00:44:38] Porém, para mim, é muito ruim como um método da gente fazer uma entrega separada em pedaços menores
[00:44:44] e que esses pedaços só vão fazer sentido quando estiverem conectados todos juntos em produção.
[00:44:48] Então, nesse sentido, é muito ruim.
[00:44:50] Agora, existe um lado bom, vamos dizer assim, que eu posso considerar aqui do Truncated Based Development,
[00:44:55] que é se a gente conseguir, a gente conseguir fazer entregas de funcionalidades inteiras de uma forma mais autocontida, menor.
[00:45:03] Então, eu acho que o esforço, ele é muito bom ou muito bem-vindo,
[00:45:07] mas ele vier no sentido de a gente conseguir criar funcionalidades que sejam menores
[00:45:12] e que já gerem valor fazendo poucas alterações.
[00:45:15] Mais isso do que necessariamente a gente dividir uma entrega grande em pedacinhos pequenininhos
[00:45:19] que só vão fazer sentido quando estiverem juntos todos em produção.
[00:45:23] Então, é mais a gente, vamos dizer assim, reduzir o tamanho dos nossos entregáveis de valor, mais isso,
[00:45:29] e menos a gente quebrar entregas grandes em pedaços menores e juntar, enfim,
[00:45:33] botar embaixo de Feature Flag e só ligar quando tudo estiver junto.
[00:45:35] Então, acho que essa é a minha grande crítica em relação a Truncated Based Development,
[00:45:39] que é muito mais fácil a gente continuar fazendo entregas grandes quebradas em pedaços menores
[00:45:45] que só fazem sentido estando juntos, do que necessariamente a gente fazer, criar escopos menores das nossas entregas.
[00:45:51] Então, para mim, vamos dizer assim, o desafio, ele é muito mais do lado do negócio,
[00:45:55] da gente conseguir quebrar entregas de valor em pedaços menores, do que do lado de tecnologia.
[00:45:59] E quando a gente fala em Truncated Based Development, a gente está falando muito mais do lado de tecnologia,
[00:46:03] menos do lado do negócio.
[00:46:05] Então, eu não tenho muita crítica a esse método.
[00:46:07] Mas, eu sou, enfim, um grande fã de fazer entregas pequenas, autocontidas, que já gerem, de fato, valor.
[00:46:12] E isso, naturalmente, deveria levar a branch a durar menos tempo, enfim, no nosso versionador ali.
[00:46:19] Então, se for nesse sentido, então eu sou super a favor.
[00:46:22] Bom, eu acho excelente, inclusive, que a gente caminhe nessa direção.
[00:46:26] Então, acho que se a gente estiver nesse ponto, então eu concordo com Truncated Based Development,
[00:46:31] senão, eu acho que não é uma solução tão boa assim, tá?
[00:46:34] Porque o uso de feature flag, ela vai poluir nosso código.
[00:46:37] A gente precisa ter isso em mente.
[00:46:39] Beleza?
[00:46:40] Então, bom, acho que eu consegui explicar aqui, relativamente bem, espero, sobre o que eu considero os quatro mitos,
[00:46:48] os quatro, não, quatro mitos em engenharia de software.
[00:46:52] Caso você tenha curtido esse formato aí, de mitos, enfim, mais dessa parte focada tecnicamente,
[00:46:58] me avisa para eu poder criar mais episódios relacionados, enfim.
[00:47:03] Também quero te convidar a conhecer a Escola Forja.
[00:47:05] Eu vou deixar o link aqui nos comentários do vídeo, nas notas de podcast da Escola Forja,
[00:47:11] que é uma escola para formação de líderes na área de tecnologia.
[00:47:13] Espero que você tenha curtido esse episódio.
[00:47:15] Se curtir, me avisa para poder criar mais episódios nesse formato.
[00:47:18] Um abraço para você e até a próxima.
[00:47:21] Se você gostou desse episódio, então também vai curtir os outros conteúdos da Escola Forja.
[00:47:25] Lá você vai encontrar treinamentos, workshops, masterclasses, estudos de caso, palestras, além desse podcast,
[00:47:31] e uma curadoria refinada de conteúdo.
[00:47:33] E diversos deles são de graça.
[00:47:35] Você pode acessar pelo QR Code aqui na tela ou pelo link na descrição.
[00:47:39] Te vejo por lá.