DNATech :: 📚 ReadStackParameters: quando o contexto existe, mas o Protheus não entrega

_Créditos das imagens: ChatGPT

## 📚 ReadStackParameters: quando o contexto existe, mas o Protheus não entrega

Quem trabalha com **Pontos de Entrada no Protheus** já entendeu uma verdade inconveniente:
👉 o sistema **sabe tudo**, mas **entrega pouco contexto**.

E foi exatamente desse abismo que nasceu o **ReadStackParameters**.

### O problema real : contexto

No Protheus, os Pontos de Entrada foram criados para **estender o sistema sem quebrar o contrato**. Beleza na teoria.
Na prática, muitos PEs:

* São executados **dentro de loops**
* Operam **item a item**
* Dependem de cálculos **já realizados pelo core**
* Mas recebem **parâmetros insuficientes**

O resultado? Código redundante, recalculando o que **já foi calculado**.

### O caso crítico: MT150GRV no MATA150

No **MATA150 (Atualização de Cotação)**, o PE `MT150GRV` é executado **para cada item**, durante a gravação.
Neste contexto, considerando que preciso obter os impostos (por item), devidamente calculados e em memória, para armazená-los em tabela proprietária para composição de preços. Mas...

Ele recebe basicamente:

* `nOPCx` → Inclusão, Alteração ou Exclusão

Só isso.

O problema é óbvio:

* `nOPCx` diz **o que o usuário escolheu**
* Mas não diz **qual item está sendo processado**

A variável que resolve isso — `nX`, índice do loop — é:

* Local
* Interna
* Não exposta
* Não passada ao PE

Mas o sistema **já calculou os impostos por item**.
Eles estão em memória.
O contexto existe.

Mesmo assim, o desenvolvedor é forçado a:

* Recalcular impostos
* Reexecutar rotinas fiscais complexas
* Lidar com erros de arredondamento
* Repassar parâmetros sensíveis manualmente

Tudo isso **sem necessidade técnica real**.

---

## Por que o ReadStackParameters foi criado

O **ReadStackParameters** nasce como uma resposta pragmática a essa pergunta incômoda:

> *Se o Protheus já tem a informação na stack, por que eu não posso lê-la?*

A ideia não é hackear.
Não é quebrar encapsulamento.
Não é mutar variáveis internas.

👉 É **ler contexto**.

### O que o ReadStackParameters faz

* Permite acessar **variáveis locais, static, etc, de funções em níveis superiores da stack**
* Atua de forma **somente leitura**
* Não altera fluxo, estado ou comportamento do core
* Apenas **recupera informações já existentes**

Ou seja:
Ele **restaura/expõe o contexto perdido** quando o PE é chamado.

No caso do MT150GRV:

* Com `nX`, é possível acessar os impostos já apurados por item
* Evita recálculo
* Evita inconsistências
* Mantém integridade fiscal
* Reduz complexidade e risco

```xBase
//Obtenho a posição do Item que está sendo gravado. Deveria vir como parâmetro do PE U_MT150GRV
//Utilizo StackParameters():ReadStackParameters para obter a informação de nX, local em A150Grava, (que representa o item a ser gravado).
nXA150GRAVA:=dna.tech.StackParameters():ReadStackParameters("A150GRAVA","NX","LOCAL")

//Obtem o Imposto de PIS à partir das informações já calculadas pelo sistema padrão
//Valor do PIS
_nValPIS:=MaFisRet(nXA150GRAVA,"IT_VALPS2")
//Base de calculo do PIS
_nBasePIS:=MaFisRet(nXA150GRAVA,"IT_BASEPS2")
//Aliquota de calculo do PIS
_nAliqPIS:=MaFisRet(nXA150GRAVA,"IT_ALIQPS2")

//Obtem o Imposto de COFINS à partir das informações já calculadas pelo sistema padrão
//Valor do COFINS
_nValCOF:=MaFisRet(nXA150GRAVA,"IT_VALCF2")
//Base de calculo do COFINS
_nBaseCOF:=MaFisRet(nXA150GRAVA,"IT_BASECF2")
//Aliquota de calculo do COFINS
_nAliqCOF:=MaFisRet(nXA150GRAVA,"IT_ALIQCF2")

```

---

## O problema não é o PE. É o contrato incompleto.

O erro não está em existir um PE dentro de um loop.
O erro está em **não fornecer o contexto mínimo de execução**.

Hoje, o contrato implícito é:

> “Aqui está um gancho. Se vire.”

Isso força soluções:

* Invasivas
* Repetitivas
* Difíceis de manter
* Altamente acopladas

O **ReadStackParameters** é um sintoma claro de que:

> O modelo atual de extensibilidade está incompleto.

---

## Como isso deveria ser resolvido “by TOTVS”

A solução ideal **não é** cada cliente criar sua própria versão de leitura de stack.

A solução ideal seria a TOTVS fornecer algo como:

### 1️⃣ Uma API oficial de contexto de execução

Algo conceitualmente assim:

* Leitura **somente leitura**
* Escopo controlado
* Sem acesso arbitrário
* Com garantia de estabilidade

Exemplo conceitual:

* `FWExecutionContext():Get("MATA150","A150Grava","nX")`
* `FWExecutionContext():Get("MATA150","A150Grava","aImpostos")`
* `FWExecutionContext():Has("MATA150","A150Grava","nItem")`

Nada de mutação.
Nada de side effects.

---

### 2️⃣ Contrato explícito de execução do PE

Documentar claramente:

* Se o PE roda em loop
* Se roda por item
* Se há contexto acumulado
* Quais variáveis são relevantes naquele momento

Isso transforma o PE de “gancho cego” em **extensão consciente**.

---

### 3️⃣ Compatibilidade com legado (sem quebrar nada)

* Não precisa alterar PEs existentes
* Não precisa mudar assinatura
* Apenas **expõe contexto existente**

Ou seja:
Zero impacto retroativo, ganho arquitetural imediato.

---

## ReadStackParameters não é gambiarra. É um pedido de socorro.

Quando um desenvolvedor cria algo como o ReadStackParameters, ele não está tentando burlar o sistema.

Ele está dizendo:

> “O Protheus sabe o que eu preciso.
> Só não me deixa acessar.”

Isso é um sinal claro de maturidade do ecossistema — e também de um ponto que precisa evoluir.

---

## Conclusão

* O Protheus **já calcula**
* O Protheus **já sabe**
* O Protheus **já tem em memória**

O que falta é **entregar o contexto**.

O **ReadStackParameters** existe porque:

* O contrato dos PEs é insuficiente
* A extensibilidade perde contexto
* O desenvolvedor precisa de previsibilidade e precisão

Uma solução oficial da TOTVS, segura e somente leitura, não seria apenas bem-vinda —
seria um **salto de qualidade arquitetural** no modelo de extensibilidade do Protheus.

---

#ReadStackParameters, #Protheus, #PontosDeEntrada, #Extensibilidade, #ArquiteturaDeSoftware, #ContextoDeExecucao, #AdvPL, #TLPP, #ERP, #BoasPraticas

Torne-se um Sponsor: 🥊(дави)={0.5x[(Налдо)+(Алине)]}🥊

Comentários

Postagens mais visitadas