Se dois sistemas lidam com um mesmo conjunto de dados, por que não compartilhar a mesma base? Afinal de contas, nada tão simples, óbvio e indolor, certo?
[tweet]Para todo problema complexo há uma solução clara, simples e … errada – Henry Mencken[/tweet]
Infelizmente, talvez devido a obviedade dessa abordagem, ela seja tão utilizada no desenvolvimento de software corporativo.
[tweet]Compartilhar uma base de dados, geralmente, implica no aumento do acoplamento, aumento no custo de manutenção, problemas de escalabilidade e gargalos de performance. É uma dívida técnica fácil de contrair e difícil de pagar[/tweet]
Se é errado, por que os times insistem?
Há três respostas possíveis:
- Faltam cicatrizes! Não há experiência suficiente lidando com problemas causados pelo compartilhamento uma mesma base de dados entre diversas aplicações.
- Sobram traumas! Existem lembranças infelizes de estratégias de “segmentação” de bases de dados que não deram certo.
- Prazo
artificialmenteapertado!
De fato, não podemos ser alheios aos aspectos mercadológicos que envolvem o nosso trabalho. Time-to-market, metas e oportunidades de mercado, não são apenas importantes, são essenciais. Eventualmente, temos que assumir dívidas técnicas para atender essas necessidades do negócio e, na nossa visão, faz parte do trabalho de um profissional sênior entender quando “fazer errado”.
Todavia, se a rotina do nosso time é sempre ter que escolher “fazer o errado” e o momento de pagar as dívidas técnicas jamais chega, temos um sintoma sério de uma doença corporativa grave: No lugar de times de desenvolvimento, temos máquinas de produção de legado.
Mas, afinal, por que é errado?
Objetivamente, os principais problemas em compartilhar um bancos de dados entre aplicações são os seguintes:
- Problema de escalabilidade, visto que várias aplicações concentram carga de trabalho em um único banco de dados que se torna um gargalo de performance.
- Aumento do custo e tempo para se evoluir as aplicações devido ao alto acoplamento entre elas. Para mudar uma aplicação é preciso mudar várias.
- É quase impossível prever os impactos de uma alteração no banco de dados. Surgem problemas em produção devido a efeitos colaterais de alterações feitas em outros sistemas.
- Alterações no banco de dados demandaria testar, novamente, todas aplicações e eventualmente modificá-las, aumentando o custo do deploy
- Necessidade de alinhamento entre os times para gerenciar dependências entre os softwares pelo uso da mesma base.
Comum em todos esses pontos, muito mais grave do que o acoplamento entre aplicações é o acoplamento entre os times, que compromete o velocity.
Eventualmente, as aplicações passam a ser mantidas por times diferentes. Não raro, equipes menos experientes fazem modificações indesejadas que impactam outros times.
O que seria o “certo”?
Se duas aplicações tem em seu core demandas por um mesmo conjunto de dados, talvez não devessem ser aplicações separadas. Entretanto, caso o cenário demande, realmente, aplicações distintas, devemos trabalhar com opções de integração menos “intrusivas”.
Há uma pluralidade de soluções de integração praticadas no mercado. A solução ideal varia conforme cada cenário.
Como substituir “acoplamento” por “integração”?
Sabendo que o compartilhamento, entre duas ou mais aplicações, de uma mesma base de dados reflete-se em problemas e que não há opção definitiva de fazer uma boa integração, devemos atentar para um processo que colabore com o pagamento dessa dívida (quando ela ocorrer).
Entendemos que o primeiro passo para “pagar a dívida” é entender, exatamente, a condição atual (AS-IS) da arquitetura. Ou seja, precisamos ter uma visão clara dos componentes envolvidos (incluindo o banco de dados que está sendo compartilhado), as responsabilidades de cada um desses componentes, a forma como se relacionam (incluindo integrações com sistemas externos), e a estratégia evolutiva.
O segundo passo seria entender qual seria o cenário ideal (TO-BE) de integração. Que novos componentes deveriam ser incluídos? Quais seriam as novas responsabilidades de cada componente? Como ocorreria o relacionamento entre os componentes?
É importante destacar que o cenário futuro pode ou não implicar na adoção de novos mecanismos tecnológicos. Em caso positivo é sempre importante verificar se as especificações de compliance da organização seriam respeitadas. Além disso, seria muito importante estabelecer o patrocínio executivo para a mudança.
Finalmente, o terceiro passo seria estabelecer um roadmap de entregas. Afinal, dependendo do tamanho do acoplamento, geralmente não é possível sair do AS-IS para o TO-BE em uma única empreitada.
Estou trabalhando em uma migração de servidores de um software que tem todas essas más praticas aí de usar um banco de dados compartilhado(um dos bancos tem 1TB de dados)…
Não bastando isso os bancos(em torno de 32 bases) tem dependências entre si…
Essa divida técnica esta custando muito caro pra toda equipe agora…
Ótimo artigo, gostaria se possível, que falasse um pouco de técnicas que são utilizadas comumente em um cenário de acoplamento entre bancos. Ex: cenários em que o app precisa de um dado em “tempo real”.
Tenho usado menssageria para deixar os dados ‘mais perto’ de onde são necessários. Em um sistema baseado em DDD onde os ‘contextos delimitados’ são respeitados, o mesmo dado pode ter diferentes visões entre os contextos. Vou dar um exemplo bem banal mas que tem funcionado no meu caso: Tenho um contexto que é responsável pelos dados dos clientes. Ele é o dono da verdade nesse caso. Tem sempre os dados atuais dos clientes. Tenho outro serviço que precisa dos dados dos clientes, porém nem todos (alguns não precisam do endereço por exemplo). Então sempre que o serviço responsável pelo cliente inclui ou altera alguma informação ele dispara um evento para que todos os outros serviços que precisam de informações dos clientes possam pegar a parte necessária e gravar no seu banco local. Porém, neste cenário temos consistência eventual mas, em muitos casos, isso é aceitável. Agora se outro serviço precisar mesmo dos dados em tempo real, e não puder esperar nem alguns segundos para se atualizar, aí tem que haver comunicação síncrona mesmo entre os serviços (contextos), o que gera acoplamento, mas em casos específicos, pode ser a uma solução. O que eu não faço, de forma alguma, é acessar o banco de dados de outro serviço…. entre as 2 opções (apesar de ter outras) eu prefiro a comunicação síncrona mesmo. Mas, no projeto atual que estou trabalhando, em que os dados demoram poucos ou menos de 1 segundo pra se atualizar, ainda não precisei de comunicação síncrona entre nenhum contexto. Até porque, quando o front precisa dos dados atualizados dos ‘clientes’, seguindo o exemplo acima, ele pode fazer uma requisição diretamente no serviço de ‘clientes’.