Do SQL para NoSQL/MongoDB: Repensando sua vida de desenvolvedor

Vivemos anos num mundo massivamente relacional, armazenando nossos dados em bancos de dados relacionais, usando SQL para encontrar, criar, atualizar e excluir dados, e o pensamento de armazenar dados invariavelmente caía neste paradigma. Mas a internet cresceu exponencialmente, necessidades diferentes surgiram e os bancos relacionais começaram a não se adequar a muitas necessidades de projetos que não podem ser pensados durante anos e ficarem como estão durante outros tantos anos.

Então, novos tipos de abordagem de armazenamento surgiram e mexeram com a supremacia relacional. E com a vida dos desenvolvedores. Neste artigo vou discutir um pouco meu histórico para chegar no MongoDB como base de armazenamento para projetos.

Eu gosto muito de metodologias ágeis, apesar de não seguir estritamente nenhuma em especial. Sempre sugiro o aprendizado do SCRUM e a leitura do Get In Real (da 37 Signals) para meus alunos, pois é preciso pensar diferente do tradicional para atender a demandas que não são mais tradicionais.

Há algum tempo atrás, coisa de 7, 8 anos, comecei a pensar que programar não podia ser um trabalho “macacal”. Então, fui atrás de formas de agilizar a programação em PHP, acabei conhecendo frameworks como o Miolo, projeto do qual participei e que me inspirou a criar meu próprio framework. Mas depois parei de querer reinventar a roda, e acabei optanto pelo symfony (sem desmerecer outros, pois há outras ótimas opções mais ou menos conhecidas).

Mas em relação ao armazenamento, o natural companheiro do PHP, o bom e velho MySQL, foi meu início. Na verdade, antes já tinha trabalhado bastante com o MS Access e um pouco como MS SQL Server (ok, todo mundo tem suas manchas no currículo), então não comecei “do zero”. O mundo maravilhoso do SQL me conquistou.

Chegou então a necessidade de trabalhar com outros bancos (Firebird, Postgres, Oracle, MS SQL Server) e o SQL genérico foi de grande valia. Então o mundo do software livre começou a me colocar alguns dilemas.

Inicialmente, o dilema de usar ou não características específicas (e muitas vezes com alto ganho de desempenho e integridade de dados), como triggers e stored procedures. Vantagens: claro, desempenho, integridade, blá, blá. Desvantagens: você só vai usar aquele banco.

Obviamente, num ambiente grande e de alta carga, esta decisão é mais tranquila, pois você não vai trocar de banco de dados a cada fim de semana. Mas quando se trabalha com software livre, é preciso dar liberdade de escolha do banco – no mínimo entre MySQL e Postgres. Aí trabalhar com SQL, apesar de muito lindo e maravilhoso, começa a cair nas sutilezas de implementação entre cada banco.

Uma “facilidade” do MySQL – os campos autonumerados – não existem em outros bancos, que possuem abordagem diferentes, muitas vezes melhores, outras vezes piores, outras vezes apenas diferentes.

Bom, meu primeiro passo foi utilizar uma camada de abstração de dados muito conhecida na época (e ainda utilizada hoje), a ADODB. Isto já facilitou muitíssimo, pois mantendo as SQLs razoavelmente portáveis era possível trabalhar com vários bancos num mesmo projeto. Era só ter um SQL schema para cada banco a suportar, e um ou outro ajuste fino em SQLs.

O PHP incluiu como padrão a biblioteca PDO, que realmente melhorou muitíssimo nossa pobre vida de desenvolvedor PHP… não mais mysql_connect. Nem mesmo sua versão OO, MySQLi. Todo mundo embaixo da asa da mamãe PDO.

Mesmo assim – e assim mesmo – ser multibanco é parte do problema. É preciso validar dados (regras de negócio), criar formulários, editar, inserir, recuperar e excluir registros… bem, fazer o CRUD. Inúmeras pequenas bibliotecas faziam este trabalho, numa imensa colcha de retalhos.

Então, já ingressado no mundo do symfony, conheci o PROPEL, um maravilhoso ORM (english, português) que mudou com minha forma de me relacionar com os bancos relacionais (ok, um tanto redundante). Ao olhar o banco de modo orientado a objeto, minha vida de programador mudou radicalmente.

Claro que o paradigma é muito distinto, e em alguns pontos os atritos com os DBAs tornam-se inevitáveis (pois utilizar alguns recursos específicos de um banco não é algo fácil ou possível com um ORM), além de que a imensa tentação de voltar a “controlar tudo de novo”, leia-se, colocar TODA regra de negócio na aplicação, deixando apenas integridade referencial ao banco de dados é praticamente inevitável. Mas nem tudo são flores.

Para nos deixar distante do SQL, o PROPEL tem uma linguagem de consulta própria. Ops… aí já é um problema. Isto por si só é desagradável, mas a linguagem de consulta do PROPEL é muito estranha. Difícil de se adaptar. Mas os ganhos compensavam as perdas…

… até aparecer o Doctrine, um outro ORM com muitos, muitos recursos que o PROPEL não possui. Dois principais: migrations (não sei como consegui viver sem ele até então…) e uma linguagem de consulta beeeeeem mais palatável, a DQL, semelhante em parte ao SQL (o que é bom para migração nosso cérebro) mas com facilidades que a OO trás. O Doctrine permite pensar o banco em OO, e ele faz o trabalho duro de converter isto em banco relacional. Simula até herança! Ok, se o desenvolvedor esquecer que embaixo de tudo roda um banco de dados relacional, pode fazer algo com desempenho sofrível. Bom, vivi muito bem neste mundo durante um bom tempo.

Mas ainda não tinha consegui passar por cima do meu eterno dilema… liberdade para manipular o banco “on-the-fly”, repassar isto para inúmeros clientes com a mesma aplicação sem ter que sair dando updates na estrutura, enfim… como ter um objeto Produto com várias configurações sem ter ou uma tabela com inúmeros campos ou um padrão EAV, que funciona mas é complexo. Ou simplesmente permitir que meu cliente crie um campo no cadastro de pessoas.

Tudo isso pode ser resolvido num banco relacional, mas a manutenção (e o tempo gasto pensando na manutenção) é árdua.

Eu estava já há tempos procurando um caminho para iniciar alguns projetos com estas premissas, quando comecei a ouvir no horizonte: NoSQL, NoSQL, NoSQL… Bem, fui investigar e descobri que gente realmente GRANDE usa e investe em NoSQL. Estudando as alternativas, acabei conhecendo o MongoDB.

Simples, rápido, uma comunidade forte, boa documentação e em constante evolução. E casa muito bem com projetos com metodologia ágil, pois permite facilmente ampliar uma aplicação com novos campos, documentos “pequenos”  convivendo lado a lado com documentos enormes na mesma coleção. O dilema de uma tabela de produtos com campos (atributos) distintos não é problema – basta gravar conjuntos de atributos que sejam necessários.

Isto tem nome: schemaless. Não é necessário definir como os dados serão gravados (“CREATE TABLE …”). Apenas grave. Mais do que isto, não é preciso criar a tabela. Não é preciso nem criar o banco (“CREATE DATABASE…”)! Apenas diga “quero gravar estes dados como documento da coleção X no banco Y”. E o MongoDB vai lá e cria. Não precisa incluir um campo (“UPDATE TABLE ADD COLUMN…”), basta gravá-lo. Não precisa excluir um campo (“UPDATE TABLE  DROP COLUMN…”), basta eliminar dos documentos (um “unset”).

E mais: é possível pesquisar nesta “bagunça”, de modo semelhante (mas muito diferente) ao que se faz no SQL. É possível pesquisar com REGEX! A agregação é possível através do MapReduce, que também é uma poderosa ferramenta de análise.

Há coisas que são estranhas pela “liberdade”. Se um documento não possui um atributo, como posso pesquisá-lo? Bom, eu posso até pesquisar documentos que possuem ou não um atributo…

E relacionamentos? Acostume-se com a idéia de que vai usar muito menos relacionamentos. E que vai trabalhar com redundâncias, e que terá que mantê-las via código. Por outro lado, vai recuperar dados sem joins complexos. Isto é estranho, difícil no início, mas não significa que o DBA será aposentado, só terá que pensar de modo diferente. E ele continuará com a responsabilidade de pensar qual o melhor modo de armazenar, com mais desempenho, e as funções de administração, backup, replicação, etc. Não, você não vai demití-lo, apenas chacoalhá-lo.

E a programação?

O suporte ao MongoDB no PHP é muito bom, nativo através de uma extensão. Existem vários ORMs que suportam o MongoDB, talvez o com mais recursos seja o… é, Doctrine (versão 2). Particularmente, utilizo o Mondongo, hoje Mandango. Mas ambos não são schemaless, e isto pode ser um pouco frustrante. Por isto, fiz um fork no Mondongo para uso em projetos pessoais, retirando esta “limitação”.

Se você pretende ir por este caminho, tenha em mente que a responsabilidade do desenvolvedor aumenta bastante, pois não há integridade referencial, se gravar um integer com string os dados serão gravados, ou seja, é preciso saber lidar com esta liberdade. É fácil fazer um grande besteira. Mas também é fácil dar manutenção, não é preciso realizar migrações, updates de banco. É fácil escalar, é fácil criar redundância.

É um paradigma diferente de construção de sistemas.

No início do texto comentei sobre metodologias ágeis. Isto porque concluí que o NoSQL, no caso o MongoDB, me fez sentir-me realmente ÁGIL.

Em tempo: minha escolha pode ser boa para mim, mas não para você. Pode considerar minha escolha, mas estude e tire suas próprias conclusões, que certamente serão o caminho que você deve seguir. Há outros bancos NoSQL, e talvez um deles se adeque melhor aos seus projetos.

Referências

  • You are so interesting! I do not suppose I have read
    a single thing like this before. So great to discover another person with some genuine thoughts on this
    topic. Seriously.. thanks for starting this up. This web site is something that is required on the
    web, someone with some originality!

  • Your style is so unique in comparison to other folks I’ve read stuff from.
    Thanks for posting when you’ve got the opportunity, Guess I’ll
    just book mark this web site.

  • I’m really enjoying the design and layout of your blog.
    It’s a very easy on the eyes which makes it much more enjoyable for
    me to come here and visit more often. Did you hire out a developer
    to create your theme? Excellent work!