SQL é para dados, lógica não!

domingo, 27 de junho de 2010

Engraçado como são montadas as grades de disciplinas nas universidades... cada professor quer ensinar o que sabe, obviamente. O problema é que isto não é, necessariamente, no melhor interesse do aluno quando se olha para o todo, para o corpo de conhecimento sendo passado. Algumas coisas ficam bem aprofundadas e outras nem são mencioadas.


Por exemplo, sempre achei engraçado como na graduação em Ciência da Computação do DCC/UFRJ temos linguagens de programação nos primeiros períodos sem vermos NADA de banco de dados. Que só é visto na segunda metade do curso, sem nenhuma linguagem de programação acompanhando.

Resultado: ninguém faz um programinha que conecte no banco e faça alguma coisa. Inclusive, toda a persistência de trabalhos de faculdade é feita em arquivos até banco de dados e muitas vezes depois também.

Claro, sempre vale o argumento de que é muito fácil aprender sozinho, etc. Mas isso quando se pensa na conexão em si. Ninguém fala de mecanismos no banco para lidar com concorrência (locks pessimistas/otimistas) nem mapeamento objeto-relacional nem particionamento horizontal/vertical nem nada assim. Pelo menos não nas obrigatórias.

Mas acho que o pior é quando o professor acha que todo mundo tem que saber fazer as coisas na mesma profundidade que ele (por mais específicos que sejam os casos de aplicação real). E passa metade da disciplina em SQL. E os alunos arrancando os cabelos para fazer SQLs de várias linhas para... hmm.. nada útil.

O fato é que grande parte dos sistemas atualmente são orientados a objetos. A maior parte das queries é simples e as mais complicadas são geradas por algum framework de mapeamento objeto-relacional.

O pior é que SQLs grandes costumam gerar código "write-once". Aqueles que as pessoas escrevem e torcem pra nunca terem que alterar pois não conseguirão mais entender como aquilo funciona (e por Murphy é justamente alí que vai ter mudança, nem que seja pra jogar aquele trabalhão todo fora).

Por exemplo, uma questão que me lembro quando fiz esta disciplina era gerar uma SQL que desse como resultado as posições de chegada de cavalos na ordem, com seus tempos de chegada após uma corrida. A tabela tinha os cavalos e seus tempos. O "x" da questão era justamente gerar as posições.

Pois bem, apreciem a resposta:

select count(*) as posicao, c1.nome, c1.tempo from cavalos c1 join cavalos c2 on c1.tempo >= c2.tempo group by c1.nome, c1.tempo order by posicao;

Isto mesmo, um join da tabela com ela mesma onde qualquer um teria feito simplesmente um "SELECT * FROM Cavalos ORDER BY posicao;" e um for que imprime o índice do loop antes de cada linha, para produzir o seguinte efeito:



1FugindoDoJackBauer00:00:01
2Veloz00:00:25
3Rápido00:00:35
4Corredor00:00:40
5Ligeiro00:00:45
6Pangaré00:01:00


Agora, amigos, imaginem uma aplicação onde se coloca a lógica da aplicação em consultas de várias linhas. Pois é, nem tudo que dá para fazer é para ser feito, né? :-)


Abraço a todos!


P.S.: Caso alguém queira testar, be my guest.


CREATE TABLE cavalos (nome varchar(255), tempo time);
INSERT INTO cavalos (nome, tempo) VALUES ('Pangaré', '00:01:00');
INSERT INTO cavalos (nome, tempo) VALUES ('Ligeiro', '00:00:45');
INSERT INTO cavalos (nome, tempo) VALUES ('Corredor', '00:00:40');
INSERT INTO cavalos (nome, tempo) VALUES ('Rápido', '00:00:35');
INSERT INTO cavalos (nome, tempo) VALUES ('Veloz', '00:00:25');
INSERT INTO cavalos (nome, tempo) VALUES ('FugindoDoJackBauer', '00:00:01');

Bookmark and Share

5 comentários:

B disse...

Muito bom artigo. :)

Jerry disse...

ARGH! Que código obstruso essa query SQL.
Sinceramente, SQL não foi feito para isso!

zimbrao disse...

Oi Peter,

Acho muito válida a sua primeira parte do post. A segunda não:
"A maior parte das queries é simples e as mais complicadas são geradas por algum framework de mapeamento objeto-relacional."
Pois é, mas alguém que fez BD I deve saber montar essas queries... se não, quem iria programar esse framework? É a velha estória, já que todos usam calculadoras porque aprender a fazer divisão no lápis?

Mas de qualquer forma, achei bem interessante essa dicotomia entre LPs e Banco de Dados/sistemas de arquivos, que revela um problema sobre o qual já houve certa discussão quando se fez a última reofrma curricular mas não se avançou muito: a integração do conteúdo das disciplinas.

Peço sua autorização para repassar esse post para a lista de discussão do dcc. Posso?

Abraços,
Zimbrão.

Peter disse...
Este comentário foi removido pelo autor.
Peter disse...

Claro Zimbrão! Fique a vontade.
Entendo o que você quer dizer com relação a saber fazer e tal.
Mas primeiro, veja o que está sendo passado neste exercício: Se o número da posição é necessário, deve ser por questões de usabilidade ou por uma questão do negócio onde a posição deve ser informada. Isto nada tem a ver com obter os dados. Este dado não está lá na base. Foi fabricado pela SQL no lugar onde um for faria um trabalho muito mais limpo (e na camada certa).
A grande questão na minha opinião gira em torno do nível de profundidade que se deve exigir dos alunos em temas muito específicos. Concordo que alguém precisa saber fazer o framework. Mas colocando este conhecimento neste nível num curso onde se preza o conhecimento amplo em detrimento de especializaçõe é o mesmo que dizer que todos, inclusive os que vão ser analistas, gerentes ou que vão trabalhar com hardware ou computação científica, etc precisam saber SQL neste nível.

Eu já tive a oportunidade de alterar algumas coisas no código do Hibernate, o framework de mapeamento O-R mais popular em Java e cada parte da consulta OO é traduzida para um trecho de SQL concatenado com outros que geram uma SQL complexa sem que ninguém tenha de fato tido o trabalho de escrever uma SQL complexa. Ela ainda é gerada automaticamente.

O único contexto em que vejo coisas assim sendo utilizadas (posso estar enganado) são em problemas de performance que lidam com grandes quantidades de dados, o que acontece vez ou outra. Até em aplicações OLAP o que vejo são muitos joins simples (ainda que gerados por uma ferramenta), nenhum problema muito complexo que exija nested queries com right outer joins e having entre diferentes tabelas e coisas do gênenro.

Atualmente, com o preço do hardware e o custo de mão de obra, sai muito mais barato clusterizar uma aplicação com problemas de performance que escrever um código write-once.
Barato não no sentido de comparar os custos como são, mas incluindo na mão de obra o custo para entender o código e documentá-lo, testar, ter um sistema estável/confiável, conseguir adaptá-lo às mudanças e responder a estas rapidamente, garantindo alto valor de negócio e melhor aproveitamento de janelas de oportunidade para stakeholders.

Postar um comentário

 
addthis_config = { data_ga_tracker: pageTracker }