Pragiva — Tecnologia na prática

Namespace em TLPP: como organizar chamadas entre arquivos

Namespace em TLPP: um fonte declara, outro chama a função pelo nome completo ou com using namespace, em dois exemplos, e o que só se confirma rodando.

Desenvolvimento Guia de processo 2 min de leitura

Assista o vídeo

Nesta página4 seções

Resposta curta: um fonte .tlpp declara namespace logo depois dos includes. Outro fonte, de outro namespace, chama uma função dele de duas formas: pelo nome completo (namespace.funcao(...)) ou declarando using namespace e chamando só pelo nome da função. Dentro do próprio namespace, a chamada é pelo nome simples.

Como as chamadas aparecem

Isto foi conferido em código .tlpp real, sem depender de documentação:

SituaçãoComo aparece
Declarar o namespacenamespace totvs.protheus.backoffice.<area>.<recurso>, depois dos #include
Chamar dentro do mesmo namespacenome simples da função
Chamar de outro namespace, com importaçãousing namespace <namespace> no topo e chamada pelo nome simples
Chamar de outro namespace, sem importação<namespace>.<funcao>(...), por extenso

Cada caso aparece em mais de um arquivo. Um mesmo namespace também pode estar espalhado em mais de um arquivo: há dois fontes distintos declarando o mesmo namespace de utilitários.

Dois arquivos, nomes neutros

O primeiro fonte declara o namespace e uma função comum.

ADVPL / TLPP
#include "totvs.ch"

namespace exemplo.comum.texto

//-------------------------------------------------------------------
// Padroniza um código: remove espaços das pontas e põe em maiúsculas.
//-------------------------------------------------------------------
Function normalizarCodigo( cCodigo as character )

    Local cRetorno := Upper( AllTrim( cCodigo ) ) as character

Return cRetorno

O segundo fonte, em outro namespace, usa a função das duas formas.

ADVPL / TLPP
#include "totvs.ch"

namespace exemplo.vendas.pedidos

// Importa o namespace do primeiro fonte.
using namespace exemplo.comum.texto

Function prepararChave( cProduto as character )

    // 1) Pelo nome simples, possível por causa do using namespace.
    Local cChave := normalizarCodigo( cProduto ) as character

Return cChave

Function prepararChaveCompleta( cProduto as character )

    // 2) Pelo nome completo, sem depender do using namespace.
    Local cChave := exemplo.comum.texto.normalizarCodigo( cProduto ) as character

Return cChave

O nome completo é o namespace inteiro, um ponto e o nome da função. As duas formas apontam para a mesma função; a escolha é de leitura. O nome completo deixa claro de onde a função vem. O using namespace reduz repetição quando o fonte chama muitas funções do mesmo namespace.

Note que os parâmetros e variáveis dos exemplos não usam nomes reservados do Protheus (cFilial, cEmpAnt, cFilAnt, cNumEmp, cUserName).

Como organizar

  • Use o namespace para refletir a área e o recurso, como se vê no código real: prefixo da organização, área, recurso.
  • Concentre utilitários compartilhados num namespace próprio e importe-o onde forem usados, em vez de copiar a função.
  • Prefira o nome completo quando o fonte chama uma única função de fora; prefira using namespace quando chama várias.
  • O using namespace não altera onde a função mora, só como você a escreve na chamada.

O que este artigo não afirma

  • Não afirma qual erro aparece quando a chamada não é resolvida. Esse comportamento depende de compilar e executar.
  • Não afirma que todo erro de função não encontrada vem de namespace. Há outras causas para isso, e nenhuma delas foi tratada aqui.
  • Não afirma que namespace resolve colisão de nomes entre fontes no repositório de objetos (RPO). Isso não foi verificado.
  • Não afirma o que vale para User Function dentro de fonte com namespace. Existem fontes com User Function e namespace, mas a regra de chamada externa a ela não foi confirmada. Antes de depender dela, teste no seu ambiente.

Para a diferença mais ampla entre AdvPL e TLPP, veja API REST em TLPP: o que muda em relação ao AdvPL.

Continue por aqui