ParamType com tlpp

Boa tarde!

Estou com uma dúvida ao realizar tipagem de parâmetros em classes tlpp. Observe o exemplo a seguir em AdvPL usando ParamType:


Method Send(aBody, cMsgErr) Class WorkMail

    ParamType 1 Var aBody         As Array
    ParamType 2 Var cMsgErr     As Character Default ''

    // meus processamentos

Return

Desejo que o primeiro método seja obrigatoriamente em array, enquanto o segundo será em caractere mas pode ser enviado como nulo.

Sei que na declaração do método eu consigo tipar os parâmetros, mas existe alguma forma de tipar e atribuir um valor default caso o mesmo seja nulo? Ou devo continuar usando ParamType?

Grato.

Giordano,

O TLPP dá suporte a tipagem de parâmetros de forma até mesmo a gerar exceção quando o parâmetro é recebido em um tipo diferente do esperado, porém permite valores nulos, logo a questão de todos os parâmetros não serem obrigatórios continua.

O ParamType permite forçar um tipo para o parâmetro, gerando exceção em caso de valor diferente, parâmetros obrigatório e valores padrões.

Ele ainda pode ser utilizado, porém agora a verificação de tipo é feita pelo binário em TLPP, ela acabaria sendo feita duas vezes.

Você poderia apenas utilizar o default para o questão de valores padrões, agora a questão de parâmetros obrigatórios, teria que ser feita manual ou utilizando o ParamType.

Eu pessoalmente evito o uso do ParamType, ele faz verificações de valores nulos, ValType, atribuições etc... E tudo isso por um único parâmetro, para funções/métodos que não serão chamadas em loop, isso não faz grande diferença, porém se sua função/métodos ser chamado dentro de um loop, você perceberá a questão de performance. Caso queira ver tudo isso, recomendo gerar o PPO de uma função/método que foi usado o ParamType, verá um código um tanto quanto extenso. Se desejar verificar as questões de performance citadas, gere um LogProfiler da execução com e sem o ParamType.

Obs.: O default teve seu funcionamento alterado devido ao TLPP, pois caso a variável esteja tipada, pode não ser possível verificar se ela é nula dentro de um IIF, logo ele passou de uma verificação de nil para um ValType, então o default também faz um ValType para comparar se é U (nulo).


Aqui um pequeno exemplo utilizando seu método, execute ele e veja os valores no console, pode ficar mais claro o funcionamento da tipagem em TLPP:


#include "protheus.ch"

//-------------------------------------------------
/*/{Protheus.doc} u_TestingParameters
Função para teste de parâmetros tipados em TLPP

@author Daniel Mendes
@since 08/08/2022
@version 1.0
/*/
//-------------------------------------------------
function u_TestingParameters()
local oWorkMail as object

oWorkMail := WorkMail():new()
oWorkMail:send()
oWorkMail:send({"Xisto"})
oWorkMail:send({"Xisto"}, "Xisto")
oWorkMail:send(, "Xisto")

oWorkMail:send(1, ) //Vai gerar exceção, pois o tipo recebido não é suportado
oWorkMail:send(, 1) //Também geraria exceção, porém não vai chegar nessa linha...

return

//-------------------------------------------------
/*/{Protheus.doc} WorkMail
Classe para teste de parâmetros

@author Daniel Mendes
@since 08/08/2022
@version 1.0
/*/
//-------------------------------------------------
class WorkMail
    public method new() as object
    public method send()
endclass

//-------------------------------------------------
/*/{Protheus.doc} new
Construtor da classe

@author Daniel Mendes
@since 08/08/2022
@version 1.0
/*/
//-------------------------------------------------
method new() as object class WorkMail
return self

//-------------------------------------------------
/*/{Protheus.doc} send
Método para teste de parâmetros

@param aBody, array, Corpo
@param cMsgErr, character, Mensagem de erro

@author Daniel Mendes
@since 08/08/2022
@version 1.0
/*/
//-------------------------------------------------
method send(aBody as array, cMsgErr as character) class WorkMail

conout("aBody", valType(aBody), aBody, "")
conout("cMsgErr", valType(cMsgErr), cMsgErr, "")

return

Daniel, fiquei com uma dúvida, usando ParamType eu posso ter parâmetros com tipos mistos (ex.: uPar podendo ser caracter ou array), seria possível fazer isso diretamente no TLPP também?

Daniel, sobre essa forma de tipagem, eu senti muita dificuldade porque da forma que está (o fato dos parâmetros não serem obrigatório) força sempre fazermos algum tipo de tratamento dentro do fonte verificando o tipo recebido.

Se o parâmetro tiver que ser obrigatório teremos que verificar se não está nulo, e não sendo obrigatório, também precisamos fazer algum tratamento quando o mesmo é nulo para poder utilizar corretamente dentro do programa.

Em resumo acho que desta forma quase que inevitavelmente temos que avaliar os parâmetros passados, um ou outro caso muito específico pode não precisa ser feito nenhum tratamento posterior para os parâmetros. Além do caso de ter várias limitações, como só aceita 1 tipo (o paramtype aceita vários), o paramtype também consegue verificar o objeto esperado, aceita valores obrigatórios, valores default. Na prática o uso é muito limitado, tornando o paramtype bastante vantajoso apesar de um pouco menos performático.

Concordo, a falta de definir um valor default para os parâmetros é um dos principais motivos que eu uso ParamType, e pelo menos nesse primeiro momento continuarei utilizando nos fontes em TLPP.

Eu também gostaria de um valor default nativo, mas até o momento, isso não foi implementado.

Dois recursos que já cobririam 99% das situações seria valor default e parâmetros obrigatórios, isso já seria trataria quase que a totalidade das situações onde usamos o paramtype. Fica ai como sugestão do time de tecnologia pensar em uma forma de criar essa melhoria.