Power AppsTécnico

Padrões de Power Apps que não quebram: componentes, variáveis, coleções e erro tratado

Nomenclatura, estado com uma fonte de verdade, IfError em todo Patch, OnStart leve e soluções com variáveis de ambiente: o que sustenta um app em produção.

Erick MacedoConsultor principal, Power Apps e Power Automate6 min de leitura

Uma concessionária de energia com 80 técnicos de campo usava um app de inspeção feito dentro de casa. Funcionava bem no escritório. No campo, onde a rede cai, o Patch falhava sem que o técnico percebesse, e cerca de um quinto das inspeções do mês não chegava à base. A correção levou dois dias. A investigação levou duas semanas, porque o app tinha 14 variáveis chamadas var1 a var14, três telas chamadas Screen2, Screen2_1 e Screen2_2 e nenhum tratamento de erro.

Desenvolvo apps de negócio desde 2020, e os incidentes de produção que vejo têm quase sempre as mesmas causas. Os padrões abaixo são os que o nosso time aplica em todo app que vai para produção, com as fórmulas que usamos.

Nomenclatura: o app precisa ser legível daqui a seis meses

Padrão de nome é o investimento de menor custo e maior retorno em Power Apps. Sem ele, quem herda o app passa horas descobrindo o que cada controle faz. O padrão que usamos segue o whitepaper de boas práticas da Microsoft, com prefixo de três letras e nome em português que diz o propósito:

  • Telas: scr (scrInicio, scrListaInspecoes, scrNovaInspecao).
  • Galerias: gal. Formulários: frm. Botões: btn. Rótulos: lbl. Entradas de texto: txt. Caixas de combinação: cmb. Listas suspensas: drp. Seletores de data: dtp.
  • Variáveis globais: gbl (gblInspecaoAtual). Variáveis de contexto: loc (locModoEdicao). Coleções: col (colEquipamentos). Fórmulas nomeadas: nf (nfEhGestor).
  • Componentes: cmp (cmpCabecalho). Fontes de dados com o nome da tabela, sem abreviação.

Dois controles com o mesmo prefixo e nomes parecidos, como lblTitulo e lblTituloTela, já são sinal de que falta uma decisão sobre o que cada um faz.

Estado: uma fonte de verdade

A maior parte dos bugs de "o valor estava certo na outra tela" vem de estado duplicado: a mesma informação em uma variável global, uma de contexto e uma coleção, atualizadas em momentos diferentes. A regra é uma: cada informação mora em um lugar só, e todo o resto lê de lá.

Para valores que derivam de outros (o usuário logado, se ele é gestor, a planta em que ele trabalha), use fórmulas nomeadas em App.Formulas: elas são calculadas quando necessário e nunca ficam desatualizadas, porque não há Set para esquecer. Set fica para estado que muda por ação do usuário e é lido em mais de uma tela. UpdateContext fica para estado de uma tela só. With resolve cálculo local sem criar variável.

App.Formulas, Set, UpdateContext e Withpowerfx

// App.Formulas: valores derivados, sem Set para esquecer
nfUsuario = User();
nfEhGestor = !IsBlank(LookUp(Gestores, Email = nfUsuario.Email));

// Set: estado global que muda por ação do usuário (OnSelect da galeria)
Set(gblInspecaoAtual, galInspecoes.Selected);

// UpdateContext: estado só desta tela (OnSelect do botão Editar)
UpdateContext({ locModoEdicao: true });

// With: cálculo local, sem variável sobrando (Text de um rótulo)
With(
    { itens: Filter(ItensInspecao, InspecaoID = gblInspecaoAtual.ID) },
    CountRows(itens) & " itens, " & CountIf(itens, !Conforme) & " não conformes"
)

Erro tratado em todo Patch e todo formulário

O Patch da concessionária falhava em silêncio porque ninguém olhava o resultado dele. Em Power Fx, Patch devolve o registro gravado ou um erro, e IfError decide o que fazer em cada caso. O padrão: mensagem clara para o usuário com Notify, e navegação só depois do sucesso.

OnSelect do botão Salvar: Patch com IfErrorpowerfx

IfError(
    Patch(
        Inspecoes,
        Defaults(Inspecoes),
        {
            Titulo: txtTitulo.Text,
            Equipamento: cmbEquipamento.Selected,
            Resultado: drpResultado.Selected.Value,
            DataInspecao: dtpData.SelectedDate,
            InspetorEmail: nfUsuario.Email
        }
    ),
    // Deu erro: avisa e fica na tela, com o que foi digitado
    Notify(
        $"Não foi possível salvar a inspeção: {FirstError.Message}",
        NotificationType.Error
    ),
    // Deu certo: confirma e volta para a lista
    Notify("Inspeção salva.", NotificationType.Success);
    Navigate(scrListaInspecoes, ScreenTransition.None)
)

Em apps criados há mais tempo, confira em Configurações se a opção de gerenciamento de erros no nível de fórmula está ligada; sem ela, o erro do Patch vai para a função Errors da fonte e o IfError não o captura. Em formulários, a mesma lógica mora nas propriedades OnSuccess e OnFailure do controle: no OnFailure, Notify(frmInspecao.Error, NotificationType.Error).

Formulário ou Patch? Formulário para cadastro simples de uma tabela: validação de campos obrigatórios, modos de novo, edição e exibição, e menos fórmula. Patch quando a tela grava em mais de uma tabela, quando o layout foge do formulário ou quando é preciso gravar um lote. Misturar os dois na mesma tela é fonte de registro duplicado.

No campo, o padrão ganha uma peça: testar Connection.Connected antes de gravar. Sem rede, o registro vai para uma coleção local salva com SaveData, e um botão de sincronizar faz o Patch quando a rede volta. Foi isso que resolveu o caso dos técnicos.

Desempenho: OnStart leve e chamadas em paralelo

App lento para abrir quase sempre tem um OnStart que carrega tabelas inteiras em coleções "para usar depois". Além do tempo, cada ClearCollect de tabela grande esbarra no limite de 500 registros, como explicamos em delegação no Power Apps. O OnStart carrega só o que todas as telas usam, em paralelo com Concurrent. O que uma tela usa fica no OnVisible dela.

App.OnStart: só o compartilhado, em paralelopowerfx

Concurrent(
    ClearCollect(colResultados, Choices(Inspecoes.Resultado)),
    ClearCollect(colMeusEquipamentos, Filter(Equipamentos, EmOperacao)),
    ClearCollect(colParametros, Parametros)
);
// O que só uma tela usa vai no OnVisible dela.
// Nunca: ClearCollect(colTudo, Inspecoes). Lento, e para em 500 registros.

Três outros pontos pesam: imagens, que devem ser comprimidas antes de entrar no app ou vir de uma biblioteca do SharePoint em vez de embutidas; LookUp dentro de galeria, que gera uma chamada por linha (traga a coluna relacionada na consulta ou use a relação do Dataverse); e controles demais na mesma tela. O Monitor, nas ferramentas avançadas do editor, mostra cada chamada de rede, a duração e o que voltou. É a primeira ferramenta a abrir quando alguém reclama de lentidão.

Componentes para tudo o que se repete

Cabeçalho, botão padrão, mensagem de confirmação e rodapé aparecem em toda tela. Em componente de biblioteca, mudam em um lugar e atualizam em todos os apps que a usam. O componente recebe o que varia por propriedade de entrada e devolve ações por propriedade de comportamento.

Componente de cabeçalho: propriedade de entrada e de comportamentopowerfx

// Componente cmpCabecalho, em uma biblioteca de componentes.
// Propriedades personalizadas: Titulo (entrada, texto)
// e AoVoltar (saída, comportamento).

// Dentro do componente
lblTitulo.Text:      cmpCabecalho.Titulo
btnVoltar.OnSelect:  cmpCabecalho.AoVoltar()

// Em cada tela que usa o componente
cmpCabecalho_1.Titulo:    "Inspeções de campo"
cmpCabecalho_1.AoVoltar:  Navigate(scrInicio, ScreenTransition.None)

Comece a biblioteca com três componentes (cabeçalho, botão primário e caixa de confirmação) e cresça conforme a repetição aparecer. Componente demais cedo demais atrapalha tanto quanto nenhum.

Solução, variável de ambiente, dono e versão

App de negócio vive dentro de uma solução, em um ambiente de desenvolvimento, e chega à produção por exportação ou pipeline. A solução carrega o app, os fluxos, as tabelas e as variáveis de ambiente. A variável de ambiente do tipo fonte de dados é o que permite apontar o app para a lista ou a tabela de desenvolvimento em um ambiente e para a de produção no outro, sem tocar em fórmula. Publicar direto do ambiente onde se desenvolve é a forma mais rápida de perder a versão que funcionava.

Cada app tem dono e suplente registrados, uma página de documentação (o que faz, quem usa, fontes, fluxos ligados) e nota de versão a cada publicação. O editor guarda as versões anteriores e permite restaurar; a nota diz qual restaurar. O App Checker roda antes de toda publicação, e nenhum aviso de delegação ou de acessibilidade fica sem decisão. As regras de ambientes e de governança estão em governança na Power Platform.

Antes de publicar

  • Controles, telas, variáveis e coleções seguem o padrão de nome (scr, gal, btn, gbl, loc, col)
  • Cada tela tem um propósito e um nome que diz qual é
  • Acessibilidade conferida no App Checker: ordem de tabulação, texto alternativo e contraste
  • Todo Patch e todo formulário têm IfError ou OnFailure com mensagem para o usuário
  • Nenhum aviso de delegação pendente no App Checker
  • Conexões revisadas: nenhuma em nome de quem vai sair, nenhuma de teste apontando para produção
  • App dentro de uma solução, com editor (publisher) da empresa
  • Fonte de dados por variável de ambiente, com valor de desenvolvimento e de produção
  • Documentação de uma página: o que o app faz, quem usa, fontes de dados e fluxos ligados
  • Dono e suplente definidos e informados no cadastro do app
  • Nota de versão escrita e versão anterior identificada para restaurar
  • Testado no celular de verdade, com rede ruim e sem rede, no mínimo no fluxo principal

Faça

  • Definir cada informação uma vez, em App.Formulas ou no OnStart, e ler em todo lugar.
  • Usar formulário para cadastro simples de uma tabela e Patch quando a tela tem várias tabelas ou layout próprio.
  • Carregar no OnStart só o que todas as telas usam, dentro de Concurrent.
  • Colocar cabeçalho, botões e mensagens em componentes de biblioteca, com propriedade de entrada para o texto.
  • Abrir o Monitor na primeira reclamação de lentidão. Ele mostra cada chamada e quanto tempo levou.

Evite

  • Criar variável de contexto e global com o mesmo nome em telas diferentes.
  • Chamar LookUp dentro de cada linha da galeria. Com 100 linhas são 100 chamadas.
  • Publicar direto do ambiente onde você desenvolve. Sem solução, voltar atrás é na sorte.
  • Deixar a mensagem de erro padrão do Power Apps para o usuário. Ela some em segundos e ninguém registra.
  • Usar Collect dentro de ForAll para gravar lote. Patch aceita uma tabela de registros de uma vez.

O próximo passo prático é pegar o app mais usado da sua área e passar o checklist acima nele, sem mexer em nada ainda. A lista do que falhou é o plano de trabalho das próximas duas semanas. Para equipes que vão construir e sustentar vários apps, a Trilha Citizen Developer cobre esses padrões em 36 horas, com os dados da empresa.

Fontes

Preços, nomes de plano e limites mudam. Confira sempre a tabela oficial da Microsoft antes de decidir.

Perguntas frequentes

O que mais perguntam sobre este assunto

Variável global ou de contexto no Power Apps?
Global (Set) quando mais de uma tela lê o valor e ele muda por ação do usuário, como o registro selecionado. De contexto (UpdateContext) quando só aquela tela precisa, como o modo de edição de um formulário. Para valores derivados, como o usuário logado ou se ele é gestor, prefira fórmulas nomeadas em App.Formulas, que dispensam Set e nunca ficam desatualizadas. O erro comum é guardar a mesma informação nos dois tipos.
Patch ou formulário no Power Apps?
Formulário para cadastro simples de uma tabela: ele cuida de campos obrigatórios, modos e validação com menos fórmula. Patch quando a tela grava em várias tabelas, tem layout próprio ou precisa gravar lote. Nos dois casos, trate o erro: IfError no Patch e OnFailure no formulário, sempre com Notify para o usuário.
Como testar um Power Apps antes de publicar?
Em camadas. O App Checker aponta delegação, acessibilidade e erros de fórmula. O Monitor mostra cada chamada de rede durante um teste manual. Um ambiente de teste com cópia dos dados e volume realista (milhares de linhas) revela o que o ambiente de desenvolvimento esconde. E o fluxo principal é testado em um celular de verdade, com rede ruim e sem rede.
Preciso de solução para um app pequeno?
Se o app é de uma pessoa ou de uma equipe que o abandona sem prejuízo, não. Se alguém depende dele para trabalhar, sim: a solução dá exportação e importação entre ambientes, variáveis de ambiente para trocar a fonte, histórico de versões e o caminho para pipelines. Criar o app dentro de uma solução custa dois minutos no início e semanas quando feito depois, com fórmula para reapontar e conexão para refazer.

Próximo passo

Quer isso funcionando na sua empresa?

A Disruptivos treina equipes e entrega projetos em Microsoft 365 e Power Platform. Conte o seu cenário no formulário e a gente responde com uma proposta.

Para a sua empresa

Trilha Citizen Developer

36 horas, turma fechada: Power Apps, Power Automate e Dataverse com os padrões de quem sustenta app em produção.

Ver o treinamento

Para você aprender

Formação Power Apps

11 apps reais construídos com estes padrões, de componentes a soluções e pipelines.R$ 697

Ver o curso
Ir para o formulário

Fale Conosco

Conte seu desafio, respondemos em até 1 dia útil

Diagnóstico Estratégico Gratuito

Analisamos seu cenário e indicamos a melhor rota para seus objetivos.

Interesse*
Treinamentos Corporativos

Validação de segurança

Essa validação evita envios automáticos sem atrapalhar sua experiência.

Prometemos não utilizar suas informações de contato para enviar qualquer tipo de SPAM.

Leia também