Protheus MVC

Daniel Mendes
Jul 4, 2019 · 5 min read

Para quem não conhece, MVC significa Model-View-Controller. É um padrão de arquitetura que visa separar a aplicação em três camadas.

As três camadas são:

  • Model — Responsável pela manipulação dos dados, CRUD e afins…
  • View — Camada de interação com o usuário
  • Controller — Responsável por receber e interpretar as requisições, digamos que ele que faz a ponte entre a view e o model

Essa arquitetura nos dá diversos benefícios, como melhor manutenabilidade, pois temos uma separação de responsabilidades, criação de interfaces distintas para o mesmo modelo etc.

Existem N frameworks para N linguagens que facilitam a implementação de MVC em seu projeto, para o Protheus, não é diferente.

No MVC do Protheus, sua implementação fica apenas na View e no Model, basicamente com duas magic static functions: ModelDef e ViewDef.

ModelDef
Será a responsável por criar e retornar seu modelo de dados, contendo todas as suas regras de negócio, validações, relacionamentos e… etc

ViewDef
Já essa será a responsável por retornar a sua interface, contendo os campos, grid (colunas/linhas) que serão apresentados para o usuário, abas etc…

O MVC do Protheus também te dá algumas coisas bem ligadas ao Protheus:

  • Inúmeros pontos de entrada… Tipo, são vários mesmo
  • Integração com o EAI
  • Possibilidade de publicar o modelo e consumir o mesmo por REST, retornando json ou xml

Também temos a possibilidade de reaproveitar outras questões, como o browser de apresentação de dados e até de localizar o MVC, criando uma estrutura simples e adicionando comportamentos para países.
Ou seja, bora implementar as rotinas com MVC pra melhorar a manutenção das coisas, vamos partir para a implementação pensando numa rotina padrão do Protheus, contendo então a função principal, o famoso MenuDef, BrowseDef e os principais caras da história, o ModelDef e o ViewDef.

Vou pegar a tabela de Naturezas (SED) para o exemplo simples, apenas uma tabela.

Primeiro vamos começar com as funções que serão consumidas, porém não são o nosso foco:

BrowseDef

Criando dessa forma, um MVC localizado por exemplo, consegue consumir essa função e adiciona comportamentos ao browse principal:

MenuDef

Bem simples e com opções que o MVC te dá na faixa, como a cópia e a impressão:

t

Função Principal

A função principal, que vai instanciar o browse e ativar o mesmo para a exibição da tela principal:

ModelDef

Agora sim! Como trata-se de uma tabela que consta no dicionário de dados (SX2), foi criado o objeto do modelo de dados pela classe MPFormModel, que já tem toda uma inteligência pronta para a persistência de dados. Caso você precise criar um modelo de uma tabela que não consta no dicionário de dados, pode utilizar da classe FWFormModel
Para criar a estrutura, vamos usar a função FWFormStruct, que busca no dicionário de dados toda a estrutura desse alias, como nome, campos, índices etc
Agora basta adicionar a estrutura retornar ao modelo de dados e pronto, temos um modelo já pronto para a persistência na SED:

ViewDef

A View segue um rumo bem simples também, instancio a classe principal da View, retorno o modelo de dados com base na FwLoadModel, que vai me retornar a minha ModelDef, porque não utilizar a ModelDef diretamente? Pois usando essa função, eu verifico também o MVC localizado!
Legal, agora com o modelo e a view prontas, eu pego também a estrutura da view, novamente com a função FwFormStruct, que retornar somente os campos que estão configurados no dicionário de dados para serem exibidos em tela… Pronto, basta adicionar o meu modelo a view e eu já tenho meu fonte MVC pronto!

Adicional… Eu posso publicar o meu MVC com o seguinte comando:

PUBLISH USER MODEL REST NAME DNL_SED SOURCE DNL_SED

Isso me permite consumir o mesmo via REST, utilizando o FWModel, assim não preciso me preocupar que criar uma classe REST!

Caso queira testar, basta colocar esse fonte no Menu de seu módulo, como o SIGAESP, módulo específico para customizações.


Agora… Vamos ao um exemplo com grid, cabeçalho e item, pai e filho… Entre outros termos!

A função principal, a BrowseDef e a MenuDef não tem alterações foram o alias de utilização, portanto, vamos focar somente no ModelDef e ViewDef:

ModelDef:

Temos aqui a diferença do AddGrid, método que permite adicionar o que? Um Grid… Enviado para o modelo o ID do Grid, o ID do Pai desse grid e sua estrutura.

Como temos um grid, temos um relacionamento, de pai para filho, para criar esse relacionamento usamos o método SetRelation, que recebe o ID do Grid, os dados do relacionamento e qual chave ele vai usar para verificar esse relacionamento.

Por fim, criamos a linha única no grid com o SetUniqueLine.

Legal, temos um modelo com pai (fields) e filho (grid) já relacionados!

ViewDef:

A view segue o mesmo padrão anterior, pegando as estruturas que devem ser exibidas.

Aqui novamente vemos o AddGrid e a grande diferença fica onde criamos onde cada item será exibido, com os método CreateHorizontalBox e SetOwnerView, nesse exemplo eu criei apenas dois box cada um pegando 50% da tela, dividindo assim metade para fields e metade para o grid.

A view também permite trabalhar com folders e sheets, porém não vou entrar no mérito, vamos no arroz e feijão mesmo!

Com isso já temos uma rotina MVC que trabalha no modelo pai e filho, sendo que como o modelo já contém o relacionamento, a linha única do grid, não precisamos nos preocupar com nada em relação a persistência do mesmo, o MVC do Protheus já persisti ambas as tabelas envolvidas corretamente.

Importante: Nos exemplos eu coloquei nomes (ID) nos modelos de forma genérica, porem esse é um dado muito importante, pois é muito comum utilizar desse nome para pegar o modelo e efetuar as validações.

Atenção: Caso não tenha reparado, o nome do fonte é muito importante, ele é utilizado no MenuDef, ViewDef. A função FWLoadModel e FWLoadBrw utilizam desse nome para encontrar o modelo e browse.

Bem, é isso… O MVC no geral vai MUITO além disso, com N possibilidades de implementação no model, na view, na reutilização… E por aí vai, fica a seu critério e necessidade!

Abaixo alguns links de documentações sobre o assunto:

MVC

FWFormStruct

FWFormView

MPFormModel

FWMBrowse

TOTVS Developers

Blog técnico do time de engenharia e desenvolvimento da TOTVS

Daniel Mendes

Written by

TOTVS Developers

Blog técnico do time de engenharia e desenvolvimento da TOTVS

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade