Skip to main content

Compreender o contexto de execução

Objetivos de aprendizagem

Após concluir esta unidade, você estará apto a:

  • Saber quais métodos usar para invocar o Apex
  • Escrever um acionador para um Salesforce Object
  • Observar como o contexto de execução funciona executando código no Console do desenvolvedor
  • Compreender como o administrador limita os padrões de design do impacto
  • Compreender a importância de trabalhar com operações em massa
Nota

Nota

O desafio prático para esse emblema está traduzido para japonês, espanhol (América Latina) e português (Brasil). Para definir o idioma do seu Trailhead Playground, siga essas instruções. A tradução pode estar desatualizada. Se você não conseguir passar no desafio usando as instruções traduzidas, defina o idioma para inglês e a localidade para Estados Unidos. Em seguida, tente novamente.

Consulte o emblema Trailhead no seu idioma para saber mais sobre como aproveitar a experiência de Trailhead em outros idiomas.

Acompanhar com o Trail Together

Deseja acompanhar um especialista enquanto trabalha nesta etapa? Veja este vídeo que faz parte da série Trail Together.

(Este clipe começa na marca dos 16:36 minutos, caso você queira retroceder e ver o início da etapa novamente.)

O que é o contexto de execução?

Nos aplicativos ASP.NET, o código é executado no contexto do domínio de um aplicativo. No universo da plataforma do Lightning, o código é executado dentro de um contexto de execução. Em poucas palavras, esse contexto representa o tempo transcorrido entre o momento em que o código é executado e o momento em que ele termina. É importante entender que o código do Apex que você escreve nem sempre é o único código a ser executado.

Para entender como isso funciona, é preciso conhecer todas as formas como o código do Apex pode ser executado na plataforma.

Métodos para invocar o Apex

Método Descrição
Acionador do banco de dados Invocado para um evento específico em um objeto padrão ou personalizado.
Apex anônimo Trechos de código executados dinamicamente no Developer Console e em outras ferramentas.
Apex assíncrono Ocorre ao executar um Apex futuro ou que permite a execução em fila, ao executar um trabalho em lote ou agendar a execução do Apex num intervalo especificado.
Serviços da web Código a ser exposto pelos serviços da web SOAP ou REST.
Serviços de email Código configurado para processar o email recebido.
Páginas do Lightning ou Visualforce Os controladores do Visualforce e os componentes do Lightning podem executar código do Apex automaticamente ou quando um usuário iniciar determinada ação, como clicar em um botão. Os componentes do Lightning também podem ser executados por processos e fluxos do Lightning.

Além de invocar o código do Apex, as ações (como criar uma nova tarefa, enviar um email, realizar uma atualização de campo ou enviar uma mensagem de saída) podem ser acionadas por um dos recursos da plataforma declarativa. Essas ações também são realizadas dentro de um contexto de execução.

Outra consideração importante é o contexto do usuário que executa o código do Apex. Por padrão, o Apex é executado no contexto do sistema. O código do Apex tem acesso a todos os objetos e campos. As permissões de objeto, a segurança em nível de campo e as regras de compartilhamento não são aplicadas ao usuário atual. Você pode usar a palavra-chave with sharing para especificar que as regras de compartilhamento do usuário atual devem ser consideradas para determinada classe. Esse tópico é importante, ou seja, confira Usar as palavras-chave com compartilhamento e sem compartilhamento.

Fundamentos dos acionadores

Antes de aprender mais sobre o contexto de execução, vamos voltar um pouco atrás para apresentar a você o universo dos acionadores do banco de dados. De modo semelhante aos acionadores do SQL Server, os acionadores do banco de dados do Apex executam a lógica de programação antes ou depois de eventos nos registros do Salesforce. Ao definir o acionador, você pode especificar mais de um dos eventos a seguir:

  • before insert
  • before update
  • before delete
  • after insert
  • after update
  • after delete
  • after undelete

A sintaxe básica de um acionador é assim:

trigger TriggerName on ObjectName (trigger_events) {
   // code_block
}

Agora, sabemos o quanto os desenvolvedores .NET adoram resolver problemas com código, mas vamos dar uma megadica de produtividade para você. Só recorra ao uso do acionador quando tiver certeza absoluta de que não é possível alcançar o mesmo efeito com uma das nossas ferramentas de automação “apontar e clicar”.

Para facilitar sua vida, a Salesforce Platform inclui uma ferramenta de automação poderosa, o Flow Builder, para administrar a lógica de negócios sem ter que codificar. Na maioria dos casos, tarefas que antes só podiam ser realizadas com um acionador são agora mais adequadas para uma das ferramentas de automação.

Nota

Nota

Caso você seja um desenvolvedor novo na plataforma, tire um tempo para conferir o módulo Aprovar registros com processos de aprovação na trilha do Desenvolvedor iniciante antes de criar um acionador. Temos certeza de que você não quer ser aquela pessoa que trouxe uma sobrecarga técnica desnecessária para a organização do Salesforce.

Marcar o contexto de execução

Para entender melhor o contexto de execução, vamos criar juntos um acionador do banco de dados do Apex que gera uma oportunidade sempre que uma nova conta é inserida. Esse acionador chama um método de uma classe de manipulador; então, precisamos criar essa classe primeiro.

  1. Em Configuração, selecione Seu nome > Developer Console para abrir o Developer Console.
  2. No Developer Console, selecione File (Arquivo) > New (Nova) > Apex Class (Classe do Apex).
  3. Digite AccountHandler como nome da classe e clique em OK.
  4. Exclua o código existente e insira o seguinte trecho:
    public with sharing class AccountHandler {
        public static void CreateNewOpportunity(List<Account> accts) {
            for (Account a :accts) {
                Opportunity opp = new Opportunity();
                opp.Name = a.Name + ' Opportunity';
                opp.AccountId = a.Id;
                opp.StageName = 'Prospecting';
                opp.CloseDate = System.Today().addMonths(1);
                insert opp;
            }
        }
    }
    
  5. Pressione Ctrl+S para salvar sua classe.
Nota

Nota

A melhor prática é usar somente um acionador por objeto, como você verá no exemplo a seguir. Depois, você pode usar métodos de manipulador específicos para o contexto dentro dos acionadores para criar acionadores sem lógica. Com essa prática, você evita cair em armadilhas comuns que prejudicam os novos desenvolvedores. Para saber mais sobre essas técnicas, confira Estruturas de acionador e melhores práticas do acionador do Apex.

Agora que temos a classe de manipulador, criaremos o acionador de conta.

  1. No Developer Console, selecione File (Arquivo) > New (Novo) > Apex Trigger (Acionador do Apex).
  2. Digite AccountTrigger como nome e selecione Account como sObject.
  3. Clique em Submit (Enviar).
  4. Exclua o código existente e insira o seguinte trecho:
    trigger AccountTrigger on Account (before insert, before update, before
        delete, after insert, after update, after delete,  after undelete) {
        if (Trigger.isAfter && Trigger.isInsert) {
            AccountHandler.CreateNewOpportunity(Trigger.New);
        }
    }
    
  5. Pressione Ctrl+S para salvar seu acionador.

Para concluir o guia passo a passo, executamos um código anônimo para simular que o usuário está inserindo uma nova conta usando a interface do Salesforce. Lembre se: o código do Apex pode ser executado de várias formas diferentes.

  1. Em Configuração, selecione Seu nome > Developer Console para abrir o Developer Console.
  2. Selecione Debug (Depurar) > Open Execute Anonymous Window (Abrir janela Executar no modo anônimo).
  3. Exclua o código existente e insira o seguinte trecho:
    Account acct = new Account(
        Name='Test Account 2',
        Phone='(415)555-8989',
        NumberOfEmployees=50,
        BillingCity='San Francisco');
    insert acct;
    
  4. Verifique se a opção Open Log está selecionada e clique em Execute. Uma nova guia mostra o registro de execução. Mantenha-a aberta para poder examiná-la com atenção.

Examinar o registro de execução

Observe que a primeira linha do registro de execução marca o evento EXECUTION_STARTED e que a última linha é o evento EXECUTION_FINISHED. Tudo que está entre essas linhas é o contexto de execução.

Vamos ver o que acontece mais de perto. O evento CODE_UNIT_STARTED marca o momento em que o código da janela Execute Anonymous foi desencadeado. Essa linha está destacada em vermelho na imagem abaixo.

Captura de tela do Registro de depuração no Developer Console, destacando os eventos code_unit_started

A segunda linha destacada, CODE_UNIT_STARTED, representa quando o código do evento BeforeInsert foi executado.

Não é possível ver na imagem, mas, se estiver acompanhando com a sua própria instância do Console do desenvolvedor, role mais para baixo nos resultados, na tela, e procure outras instâncias de CODE_UNIT_STARTED. Você verá, pelo menos, mais uma instância representando o momento em que o código do evento AfterInsert foi executado. Se você criou regras de fluxo de trabalho desencadeadas quando uma nova conta foi criada, essas regras também devem aparecer no registro de execução. Esse código inteiro funciona dentro do mesmo contexto de execução e, portanto, está sujeito ao mesmo conjunto de limites do administrador.

Você deve estar se perguntando: por que é tão importante entender isso? Bem, como o Salesforce é um ambiente multilocatário, os limites do administrador são essenciais para evitar que cada instância de uma organização do Salesforce consuma demasiados recursos. Isso basicamente evita que o sistema inteiro entre em colapso.

Trabalhando com limites

Isso nos traz de volta ao trabalho com limites. Provavelmente, os dois limites mais preocupantes estão relacionados com o número de consultas SOQL e de demonstrativos DML. Esses limites tendem a dar trabalho para os desenvolvedores novos na plataforma; então, queremos dedicar um tempo extra para falar sobre como evitá-los.

Nota

Nota

Existem muitos limites que você precisa conhecer e eles tendem a mudar com o lançamento de cada versão importante. Além disso, é comum que os limites fiquem menos estritos com o passar do tempo, ou seja, não deixe de se manter informado usando o link Administradores e limites de execução em Recursos.

Trabalhando em massa

Muitos desenvolvedores caem na armadilha de desenvolver um código que funciona com um único registro. Eles aprendem bem rápido que isso pode ser um engano gravíssimo na plataforma do Lightning.

Os acionadores do Apex podem receber até 200 registros de uma vez. No momento, o limite síncrono é de 100 para o total de consultas SOQL e de 150 para o total de demonstrativos DML emitidos. Portanto, se o seu acionador realizar uma consulta SOQL ou um demonstrativo DML dentro de um loop e esse acionador for ativado para uma operação em massa, adivinha o que acontece?

BOOM!!!

Isso mesmo, você verá um erro de limites. É possível que o código seja implantado e execute bem durante algum tempo antes que o limite seja descoberto. Mas depois disso, o desenvolvedor precisa retornar e descobrir como “massificar” o código. Não é raro que essa segunda tentativa seja mais demorada do que o projeto inicial. Para evitar essa situação, desenvolva seu código do Apex para manipular operações em massa desde o início. Descubra como fazer isso no módulo Acionadores do Apex em massa.

Talvez você tenha percebido, talvez não tenha, mas o código do manipulador do acionador que criamos antes não usou um padrão em massa e, portanto, está propenso a erros de limites. Só para recordar, veja abaixo como era o código original.

public with sharing class AccountHandler {
    public static void CreateNewOpportunity(List<Account> accts) {
        for (Account a :accts) {
            Opportunity opp = new Opportunity();
            opp.Name = a.Name + ' Opportunity';
            opp.AccountId = a.Id;
            opp.StageName = 'Prospecting';
            opp.CloseDate = System.Today().addMonths(1);
            insert opp;
        }
    }
}

Repare que a operação insert DML está dentro do loop for. Isso é muito, muito ruim, algo a ser evitado a todo custo.

Felizmente, podemos alterar esse código para consertá-lo, fazendo com que ele escreva em uma variável de lista dentro do loop e, depois, insira o conteúdo da lista em uma única etapa.

  1. Em Configuração, selecione Seu nome > Developer Console para abrir o Developer Console.
  2. No Developer Console, selecione File (Arquivo) > Open (Abrir).
  3. Selecione Classes como tipo de entidade. Selecione AccountHandler como entidade.
  4. Clique em Open (Abrir).
  5. Exclua o código existente e insira o seguinte trecho:
    public with sharing class AccountHandler {
        public static void CreateNewOpportunity(List<Account> accts) {
            List<Opportunity> opps = new List<Opportunity>();
            for (Account a :accts) {
                Opportunity opp = new Opportunity();
                opp.Name = a.Name + ' Opportunity';
                opp.AccountId = a.Id;
                opp.StageName = 'Prospecting';
                opp.CloseDate = System.Today().addMonths(1);
                opps.add(opp);
            }
            if (opps.size() > 0) {
                insert opps;
            }
        }
    }
    
  6. Pressione Ctrl+S para salvar sua classe.

Agora que consertamos o código do manipulador do acionador, vamos testá-lo para verificar se o acionador pode lidar com uma carga de 200 registros. Como você certamente já sabe, escrever testes de unidade para garantir que o código funciona é uma melhor prática.

  1. No Developer Console, selecione File (Arquivo) > New (Nova) > Apex Class (Classe do Apex).
  2. Digite AccountTrigger_Test como nome da classe e clique em OK.
  3. Exclua o código existente e insira o seguinte trecho:
    @isTest
    private class AccountTrigger_Test {
        @isTest static void TestCreateNewAccountInBulk() {
            // Test Setup data
            // Create 200 new Accounts
            List<Account> accts = new List<Account>();
            for(Integer i=0; i < 200; i++) {
                Account acct = new Account(Name='Test Account ' + i);
                accts.add(acct);
            }              
            // Perform Test
            Test.startTest();
            insert accts;                               
            Test.stopTest();
            // Verify that 200 new Accounts were inserted
            List<Account> verifyAccts = [SELECT Id FROM Account];
            System.assertEquals(200, verifyAccts.size());    
            // Also verify that 200 new Opportunities were inserted
            List<Opportunity> verifyOpps = [SELECT Id FROM Opportunity];                              
            System.assertEquals(200, verifyOpps.size());                             
        }
    }
    
  4. Pressione Ctrl+S para salvar sua classe.
  5. Selecione Test (Teste) > New Run (Nova execução).
  6. Selecione AccountTrigger_Test como TestClass e TestCreateNewAccountInBulk como método de teste.
  7. Clique em Run (Executar).
  8. Selecione a guia Testes e verifique se o teste é executado até o fim sem falhas, o que é indicado pelo sinal de visto verde na coluna Status.
Nota

Nota

Ainda não falamos dos testes de unidade, mas não se preocupe com isso. Na plataforma do Lightning, eles funcionam de uma forma bem parecida à do .NET, tendo apenas algumas palavras-chave diferentes. Você vai entender bem rápido como eles são estruturados. Saiba mais sobre os testes de acionadores do Apex no link em Recursos.

Quero saber mais

O Apex usa o conhecido bloco try-catch-finally para lidar com as exceções. Mas o demonstrativo catch e o possível rollback podem mudar conforme o ponto em que o código do Apex é executado. Confira o link em Resources sobre as melhores práticas ao lidar com try, catch e rollback no Apex.

Não existe variável de aplicativo ou sessão na plataforma do Lightning. Se você precisar que os dados persistam entre as classes, use variáveis estáticas, mas lembre-se de que as variáveis estáticas na plataforma do Lightning não funcionam do mesmo jeito que no .NET. No universo da plataforma do Lightning, uma variável estática só pode preservar informações dentro de um contexto de execução única, embora haja outras opções disponíveis para manter os dados entre as invocações do acionador. Confira os links sobre o Apex avançado nos Resources, na Internet, para saber mais.

Ao trabalhar com limites, é preciso considerar vários dilemas, principalmente no caso dos desenvolvedores de pacotes gerenciados. A propósito, os parceiros do Salesforce costumam usar pacotes gerenciados para distribuir e vender aplicativos. Neste módulo, falamos bem superficialmente do que você precisa saber. Caso queira estudar o desenvolvimento em Apex a sério, confira os links sobre o Apex avançado nos Resources, na Internet.

Recursos

Continue a aprender de graça!
Inscreva-se em uma conta para continuar.
O que você ganha com isso?
  • Receba recomendações personalizadas para suas metas de carreira
  • Pratique suas habilidades com desafios práticos e testes
  • Monitore e compartilhe seu progresso com os empregadores
  • Conecte-se a orientação e oportunidades de carreira