terça-feira, 26 de fevereiro de 2008

Argumentos variáveis (varargs) são para os fracos - ou Como o Ensemble lida com isso

Em Caché Object Script (a linguagem padrão pra se desenvolver no Caché da Intersystems) não conseguimos definir métodos que podem ter um número arbitrário de parâmetros, como as VarArgs do Java, ou mesmo as funções com argumentos variáveis do C/C++.

Entretanto, ainda podemos passar como parâmetro, um array ou uma List.

Então, quando me deparo com uma definição de método como esta abaixo... (consta no Adapter EnsLib.SOAP.OutboundAdapter, do Ensemble):

Method InvokeMethod(pMethodName As %String, Output pResult As %RegisteredObject, ByRef pArg1, ByRef pArg2, ByRef pArg3, ByRef pArg4, ByRef pArg5, ByRef pArg6, ByRef pArg7, ByRef pArg8, ByRef pArg9, ByRef pArg10, ByRef pArg11, ByRef pArg12) As %Status


E não estando satisfeito, fui olhar como é que este método estava implementado. Uma pequena amostra abaixo:

        If $D(pArg12)    { Set pResult = $zobjmethod(..%Client,pMethodName,.pArg1,.pArg2,.pArg3,.pArg4,.pArg5,.pArg6,.pArg7,.pArg8,.pArg9,.pArg10,.pArg11,.pArg12) }
elseif $D(pArg11){ Set pResult = $zobjmethod(..%Client,pMethodName,.pArg1,.pArg2,.pArg3,.pArg4,.pArg5,.pArg6,.pArg7,.pArg8,.pArg9,.pArg10,.pArg11) }
elseif $D(pArg10){ Set pResult = $zobjmethod(..%Client,pMethodName,.pArg1,.pArg2,.pArg3,.pArg4,.pArg5,.pArg6,.pArg7,.pArg8,.pArg9,.pArg10) }
elseif $D(pArg9) { Set pResult = $zobjmethod(..%Client,pMethodName,.pArg1,.pArg2,.pArg3,.pArg4,.pArg5,.pArg6,.pArg7,.pArg8,.pArg9) }
elseif $D(pArg8) { Set pResult = $zobjmethod(..%Client,pMethodName,.pArg1,.pArg2,.pArg3,.pArg4,.pArg5,.pArg6,.pArg7,.pArg8) }
elseif $D(pArg7) { Set pResult = $zobjmethod(..%Client,pMethodName,.pArg1,.pArg2,.pArg3,.pArg4,.pArg5,.pArg6,.pArg7) }
elseif $D(pArg6) { Set pResult = $zobjmethod(..%Client,pMethodName,.pArg1,.pArg2,.pArg3,.pArg4,.pArg5,.pArg6) }
elseif $D(pArg5) { Set pResult = $zobjmethod(..%Client,pMethodName,.pArg1,.pArg2,.pArg3,.pArg4,.pArg5) }
elseif $D(pArg4) { Set pResult = $zobjmethod(..%Client,pMethodName,.pArg1,.pArg2,.pArg3,.pArg4) }
elseif $D(pArg3) { Set pResult = $zobjmethod(..%Client,pMethodName,.pArg1,.pArg2,.pArg3) }
elseif $D(pArg2) { Set pResult = $zobjmethod(..%Client,pMethodName,.pArg1,.pArg2) }
elseif $D(pArg1) { Set pResult = $zobjmethod(..%Client,pMethodName,.pArg1) }
else { Set pResult = $zobjmethod(..%Client,pMethodName) }
$$$sysTRACE("Got Result "_pResult)


Tá certo que pela maneira como foi concebida, essa solução nem é tão ruim assim. Isso porque no caso acima, os parâmetros estão sendo sempre passados por referência.

O que me incomoda nem são os trocentos elseifs, ou a "beleza" do código. É a limitação do número de parâmetros. Tá certo que dificilmente são usados 12 argumentos, mas sempre surgem aquelas situações-limite, e um décimo terceiro argumento pode ser necessário. E aí?

Uma solução é ficar alterando a própria API do Ensemble. Como foi feito neste outro post, sobre um problema no Adapter de SQL.

Uma outra solução é largar mão, e procurar outra ferramenta. =P

Eu acho que essa merecia ir pro The Daily WTF.

3 comentários:

Anônimo disse...

credo, essa api do cache, se é q se pode chamar de api, parece ser uma POG total. Isso eu via o pessoal do clipper fazer mto, mas isso era mto antigamente, qdo nao se tinha POO. Tipo, aqueles sistemas antigos de RH, se tivesse que registrar os filhos de um funcionario, o clippeiro alterava a tabela funcionario assim. filho1, filho2, filho3, filho4. mas se o cara tivesse um quinto filho, dai fod..., teria que mandar pra adoção, hehehe.

Pelo visto, o pessoal q desenvolveu esse cache nunca ouviu falar de POO, mas sim de POG.

Andarilho disse...

Huahuuhauh, essa de POO e POG foi muito boa, como é que eu não havia pensado nisso? =P

E isso porque o pessoal ainda vendo o Caché como sendo "pós-relacional", "banco de dados orientado a objeto", e outras falácias.

CintiaYamane disse...

huahuaa.. e eu to entendendo tudo do que vcs estão falando... pós relacional.. deve ser tipo.. final de namoro...