Polimorfismo ou Parametros Dinâmicos

Dúvidas, dicas e truques de PL/SQL. Aqui também vão assuntos relacionados a pacotes, triggers, funções, Java-Stored Procedures, etc
Responder
Tinho
Rank: DBA Sênior
Rank: DBA Sênior
Mensagens: 318
Registrado em: Seg, 16 Nov 2009 4:50 pm
Localização: São Paulo - SP

Senhores,

Sei que a partir do Oracle 9, foi introduzido o conceito de objeto-relacional ao banco de dados. Por isso, utilizando o conceito de objetos gostaria de saber se alguém já utilizou poliformismo com PL/SQL.

Apenas para exemplificar:

Estou utilizando o Oracle Web Application. E na aplicação eu pego os parametros de uma tela HTML (página), dentro de uma procedure da package "A". Dentro da rotina da procedure da package "A" é chamado uma outra procedure da package "B" que recebe como parâmetros os valores dos parâmetros capturados na procedure da package "A".

Até então tudo bem, se a procedure da package "B" que é chamada dentro da package "A" não fosse chamada em diversos outros objetos. Ou seja, se altero a assinatura da chamada da procedure teria que replicar em todos os lugares onde a mesma é evocada. Assim sendo, o impacto desta alteração seria suficientemente crítico para outros projetos que estejam utilizando os objetos que seriam alterados, pois teriam os objetos invalidados.

Simplificando:

* PKG_A -> PRC_A: pega os parametros da tela (página HTML);
* PKA_A -> PKG_B.PRC_B: que recebe como parametros os valores capturados na PRC_A da PKG_A;
* PKG_B -> PRC_B: é utilizada em vários outros objetos, ou seja, se altero a assinatura da PRC_B, terei que alterar em todos os outros lugares onde a mesma é chamada;

Conversando com um colega, ele mencionou o polimorfismo, mas o exemplo que ele me deu não é bem polimorfismo. Ele sugeriu que eu replicasse a procedure com o mesmo nome alterando apenas os parametros na chamada da mesma. Alegando que dessa forma eu evitaria impacto em outras rotinas onde a mesma função é chamada. Nós chegamos a debater o conceito e eu comentei que já havia visto a sobreposição de métodos e/ou a passagem de parametros dinamicamente, mas não sei se aplicaria-se neste caso.

Mas como já existe toda uma rotina pronta com diversas regras e validações, não sei o que é mais viável. Ou seja:

- Altero a assinatura da função e replico a alteração em todos os lugares onde a mesma é chamada? Passando como NULL os parâmetros não utilizados?

- Replico a função e altero apenas a passagem de parametros? Isto geraria mais código e dificultaria a manutenção;

- "Perco um tempo", tentando passar os parâmetros dinamicamente? Com o mínimo de impacto nas regras atuais? Esta me parece ser a solução mais adequada, no entanto mais trabalhosa.

Embora a solução pareça obvia, gostaria da opinião dos parceiros aqui do fórum para ajudar a esclarecer essa dúvida.

Por favor, alguém poderia me ajudar a esclarecer este dilema?

Grato.
tora34
Rank: Analista Pleno
Rank: Analista Pleno
Mensagens: 108
Registrado em: Qua, 12 Nov 2008 6:01 pm
Localização: Campo Mourão PR
Renato Pasquini
Oracle Developer

Boa tarde,
esta função que você quer alterar a assinatura é chamada por aplicações Forms&Reports?
Uma forma é criar novos parâmetros e incluir default NULL. Será necessário compilar novamente todos os programas que utiliza a função.
rogenaro
Rank: DBA Pleno
Rank: DBA Pleno
Mensagens: 232
Registrado em: Sex, 30 Mar 2007 7:26 pm
Localização: Londrina - PR
Rafael O. Genaro

Como o tora34 disse, você poderia criar novos parâmetros com valores default.
Digamos que prc_b tenha a seginte assinatura:

Selecionar tudo

procedure prc_b 
( param1 number
, param2 number
, param3 number
) is 
...
Você pode adicionar os parâmetros param4 e param5:

Selecionar tudo

procedure prc_b 
( param1 number
, param2 number
, param3 number
, param4 varchar2 default null
, param5 date default sysdate
) is 
...
Informando parâmetros default, você não precisa informá-los ao executar a sua procedure. Desta forma só é necessário recompilar os objetos já existentes (pois ficarão inválidos), sem alterar em nada a chamada.

Algumas formas que você poderia chamar esta procedure seriam:

Selecionar tudo

prc_b( 1, 2, 3 );
prc_b( 1, 2, 3, 'param4' );
prc_b( 1, 2, 3, 'param4', sysdate+5 );
prc_b( param1 => 1, param3 => 3, param2 => 2, param5 => sysdate-1 ); -- sem informar o parametro 4. Para "pular" um parâmetro, é necessário informar a posição de cada parâmetro.
Tinho
Rank: DBA Sênior
Rank: DBA Sênior
Mensagens: 318
Registrado em: Seg, 16 Nov 2009 4:50 pm
Localização: São Paulo - SP

Bom dia,

Não, ela é chamada via requisição HTTP pelo browser através de uma tela HTML (página). Se trata do Oracle Web Application utilizando os pacotes HTP.P.

Primeiramente obrigado. A sua sugestão seria uma solução, se dentre as exigências não estivesse o fato de que a alteração da assinatura da PACKAGE não deveria gerar impactos nas demais PACKAGES. Ainda assim, as outras packages que eu tenho que alterar estão lockadas para outros analistas que estão desenvolvendo outros projetos paralelos ao meu, ou seja, as minhas alterações não podem impactar nas outras rotinas e ainda teria que fazer um merge e alinhar com o mesmo a prioridade para a subida em produção. O problema não é o trabalho em si, mas sim o impacto que uma "simples" alteração pode causar à aplicação e ao banco.

O que eu quero e preciso e minimizar isto.

No entanto a alteração que eu preciso fazer é a inclusão de uma sub-rotina dentro de uma rotina já existente. Exemplo, existe um cadastro de funcionários e eu preciso incluir uma nova funcionalidade que vai permitir ao funcionário incluir seus dependentes. Isto é feito dentro da mesma procedure de determinada package. Acontece que na rotina de inclusão de funcionários, já é feito uma série de validações e a cada validação existe relação com outras chamadas a package e procedure. Como neste caso a indicação dos dependentes depende de algumas das validações feita na rotina anterior, e compartilham objetos em comum. A idéia inicial era aproveitar toda essa "estrutura" já existente para fazer as validções referente a nova funcionalidade e incluir os comandos DML para a inserção dos dependentes.

Eis a questão. Como as duas rotinas utilizam o mesmo objeto e na nova rotina eu preciso passar novos parametros de entrada, como altero uma sem afetar na outra? E ainda não afetar outros objetos que chamam a mesma procedure de sua respectiva package?

Por isso, citei o conceito de orientação a objetos (objeto-relacional), pois os próprios recursos do banco oferecem uma solução para este caso. Que seria utilizar o polimorfismo onde um método pode possuir a mesma assinatura mas assumir comportamentos diferentes sem ter a necessidade da replicção do código. Eu já vi exemplos e achei estudos de caso utilizando o TYPE Object e sobreposição de métodos, bem como passagem de parametros dinamicos e utilização do tipo de dado ANYDATA. Mas se eu tentar aplicar este conceito, de qualquer maneira vou ter que alterar a assinatura da procedure, além do que vou estar aplicando o conceito de O.O em uma aplicação desenvolvida de forma procedural. Vai ficar uma miscelania.

Alguma alternativa?

--

Até o tempo de eu terminar de editar a minha resposta (acima) em relação a sugestão do tora34. Eu vi a sua resposta, rogenaro. Agradeço a atenção também. E não havia me atentado ao detalhe de que se eu declarar o parametro como default null (como citado pelo tora34 também) eu não preciso informá-los no momento da execução da procedure. Mas mudando a assinatura, eu não precisarei alterá-las nos outros lugares em que a mesma é chamada?

Se for isso acho que já resolve!

Abçs.,
tora34
Rank: Analista Pleno
Rank: Analista Pleno
Mensagens: 108
Registrado em: Qua, 12 Nov 2008 6:01 pm
Localização: Campo Mourão PR
Renato Pasquini
Oracle Developer

Bom dia,
crie um script para recompilar os objetos invalidados no banco de dados após a alteração da package.
Acredito que o DBA já possua um script criado para isto. Basicamente é utilizar o dicionário de dados para buscar todos os objetos inválidos no banco de dados e compilar.
rogenaro
Rank: DBA Pleno
Rank: DBA Pleno
Mensagens: 232
Registrado em: Sex, 30 Mar 2007 7:26 pm
Localização: Londrina - PR
Rafael O. Genaro

Tinho, não há necessidade de alterar nenhum dos outros objetos que referenciam a procedure que você irá alterar, contato que os parâmetros novos tenham valores default (como o valor é default, a assinatura antiga ainda continuará válida para os objetos já existentes).

O único problema é que estes objetos serão invalidados, e precisarão ser recompilados (somente recompilados, sem necessidade de alterações), tal como ocorreria caso uma tabela referenciada pela procedure sofresse alguma alteração em um campo que não é utilizado dentro da mesma.
Tinho
Rank: DBA Sênior
Rank: DBA Sênior
Mensagens: 318
Registrado em: Seg, 16 Nov 2009 4:50 pm
Localização: São Paulo - SP

Sim tora34, acredito também que o DBA já deva ter algum script para essa finalidade. Muito agradecido.

E rogenaro, obrigado também pelos esclarecimentos.

Abç.
Responder
  • Informação
  • Quem está online

    Usuários navegando neste fórum: Nenhum usuário registrado e 6 visitantes