Chave Estrangeira e Integridade Referencial é coisa do passado?

Praticamente todo mundo do mundo já estudou bando de dados e ouviu falar sobre chaves estrangeiras e integridade referencial. Se você nunca ouviu falar nisso, páre de ler agora e vá procurar ler algo sobre esse assunto. Não quero entrar em detalhes sobre o que é integridade referencial, mas aqui vai uma definição básica da wikipedia:

Num banco de dados relacional, quando um registro aponta para o outro, dependente deste, há de se fazer regras para que o registro “pai” não possa ser excluído se ele tiver “filhos” (as suas dependências).

O relacionamento é feito através das chaves estrangeiras das tabelas, avaliadas antes da execução do comando de delete, insert ou update.

O grande objetivo de manter a integridade referencial, é evitar a presença de registros no banco de dados que tenham relação com registros que não estão mais no banco de dados (porque foram apagados ou qualquer outro motivo). Manter a consistência e integridade dos dados. Faz muito sentido, por qual razão alguém gostaria de ter dados inconsistentes?? è importante lembrar que integridade referencial e normalização de banco de dados são conceitos que andam lado a lado. Uma vez que normalizamos, precisamos “espalhar” os dados em lugares (tabelas) diferentes e aí não queremo que os dados fiquem inconsistentes.

Tudo bem até aí, mas agora entra em cena o choque de realidade que 2 outros conceitos trazem consigo:

  • Banco de dados NoSql
  • Arquiteturas baseadas em Micro-Serviços

Vamos tratar um de cada vez, começando com NoSql e uma descrição simples (retirada da wikipedia)

NoSQL (ás vezes interpretado como Not Only SQL – Não Somente SQL) é um termo genérico para uma classe definida de banco de dados não-relacionais que rompe uma longa história de banco de dados relacionais com propriedades ACID.

Quem conhece sabe que (em especial os banco de dados document based) armazenam os dados de forma “nao-normalizada”, o que significa que os dados estão menos “espalhados”, e consequetemente existem menos relações entre registros armazenados no banco dados. Obviamente, se existem menos tabelas e menos relações, também pode existir mais duplicação dos dados armazenados.

Ainda assim, é preciso existir relações entre os registros (ou documentos), e para isso, ao invés de fazer a relação baseada em chaves estrangeiras, podemos usar simplesmente uma URI (de uma determinada API). Agora preste atenção, esse é um ponto chave desse post. Se a relação entre um registro e outro é baseada em uma URI/URL (que vai levar a outro resource), esse outro resource pode não estar armazenado no mesmo banco de dados, inclusive pode incluse estar em outro servidor, em outro lugar do mundo. Nesse caso, chaves estrangeiras não ajudariam. E agora faremos a ponte entre os 2 conceitos que mencionamos anteriormente: Micro-Services.

Para começar, uma breve descrição do que seria micro serviços (retirado deste site):

O termo “Arquitetura de Micro-serviços (Microservice Architecture)” surgiu nos últimos anos para descrever uma maneira específica de desenvolver software como suites de serviços com deploy independente. Embora não exista uma definição precisa desse estilo de arquitetura, há certas características comuns em relação à organização, à capacidade de negócios, ao deploy automatizado, à inteligência nos terminais e ao controle descentralizado de linguagens e de dados.

Como em quase todas as coisas, se você aplicar o conceito do “divide and conquer”, é melhor e mais gerenciável ter algumas/várias partes pequenas do que uma só grande parte. Seguindo essa linha de raciocínio, as arquiteturas baseadas em serviços, caminham na direção de micro serviços. Seriam partes que teriam um deploy independente, potencialmente em servidores independentes e que se comunica com outras partes da sua arquitetura por meio de uma RESTfull API.

Tudo bem, e qual é a conclusão?

Levando em consideração essa tendência, que diferentes partes do sistema podem estar em servidores/banco de dados diferentes, não faz sentido sentido controlar a integridade referencial com chaves estrangeiras no nível do banco de dados como estamos acostumados e estudamos nas universidades. Esse controle tem que ser em um nível acima do banco de dados.

Claro que chaves estrangeiras ainda tem seu lugar, e são muitíssimo indicadas para solucionar/arquitetar determinados problemas. Contanto, com o mundo da computação ficando cada vez mais e mais distribuído, nossas queridas chaves estrangeiras como conhecemos não são mais suficientes em todos os casos.

Tudo bem, e como controlar a integridade referencial nesse novo cenário?

Existem algumas opções, algumas muito simples, mas talvez não solucionem seu problema. Uma delas é, simplesmente não se preocupar com isso (ok, eu concordo que é meio ridículo). Outra é, em um nível de abstração acima dos banco de dados e servidores, ter um serviço específico para fazer o controle, o que pode se tornar uma tarefa dificílima e passível de erros também. Então, se você precisa de uma solução em que os dados estão espalhados, e a integridade é absolutamente essencial e vital, você deveria estar usando bancos relacionais e serviços mais centralizados em minha opinião.

“Eu não concordo com você”

Então meu amigo, deixe um comentário falando como você resolveria esse problema 🙂 Eu vou ficar mais do que feliz de ler e possivelmente incorporar tua solução no texto desse post.

GRASP – Coisas que todo programador deveria saber

the-thinkerEsse é o segundo post do BdB (Bytes don’t Bite) da série “Coisas que todo programador deveria saber”. Caso você tenha perdido o primeiro post, nele eu falei sobre os princípios de design de software chamado SOLID e você pode acessar esse post aqui (Não se preocupe pois a leitura do primeiro não é pre-requisito para esse post).

O foco do segundo post é sobre o GRASP, que é algo desconhecido para muita gente, mas é também muito importante. GRASP não é uma ferramenta, não é uma metodologia, não é um software, não é um plugin nem nada do tipo. De forma similar aos princípios do SOLID, o GRASP é um conjunto de conceitos que ajudam na hora de pensar no design do software, em como suas classes estarão estruturadas e relacionadas, onde cada operação vai ser implementada, etc.

Craig Larman escreveu no seu livro (mesmo livro onde ele descreve o GRASP), uma frase interessante:

“the critical design tool for software development is a mind well educated in design principles. It is not the UML or any other technology.”

Quando eu vi essa frase eu já me identifiquei, pois reflete o que eu penso também. UML não vale de nada se você não souber como estruturar (design/architecture) o seu sistema. Se você não sabe como fazer um design bem feito, UML vai se resumir a uma ferramenta de desenho, como o paintbrush. Isso só faz reforçar a importância de princípios e padrões como o SOLID e o GRASP.

Como disse antes o GRASP é um conjunto de princípios e padrões para design de software, e nesse post eu vou cobrir alguns desses princípios/padrões que acho relevantes. Então vamos lá:

  1. High Cohesion (Alta Coesão) e Low Coupling (Baixo Acoplamento): Esses 2 pontos merecem ser tratados juntos, pois estão sempre de mãos dadas. A idéia central aqui, é diminuir as dependências entre as classes, de forma que uma mudança em uma classe não afete muitas outras. E a melhor forma de fazer isso é separando as responsabilidades de cada classe, dessa forma aumentando a coesão. Quanto mais coisas não relecionadas uma classe faz, menos coesa essa classe é. O resultado de uma alta coesão e um baixo acoplamento é que suas classes e componentes vão ser mais reusáveis.
    (Esse ponto também está relacionado com um dos princípios do SOLID)
  2. Creator: Quem deve ser o responsável por criar uma instância de uma classe X? Essa pergunta as vezes pode parecer fácil, mas se você der uma resposta errada, você começa a ferir outros pontos importantes como o acoplamento e coesão discutidos no ponto anterior. Esse padrão lista algumas dicas para responder essa pergunta. Geralmente a classe Y responsável por instanciar objetos da classe X deve ser sob as seguintes condições (quanto mais melhor) : (i) Classe Y contém ou é composta por X (ii) Classe Y usa extensivamente classe X (iii) Classe Y possui todas as informações necessárias pra instanciar X (e aqui está um ótimo link para falarmos sobre o próximo ponto, que talvez seja um dos mais importantes na minha opinião).
  3. Information Expert: Como saber quais responsabilidades atribuir a quais classes? A resposta é simples, mas é preciso ter essa resposta sempre em mente se quiser definir o design de seu sistema de forma satisfatória e elegante. A resposta é: A responsabilidade de uma determinada operação, deve ser da classe que tem todas as informações necessárias para completar aquela operação. Se você tiver isso sempre em mente, fica fácil saber em qual classe você vai implementar determinado método, qual classe vai conter um determinado atributo, e qual classe vai ser responsável por instanciar uma outra classe (aqui está o link de volta para o ponto 2 “Creator”)
  4. Indirection: Esse princípio prega que, de forma a diminuir (ou evitar) o acoplamento entre duas entidades quaisquer, a melhor forma é atribuir essa responsabilidade a uma entidade intermediária. Alguns design patterns se baseiam nesse princípio, como por exemplo: Adapter, Bridge, Façade, Observer, etc.
  5. Controller: Uma aplicação clara do princípio de Indirection, é o Controller. De quem é a responsabilidade de diminuir (ou evitar) o acoplamento entre os dados (model) e sua representação (view)?? Resposta clara, Controller 🙂 Não quero explicar o que é um Controller, mas queria chegar nesse ponto só para ficar claro a relação dos padrões e como um ponto impacta e afeta os outros. No final estão todos conectados!

Esse foi o segundo capítulo da série “Coisas que todo programador deveria saber”. Se você gostou, e gostaria que essa série continuasse, deixe um comentário aqui ou compartilhe esse post com seus amigos que você sabe que acharia útil essa informação.

Qual o FUTURO da computação nos países ricos?

Enquanto dirigíamos para uma high school no estado de Iowa nos Estados Unidos, escutei de um engenheiro de sotware americano (muito compentente por sinal) sobre um fenômeno que estava acontecendo nos USA que me deixou pensativo. O motivo pelo qual estávamos indo para a high school era porque a empresa onde eu trabalho participa de um projeto social onde os engenheiros de software experientes da empresa fazem uma espécie de “aula” e acompanham os estudantes em tópicos relacionados a TI, numa tentativa de despertar a curiosidade desses alunos por computação, desenvolvimento de software e afins.

Voltando ao assuto que tinha me deixado pensativo, aquele 8213e2b9121b11c16d18a02e2899d724engenheiro me falou que as pessoas que prestavam aconselhamento vocacional para as crianças/adolescentes nas escolas, muitas vezes estavam com um discurso que não valia a pena escolher computação, especialmente se for para enveredar em desenvolvimento de software. O Motivo? Simples demais. Pra que você vai ser programador/tester/etc se as empresas nos países ricos e desenvolvidos estão cada vez mais transferindo o desenvolvimento para países onde a mão de obra é mais barata (seja terceirizando ou abrindo filiais nesses países)? Isso é um fato, não existe dúvida que isso está acontecendo. Países como a Índia já estão cheios de centros de desenvolvimento de software, e a matemática é simples: Para que contratar um desenvolvedor/tester na Alemanha (por exemplo) se é possível contratar 4 ou 5 na Índia pelo mesmo valor?

Claro que existem diversas questões atreladas a isso, como por exemplo se realmente vale a pena, questões relacionadas com a qualidade do produto final, questões relacionadas com como gerenciar o desenvolvimento geograficamente espalhado, como coordenar da melhor forma e assim por diante. Não quero entrar nos detalhes dessas questões, quero me ater ao fato de que isso está acontecendo, e cada vez mais.

Gostaria de deixar aqui algumas reflexões:

1) Antes eu pensava [e ainda hoje penso] que seria ótimo se meus filhos seguissem o caminho da computação, mas agora, estou pensando se realmente é isso que quero para o futuro deles. Será que você também aconselharia seu filho a fazer computação, ou seria melhor algo que não pudesse ser facilmente transferível para a Índia (ou qualquer outro lugar no mundo onde seja mais barato)? Estou honestamente pensativo sobre isso… acho que essa reflexão é válida.

2) Outra reflexão válida, é se o nosso Brasil vai virar uma Índia nesse sentido. Não sei até que ponto o nosso “Custo Brasil” permite que isso aconteça, mas o fato é que temos recursos humanos excelentes em TI… será?

3) Essa terceira reflexão, vai de encontro com a reflexão número 2. Nessa aqui, eu coloco o Brasil como um país “rico”, pelo menos no que diz respeito a terceirizar os serviços de TI e contratar países onde os serviços sejam mais baratos. Nesse caso, o ponto 1 começaria a fazer sentido também para os brasileiros. E aí, o que vocês acham?

Hora de partir

Depois de quase 4 anos desde meu primeiro post, chegou a hora de me despedir do BdB! Nesse tempo foram muitos posts falando sobre testes de software, agilidade e outros assuntos relacionados. Gostaria de agradecer imensamente a todos aqueles que participaram de alguma forma (comentando, curtindo, compartilhando…) e ao grande amigo Thiago Burgos.

QAlab_verde_subtitleNo entanto, não estou me despedindo do mundo dos blogs. A experiência de aprender e compartilhar continua e a partir de 2015 estarei me dedicando a um novo projeto,  e como parte do QALab também teremos o nosso blog, onde pretendo seguir compartilhando conteúdo relacionado a qualidade de software.

Um Abraço a todos! E Feliz 2015!