Outro dia sai do trabalho com uma cópia de um artigo do Alistair Cockburn, Hexagonal architecture, que fala sobre arquitetura de aplicações. Acabei em uma mesa de bar e o artigo incitou um debate sobre a necessidade de desenvolver aplicações que são agnósticas em relação ao Banco de dados, em outras palavras, aplicações que funcionam com diversos bancos de dados somente com alteração de configurações.
Para alguns na mesa isto é desnecessário, já que este não é um requisito real na grande maioria dos casos. São raros os exemplos de aplicações que foram migradas de um SGBD para outro e não é possível prever que isto vá acontecer um dia. Portanto, adicionar esta característica a aplicação seria adicionar complexidade desnecessariamente.
O problema não são os argumentos, mas sim o assunto. Ele é tão polêmico, quanto inútil. Pior que isto, nos distrai do que é realmente importante, como aconteceu nesta conversa que tive.
Eis a introdução do artigo, que iniciou todo o debate:
Create your application to work without either a UI or a database so you can run automated regression-tests against the application, work when the database becomes unavailable, and link applications together without any user involvement.
O negrito foi colocado propositalmente para destacar o assunto mais importante, que é ofuscado pela inútil discussão sobre banco de dados. Os principais requisitos da divisão de responsabilidades entre camadas e artefatos de uma aplicação são: Testabilidade e manutenibilidade.
A lógica de comunicação com o Banco de dados é complexa o suficiente para ser considerada uma responsabilidade que deve ser isolada e testada à parte. Mas isto já é feito pela camada de acesso a dado na velha conhecida arquitetura em três camadas.
Se eu consigo isolar e substituir esta camada por test double para poder testar as outras camadas sem precisar acessar o banco de dados meus já estão infinitamente melhores.
É possível testar uma aplicação sem isolá-la em pedaços menores. Na verdade isto é até desejável, são conhecidos como testes de aceitação, que testam cenários fim a fim, inclusive a persistência e leitura de dados no banco de dados. Todavia estes testes normalmente são pouco assertivos e consomem bastante tempo.
Um teste destes pode falhar por que: A UI não está correta, a regra de negócios está com defeito, o código de persistência está incorreto, a conexão de rede falhou, o tempo de resposta expirou, o dado no Banco de dados está incorreto, o Banco de dados está offline ou <preencha aqui o seu motivo favorito>. Ou seja, por qualquer motivo.
Além disto, a comunicação aplicação SGBD ainda é um pontos que mais consome tempo de execução, o que torna estes testes demorados.
Em suma, é desejável, senão necessário, conseguir testar minha aplicação sem precisar acessar o banco de dados a cada teste.
Mas se é possível substituir toda a camada de acesso a dados por uma falsa, ou um test double, então eu consigo substituir por outra que acesse outro repositório de dados. Então a propriedade “banco de dados agnóstica” vem de graça, ou a um custo muito baixo, como resultado da correta divisão de responsabilidades e do desacoplamento das camadas.
Agora como todas as decisões feitas na construção de um software, custos e benefícios devem ser avaliados. Faz algum tempo que eu acredito que testabilidade não é uma característica negociável, pois o custo de não tê-la é enorme e, mais dia menos dia, virá morder o seu calcanhar.