Tom Kyte e os Pedidos
Olá,
Estive no GUOB Tech Day em São Paulo no dia 18, evento organizado (e muito bem organizado) pelo Grupo de Usuários Oracle Brasil e América Latina. Fui para prestigiar as palestras dos nossos amigos Ricardo Portilho e Rodrigo Almeida, mas aproveitei também para ver o Thomas Kyte ou Tom Kyte para os mais íntimos (ver o link) do famoso site ASKTOM.oracle.com nas suas palestras houve um momento interessante e para reflexão. Perguntado pelo criador da linguagem PL/SQL, se ele tivesse três desejos, o que ele, Tom Kyte colocaria no PL/SQL?
Como resposta, Tom Kyte disse que em vez de colocar, removeria três funcionalidades do PL/SQL a seguir:
- OTHERS: Quando usado com null (exemplo: … exception when OTHERS then null)
- AUTONOMOUS TRANSACTION
- TRIGGER
Enquanto ele explicava o primeiro tópico, lembrei-me de várias vezes ter usado para resolver um problema imediato e sem analisar o erro, mas, mesmo rindo, ouvi dele: “O ideal seria obrigar o uso de um “raise” quando utilizar o OTHERS, obrigando assim a saber o erro”. E mesmo concordando com o segundo e tendo dúvidas sobre o terceiro, pensei comigo mesmo: O problema está na verdade na falta de Bom Senso na utilização dessas funcionalidades. Ricardo Portilho e eu conversamos no café e ele também sugeriria a eliminação do DBLINK, porém ambos concordamos que essas funcionalidades na verdade foram utilizadas sem critério muitas vezes e por isso causam tantos problemas e portanto seria unânime a escolha de eliminação das mesmas. Mas quero aqui fazer uma reflexão sobre o usos dessas com base no exposto e explicado pelo mr. Kyte.
- OTHERS: Acho que fica claro quando ele fala sobre a obrigatoriedade do uso do RAISE e nunca o NULL quando se usa isso. Entendo que nas definições do POG essa é uma saída para evitarmos uma análise mais apurada sobre o erro que pode acontecer, porém ao utilizarmos o NULL com certeza NUNCA saberemos se houve um problema e pior: NEM COMO RESOLVÊ-LO!!!! Mas volto a afirmar sobre o Bom Senso, sim, eu já utilizei a combinação OTHERS-NULL para resolver um problema de falta de integridade de dados e o DUP_VAL_ON_INDEX não resolvia e nenhuma das outras vinte tratativas de exception. Analisando a Documentação do Oracle nota-se que o OTHERS era a “exceção” da exceção, algo como “Se nada mais der certo, use o OTHERS” porém como isso nunca ficou claro (nem na documentação) está aí a causa do uso indiscriminado do OTHERS e a sua mágoa para o mr. Kyte nas sua utilização, ainda mais por que é possível criar suas próprias exceptions tratando qualquer erro analisado e há sempre uma desculpa (normalmente por preguiça e mesmo no meu caso, admito que foi preguiça de criar uma exception especifica para meu problema) por parte da Equipe de Programação.
- AUTONOMOUS TRANSACTION: Para quem já desenvolveu em PL/SQL há muito tempo atrás, havia uma situação no caso da utilização de uma TRIGGER fazendo um SQL na mesma tabela associada a ela: o erro do “TABLE IS MUTATING” e também para o mais “antigos” havia uma solução para resolver esse caso. Com três triggers era possível resolver essa situação, mas dava trabalho e gerava várias linhas de código e funcionava muito bem. A vantagem dessa funcionalidade era justamente essa redução de código, porém ela gera um problema: há a (grande) possibilidade, no caso de mau-uso e de Modelo de Dados complexo, de se perder a integridade caso haja algum problema não tratado corretamente (algo como o OTHERS acima), pois o uso dessa funcionalidade leva a um “commit” na transação quando há alteração de dados (update , por exemplo) e o que ocorre na verdade é a criação de uma nova sessão para a execução dessa transação dentro da Trigger. Veja novamente que o uso indiscriminado da funcionalidade causa problemas às vezes de difícil rastreabilidade e geram horas e horas de análise para um diagnóstico correto.
- TRIGGER: Acho que essa foi uma afirmação do mr. Kyte que mais me fez refletir. Ele alega que as triggers não permitem que os programadores escrevam corretamente o código de programação, pois realmente facilitam a inserção de dados e algumas verificações, quando o correto na visão dele seria que a criação dessa inserção de maneira completa. Concordo e Discordo… Concordo quanto a escrever corretamente a inserção, pois realmente acho que as triggers não deveriam complementar nada e mesmo as verificações deveriam estar nas rotinas de inserção/deleção/atualização, mesmo auditorias deveriam estar nessas rotinas, porém quando a Oracle disponibilizou as triggers de DDL ou de Event Database, eu achei que estavam redimidas as triggers e passei a usar esses tipos com mais critério e cuidado. Um dos erros que mais encontro nos meus trabalhos está justamente no fato de se desabilitar as triggers de verificação para fazer alguma manipulação de dados e depois reabilitá-las, com as triggers de DDL e Database Event resolvo isso, mas somente depois de conseguir identificar a primeira ocorrência, afinal eu crio essas triggers depois para saber se isso realmente ocorreu. Discordo, pois há situações que o uso correto da trigger resolve vários outros problemas, mas acho que NUNCA poderia utilizar uma trigger para disparar processos, sejam eles quais forem. Com isso qualquer processo poderá não ter sido executado pelo simples fato de uma trigger estar desabilitada… (e isso quase nunca acontece…)
O Fato principal mesmo está no BOM SENSO no uso desses recursos. Não importa quão importante seja o recurso, se mal-utilizado pode ser um tiro no pé. Pena que o bom senso não seja algo que se possa ensinar, se fosse possível não teríamos nem que estar discutindo isso.
Abraços
Fabio,
Realmente, essa resposta dele foi fantástica, ainda mais quando falou do WHEN OTHERS!!!
Abraços,
Rodrigo Almeida