Tutorial de Salesforce Apex para iniciantes
โก Resumo Inteligente
A programaรงรฃo Apex oferece aos desenvolvedores Salesforce uma linguagem orientada a objetos e fortemente tipada para adicionar lรณgica de negรณcios personalizada ao CRM. Ela viabiliza classes, gatilhos e trabalhos em lote, enquanto os limites de governanรงa mantรชm a plataforma multilocatรกria compartilhada estรกvel.
O que รฉ Apex no Salesforce?
รกpice Apex รฉ uma linguagem de programaรงรฃo orientada a objetos e fortemente tipada, desenvolvida pela Salesforce para a criaรงรฃo de aplicativos de Software como Serviรงo (SaaS) e de Gestรฃo de Relacionamento com o Cliente (CRM). O Apex auxilia desenvolvedores na criaรงรฃo de aplicativos SaaS de terceiros e na adiรงรฃo de lรณgica de negรณcios a eventos do sistema, fornecendo suporte a bancos de dados e interfaces cliente-servidor.
O Apex ajuda os desenvolvedores a adicionar lรณgica de negรณcios a eventos do sistema, como cliques em botรตes, atualizaรงรตes de registros relacionados e pรกginas do Visualforce. O Apex tem uma sintaxe semelhante a... Java. Registre-se no Salesforce Para aprender como funciona o CRM.
Recursos da linguagem de programaรงรฃo Apex
Aqui estรฃo os recursos importantes do Salesforce Apex:
- Apex รฉ uma linguagem que nรฃo diferencia maiรบsculas de minรบsculas.
- Vocรช pode executar operaรงรตes DML como INSERT, UPDATE, UPSERT e DELETE em registros sObject usando Apex.
- Vocรช pode consultar registros de sObject usando SOQL (Salesforce Object Query Language) e SOSL (Salesforce Object Search Language) no Apex.
- Permite que vocรช crie um teste de unidade e executรก-lo para verificar o Cobertura de cรณdigo e a eficiรชncia do cรณdigo em Apex.
- O Apex รฉ executado em um ambiente multilocatรกrio e Salesforce O Salesforce definiu limites de governanรงa que impedem um usuรกrio de monopolizar os recursos compartilhados. Qualquer cรณdigo que ultrapasse um limite de governanรงa do Salesforce falharรก e um erro serรก exibido.
- Um objeto do Salesforce pode ser usado como um tipo de dados no Apex. Por exemplo:
Account acc = new Account();
Aqui, "Conta" รฉ um objeto padrรฃo do Salesforce.
- O Apex รฉ atualizado automaticamente a cada versรฃo do Salesforce.
Quando um desenvolvedor deve escolher o Apex?
O cรณdigo Apex sรณ deve ser escrito se um cenรกrio de negรณcios for complexo demais para ser implementado usando a funcionalidade prรฉ-construรญda de apontar e clicar fornecida pelo Salesforce.
A seguir, apresentamos alguns cenรกrios em que vocรช precisarรก escrever cรณdigo Apex:
- Para criar serviรงos web que integram o Salesforce com outros aplicativos.
- Para implementar validaรงรฃo personalizada em sObjects.
- Para executar lรณgica Apex personalizada quando uma operaรงรฃo DML for realizada.
- Para implementar funcionalidades que nรฃo podem ser criadas com as ferramentas de automaรงรฃo declarativa existentes, como o Flow.
- Para configurar serviรงos de email que processam o conteรบdo, os cabeรงalhos e os anexos dos e-mails recebidos.
Depois de saber quando o Apex รฉ a escolha certa, o prรณximo passo รฉ entender o que acontece com o seu cรณdigo depois de salvรก-lo.
Estrutura de funcionamento do Apex
A seguir, o fluxo de aรงรตes para o cรณdigo Apex:
- Aรงรฃo do desenvolvedor: Quando o desenvolvedor salva o cรณdigo na plataforma, todo o cรณdigo Apex รฉ compilado em um conjunto de instruรงรตes que o interpretador de tempo de execuรงรฃo do Apex consegue entender, e essas instruรงรตes sรฃo entรฃo salvas como metadados na plataforma.
- Aรงรฃo do usuรกrio final: Quando um evento de usuรกrio executa cรณdigo Apex, o servidor da plataforma recupera as instruรงรตes compiladas dos metadados e as executa por meio do interpretador Apex antes de retornar o resultado.
O diagrama abaixo mostra como as aรงรตes do desenvolvedor e do usuรกrio final interagem com o servidor de aplicativos da Lightning Platform:
Ambiente de desenvolvimento Apex
O cรณdigo Apex pode ser desenvolvido tanto em um ambiente de teste (sandbox) quanto em uma organizaรงรฃo Developer Edition do Salesforce.
ร uma boa prรกtica desenvolver o cรณdigo em um ambiente de teste (sandbox) e, em seguida, implantรก-lo no ambiente de produรงรฃo, conforme ilustrado abaixo:
Ferramentas de desenvolvimento de cรณdigo Apex: A seguir, apresentamos as trรชs ferramentas disponรญveis para desenvolver cรณdigo Apex em todas as ediรงรตes do Salesforce:
- Console do desenvolvedor
- Visual Studio Code com o Salesforce Extension Pack (que substitui o Force.com IDE descontinuado)
- Code editor na interface do usuรกrio de configuraรงรฃo do Salesforce
Com o ambiente pronto, vamos analisar os elementos bรกsicos da linguagem em si, comeรงando pelos tipos de dados.
Tipos de dados no Apex
A seguir, estรฃo os tipos de dados suportados pelo Apex:
Primitivo
Inteiro, DoubleOs tipos de dados primitivos sรฃo: `long`, `date`, `datetime`, `decimal`, `time`, `blob`, `string`, `ID` e `boole`. Todos os tipos de dados primitivos sรฃo passados โโpor valor, nรฃo por referรชncia.
Coleรงรตes
Existem trรชs tipos de coleรงรตes disponรญveis no Apex:
- Lista: ร uma coleรงรฃo ordenada de elementos primitivos, sObjects, coleรงรตes ou objetos Apex, baseada em รญndices.
- Conjunto: Uma coleรงรฃo nรฃo ordenada de elementos รบnicos que nรฃo contรฉm duplicados.
- Mapa: ร uma coleรงรฃo de chaves รบnicas que correspondem a valores individuais, que podem ser tipos primitivos, sObjects, coleรงรตes ou objetos Apex.
objeto
Este รฉ um tipo de dados especial no Salesforce. ร semelhante a uma tabela em SQL e contรฉm campos semelhantes a colunas em SQL.
Enums
Um Enum รฉ um absolutotracTipo de dados t que armazena um valor de um conjunto finito de identificadores especificados.
Classes, objetos e interfaces
Classes e interfaces Apex definidas pelo usuรกrio tambรฉm podem ser usadas como tipos de dados. Um objeto se refere a uma instรขncia de qualquer tipo de dado compatรญvel com o Apex.
Sintaxe do รกpice
Declaraรงรฃo de Variรกvel
Como o Apex รฉ uma linguagem fortemente tipada, รฉ obrigatรณrio declarar uma variรกvel com um tipo de dados no Apex.
Por exemplo:
Contact con = new Contact();
Aqui, a variรกvel `con` รฉ declarada com `Contact` como seu tipo de dados.
Consulta SOQL
SOQL significa Salesforce Object Query Language (Linguagem de Consulta de Objetos do Salesforce). O SOQL รฉ usado para buscar registros de sObjects no banco de dados do Salesforce. Por exemplo:
Account acc = [SELECT Id, Name FROM Account LIMIT 1];
A consulta acima recupera um registro de conta do banco de dados do Salesforce.
Declaraรงรฃo de loop
Uma estrutura de laรงo รฉ usada para iterar sobre os registros em uma lista. O nรบmero de iteraรงรตes รฉ igual ao nรบmero de registros na lista. Por exemplo:
List<Account> listOfAccounts = [SELECT Id, Name FROM Account LIMIT 100];
// iteration over the list of accounts
for(Account acc : listOfAccounts){
//your logic
}
No trecho de cรณdigo acima, listOfAccounts รฉ uma variรกvel do tipo de dados List.
Declaraรงรฃo de controle de fluxo
Uma instruรงรฃo de controle de fluxo รฉ รบtil quando vocรช deseja executar algumas linhas de cรณdigo com base em determinadas condiรงรตes.
Por exemplo:
List<Account> listOfAccounts = [SELECT Id, Name FROM Account LIMIT 100];
// execute the logic if the size of the account list is greater than zero
if(listOfAccounts.size() > 0){
//your logic
}
O trecho de cรณdigo acima consulta os registros de contas no banco de dados e verifica o tamanho da lista.
Declaraรงรฃo DML
DML significa Linguagem de Manipulaรงรฃo de Dados. As instruรงรตes DML sรฃo usadas para manipular dados no banco de dados do Salesforce. Por exemplo:
Account acc = new Account(Name = 'Test Account'); insert acc; //DML statement to create account record.
Especificadores de acesso Apex
A seguir estรฃo os especificadores de acesso suportados pelo Apex:
Pรบblico
Este especificador de acesso concede acesso a uma classe, mรฉtodo ou variรกvel para ser usada pelo Apex dentro de um namespace.
Privado
Este especificador de acesso permite o uso local de uma classe, mรฉtodo ou variรกvel, ou seja, dentro da seรงรฃo de cรณdigo onde ela estรก definida. Todos os mรฉtodos e variรกveis โโque nรฃo possuem um especificador de acesso definido assumem o especificador de acesso padrรฃo `private`.
Protegido
Este especificador de acesso concede acesso a um mรฉtodo ou variรกvel que poderรก ser usado por quaisquer classes internas dentro da classe Apex que o define.
Cobertura
Este especificador de acesso permite que o Apex acesse uma classe, mรฉtodo ou variรกvel tanto dentro quanto fora de um namespace. ร uma boa prรกtica nรฃo usar a palavra-chave `global` a menos que seja necessรกrio.
Palavras-chave no Apex
Com compartilhamento
Se uma classe for definida com esta palavra-chave, todas as regras de compartilhamento aplicรกveis โโao usuรกrio atual serรฃo aplicadas. Se esta palavra-chave estiver ausente, o cรณdigo serรก executado no contexto do sistema.
Por exemplo:
public with sharing class MyApexClass{
// sharing rules enforced when code in this class executes
}
Sem compartilhar
Se uma classe for definida com esta palavra-chave, as regras de compartilhamento aplicรกveis โโao usuรกrio atual nรฃo serรฃo aplicadas.
Por exemplo:
public without sharing class MyApexClass{
// sharing rules are not enforced when code in this class executes
}
Estรกtico
Uma variรกvel ou mรฉtodo definido com a palavra-chave `static` รฉ inicializado uma รบnica vez e associado ร classe. Variรกveis โโe mรฉtodos estรกticos podem ser chamados diretamente pelo nome da classe, sem a necessidade de criar uma instรขncia da classe.
final
Uma constante ou mรฉtodo definido com a palavra-chave final nรฃo pode ser sobrescrito. Por exemplo:
public class myCls {
static final Integer INT_CONST = 10;
}
Se vocรช tentar sobrescrever o valor dessa variรกvel INT_CONST, receberรก a exceรงรฃo โ System.FinalException: A variรกvel final jรก foi inicializada.
Devoluรงรฃo
Esta palavra-chave retorna um valor de um mรฉtodo. Por exemplo:
public String getName() {
return 'Test';
}
Nulo
Define uma constante nula e pode ser atribuรญda a uma variรกvel. Por exemplo:
Boolean b = null;
Virtual
Se uma classe for definida com a palavra-chave virtual, ela poderรก ser estendida e sobrescrita.
Sumรกrio
Se uma classe for definida com o valor absolutotracA palavra-chave `t` deve conter pelo menos um mรฉtodo com a palavra-chave `abs`.tract, e esse mรฉtodo deve ter apenas uma assinatura.
Por exemplo:
public abstract class MyAbstractClass {
abstract Integer myAbstractMethod1();
}
Seqรผรชncia de รpice
Uma string รฉ um conjunto de caracteres sem limite de caracteres. Por exemplo:
String name = 'Test';
Existem vรกrios mรฉtodos integrados fornecidos pela classe String no Salesforce. A seguir, alguns dos mรฉtodos mais utilizados:
abreviar (largura mรกxima)
Este mรฉtodo trunca uma string para o comprimento especificado e a retorna se o comprimento da string fornecida for maior que o comprimento especificado; caso contrรกrio, retorna a string original. Se o valor da variรกvel `maxWidth` for menor que 4, este mรฉtodo lanรงarรก uma exceรงรฃo em tempo de execuรงรฃo: `System.StringException: Minimum abbreviation width is 4`.
Por exemplo:
String s = 'Hello World';
String s2 = s.abbreviate(8);
System.debug('s2: ' + s2); //Hello...
capitalizar()
Este mรฉtodo converte a primeira letra de uma string em maiรบsculas e minรบsculas e a retorna.
Por exemplo:
String s = 'hello';
String s2 = s.capitalize();
System.assertEquals('Hello', s2);
contรฉm (substring)
Este mรฉtodo retorna verdadeiro se a string que o chama contiver a substring especificada.
String name1 = 'test1';
String name2 = 'test';
Boolean flag = name1.contains(name2);
System.debug('flag:: ' + flag); //true
รฉ igual(stringOrId)
Este mรฉtodo retorna verdadeiro se o parรขmetro passado nรฃo for nulo e representar a mesma sequรชncia binรกria de caracteres que a string que estรก chamando o mรฉtodo.
Ao comparar valores de ID, os comprimentos dos IDs podem nรฃo ser iguais. Por exemplo, se uma string que representa um ID de 15 caracteres for comparada com um objeto que representa um ID de 18 caracteres, este mรฉtodo ainda retornarรก verdadeiro. Por exemplo:
String stringValue15 = '001D000000Ju1zH';
Id idValue18 = '001D000000Ju1zHIAR';
Boolean result = stringValue15.equals(idValue18);
System.debug('result: ' + result); //true
No exemplo acima, o mรฉtodo equals compara um ID de objeto de 15 caracteres com um ID de objeto de 18 caracteres e, se ambos os IDs representarem a mesma sequรชncia binรกria, retorna verdadeiro.
Use este mรฉtodo para fazer comparaรงรตes que diferenciam maiรบsculas de minรบsculas.
escapeSingleQuotes(stringToEscape)
Este mรฉtodo adiciona um caractere de escape (\) antes de qualquer aspa simples em uma string e retorna o resultado. Ele impede a injeรงรฃo de SOQL durante a criaรงรฃo de uma consulta SOQL dinรขmica, garantindo que todas as aspas simples sejam tratadas como strings delimitadoras em vez de comandos de banco de dados.
Por exemplo:
String s = 'Hello \'Tom\''; String escapedStr = String.escapeSingleQuotes(s); System.debug(escapedStr); // Outputs Hello \'Tom\'
remover(substring)
Este mรฉtodo remove todas as ocorrรชncias da substring mencionada da string que chama o mรฉtodo e retorna a string resultante.
Por exemplo:
String s1 = 'Salesforce and force.com';
String s2 = s1.remove('force');
System.debug('s2: ' + s2); // 'Sales and .com'
substring(startIndex)
Este mรฉtodo retorna uma substring que comeรงa no caractere em startIndex e se estende atรฉ o final da string.
Por exemplo:
String s1 = 'hamburger';
String s2 = s1.substring(3);
System.debug('s2: ' + s2); //burger
marcha rรฉ()
Este mรฉtodo inverte todos os caracteres de uma string e a retorna. Por exemplo:
String s = 'Hello';
String s2 = s.reverse();
System.debug('s2:::: ' + s2); // olleH
aparar()
Este mรฉtodo remove todos os espaรงos em branco iniciais e finais de uma string e a retorna.
valorOf(paraConverter)
Este mรฉtodo retorna a representaรงรฃo em formato de string do objeto passado como parรขmetro.
Strings, classes e palavras-chave se unem quando vocรช comeรงa a empacotar a lรณgica em unidades reutilizรกveis, que รฉ exatamente para isso que servem as classes Apex.
Classe Apex
Uma classe Apex รฉ um modelo ou projeto a partir do qual os objetos sรฃo criados. Um objeto รฉ uma instรขncia de uma classe.
Existem trรชs maneiras de criar classes Apex no Salesforce:
- Console do desenvolvedor
- Visual Studio Code com o pacote de extensรตes do Salesforce
- Pรกgina de detalhes da classe Apex em Configuraรงรฃo
Em Apex, vocรช pode definir uma classe externa, tambรฉm chamada de classe de nรญvel superior, e tambรฉm pode definir classes dentro de uma classe externa, chamadas de classes internas.
ร obrigatรณrio usar um modificador de acesso como global ou pรบblico na declaraรงรฃo de uma classe externa.
Nรฃo รฉ necessรกrio usar um modificador de acesso na declaraรงรฃo de classes internas.
Uma classe Apex รฉ definida usando a palavra-chave `class` seguida pelo nome da classe.
A palavra-chave `extends` รฉ usada para estender uma classe existente em uma classe Apex, e a palavra-chave `implements` รฉ usada para implementar uma interface em uma classe Apex.
O Salesforce Apex nรฃo suporta heranรงa mรบltipla; uma classe Apex sรณ pode estender uma classe Apex existente, mas pode implementar vรกrias interfaces.
Uma classe Apex pode conter um construtor definido pelo usuรกrio e, caso um construtor definido pelo usuรกrio nรฃo esteja disponรญvel, um construtor padrรฃo serรก utilizado. O cรณdigo dentro de um construtor รฉ executado quando uma instรขncia da classe รฉ criada.
Sintaxe de uma classe Apex:
public class myApexClass{
// variable declaration
//constructor
public myApexClass(){
}
//methods declaration
}
A palavra-chave `new` รฉ usada para criar uma instรขncia de uma classe Apex. Abaixo estรก a sintaxe para criar uma instรขncia de uma classe Apex:
myApexClass obj = new myApexClass();
Apex Getter e Setter
Uma propriedade Apex รฉ semelhante a uma variรกvel Apex. Um getter e um setter sรฃo necessรกrios para uma propriedade Apex. Eles podem ser usados โโpara executar cรณdigo antes que o valor da propriedade seja acessado ou alterado. O cรณdigo no acessador get รฉ executado quando o valor de uma propriedade รฉ lido. O cรณdigo no acessador set รฉ executado quando o valor de uma propriedade รฉ alterado. Qualquer propriedade que tenha apenas um acessador get รฉ considerada somente leitura, qualquer propriedade que tenha apenas um acessador set รฉ considerada somente gravaรงรฃo e qualquer propriedade que tenha acessadores get e set รฉ considerada leitura e gravaรงรฃo. Sintaxe de uma propriedade Apex:
public class myApexClass {
// Property declaration
access_modifier return_type property_name {
get {
//code
}
set{
//code
}
}
}
Aqui, `access_modifier` รฉ o modificador de acesso da propriedade, `return_type` รฉ o tipo de dados da propriedade e `property_name` รฉ o nome da propriedade.
Abaixo, segue um exemplo de uma propriedade Apex que possui acessadores get e set:
public class myApex{
public String name{
get{ return name; }
set{ name = value; }
}
}
Neste caso, o nome da propriedade รฉ "name", trata-se de uma propriedade pรบblica e retorna um tipo de dados String.
Nรฃo รฉ obrigatรณrio ter cรณdigo nos blocos get e set. Esses blocos podem ser deixados vazios para definir uma propriedade automรกtica. Por exemplo:
public double MyReadWriteProp{ get; set; }
Os acessadores get e set tambรฉm podem ser definidos com seus prรณprios modificadores de acesso. Se um acessador for definido com um modificador, ele substituirรก o modificador de acesso da propriedade. Por exemplo:
public String name{private get; set;}// name is private for read and public for write.
As classes definem uma lรณgica reutilizรกvel que vocรช chama explicitamente. Os gatilhos, abordados a seguir, sรฃo executados automaticamente sempre que os registros sรฃo alterados.
Acionador do Apex
Os gatilhos Apex permitem executar cรณdigo Apex personalizado antes e depois da execuรงรฃo de uma operaรงรฃo DML.
O Apex suporta os dois tipos de gatilhos a seguir:
Antes dos gatilhos: Esses gatilhos sรฃo usados โโpara validar e atualizar o valor de um campo antes que o registro seja salvo no banco de dados.
Apรณs os gatilhos: Esses gatilhos sรฃo usados โโpara acessar valores de campos (como o ID do registro e o campo LastModifiedDate) que sรฃo definidos pelo sistema apรณs um registro ser gravado no banco de dados. Esses valores de campo podem ser usados โโpara modificar outros registros. Os registros acionados por gatilhos sรฃo somente leitura.
ร uma boa prรกtica escrever gatilhos otimizados para processamento em lote. Um gatilho otimizado para processamento em lote pode processar um รบnico registro, bem como vรกrios registros simultaneamente.
Sintaxe de um gatilho Apex:
trigger TriggerName on ObjectName (trigger_events) {
//Code_block
}
Aqui, TriggerName รฉ o nome do gatilho, ObjectName รฉ o nome do objeto no qual o gatilho estรก escrito e trigger_events รฉ uma lista de eventos separados por vรญrgulas.
Os seguintes eventos sรฃo suportados pelos gatilhos Apex: antes da inserรงรฃo, antes da atualizaรงรฃo, antes da exclusรฃo, apรณs a inserรงรฃo, apรณs a atualizaรงรฃo, apรณs a exclusรฃo e apรณs a recuperaรงรฃo da exclusรฃo.
Palavras-chave estรกticas nรฃo podem ser usadas em um gatilho Apex. Todas as palavras-chave aplicรกveis โโa classes internas podem ser usadas em um gatilho Apex.
Existem variรกveis โโimplรญcitas definidas por cada gatilho que retornam o contexto de tempo de execuรงรฃo. Essas variรกveis โโsรฃo definidas na classe System.Trigger e sรฃo chamadas de variรกveis โโde contexto. As duas capturas de tela abaixo listam as variรกveis โโde contexto suportadas pelos gatilhos Apex:
A seguir, apresentamos as consideraรงรตes para variรกveis โโde contexto em gatilhos Apex:
- Nรฃo utilize trigger.new e trigger.old em operaรงรตes DML.
- O arquivo Trigger.new nรฃo pode ser excluรญdo.
- Trigger.new รฉ somente leitura em gatilhos posteriores.
- O mรฉtodo `trigger.new` pode ser usado para alterar os valores de campos no mesmo objeto somente em gatilhos `before`.
As duas capturas de tela abaixo listam as consideraรงรตes sobre aรงรตes especรญficas em diferentes eventos de gatilho:
Os gatilhos lidam com a lรณgica em tempo real, mas algumas tarefas sรฃo simplesmente grandes demais para uma รบnica transaรงรฃo. ร aรญ que entra o Apex em lote.
Classe de lote no Apex
Uma classe em lote no Salesforce รฉ usada para processar um grande nรบmero de registros que excederiam os limites do Apex se processados โโnormalmente. Uma classe em lote executa o cรณdigo de forma assรญncrona.
A seguir, as vantagens de uma aula em lote:
- Uma classe de processamento em lote processa os dados em partes, e se uma parte nรฃo for processada com sucesso, as partes processadas com sucesso nรฃo sรฃo revertidas.
- Cada bloco de dados em uma classe batch รฉ processado com um novo conjunto de limites de governanรงa, o que garante que o cรณdigo seja executado dentro dos limites de execuรงรฃo definidos.
A interface Database.Batchable deve ser implementada por uma classe Apex para ser usada como uma classe de lote. Ela fornece trรชs mรฉtodos que devem ser implementados pela classe de lote:
1. iniciar()
Este mรฉtodo gera o escopo de registros ou objetos a serem processados โโpelo mรฉtodo de interface `execute`. Ele รฉ chamado apenas uma vez durante a execuรงรฃo do lote. Este mรฉtodo retorna um objeto `Database.QueryLocator` ou um `Iterable`. O nรบmero de registros que podem ser recuperados por uma consulta SOQL usando o objeto `Database.QueryLocator` รฉ de 50 milhรตes, mas usando um `Iterable`, o nรบmero total de registros que podem ser recuperados pela consulta SOQL รฉ de apenas 50,000. Um `Iterable` รฉ usado para gerar um escopo complexo para a classe de lote.
Sintaxe do mรฉtodo start:
global (Database.QueryLocator | Iterable<sObject>) start(Database.BatchableContext bc) {}
2. executar()
Este mรฉtodo รฉ usado para processar cada bloco de dados. O mรฉtodo `execute` รฉ chamado para cada bloco de registros. O tamanho padrรฃo do lote para execuรงรฃo รฉ de 200 registros. O mรฉtodo `execute` recebe dois argumentos:
Uma referรชncia ao objeto Database.BatchableContext,
Uma lista de sObjects, como List ou uma lista de tipos parametrizados. Sintaxe do mรฉtodo execute:
global void execute(Database.BatchableContext bc, List<P> records){}
3. finalizar()
O mรฉtodo `finish` รฉ chamado uma vez durante a execuรงรฃo da classe em lote. Operaรงรตes de pรณs-processamento podem ser realizadas no mรฉtodo `finish`. Por exemplo: enviar um e-mail de confirmaรงรฃo. Este mรฉtodo รฉ chamado quando todos os lotes sรฃo processados. Sintaxe do mรฉtodo `finish`:
global void finish(Database.BatchableContext bc){}
Objeto Database.BatchableContext
Cada mรฉtodo da interface Database.Batchable possui uma referรชncia a um objeto Database.BatchableContext.
Este objeto รฉ usado para track o progresso do trabalho em lote.
A seguir estรฃo os mรฉtodos de instรขncia fornecidos por BatchableContext:
- getChildJobId(): Este mรฉtodo retorna o ID do trabalho em lote que estรก sendo processado no momento.
- getJobId(): este mรฉtodo retorna o ID do trabalho em lote.
A seguir estรก a sintaxe de uma classe em lote:
global class MyBatchClass implements Database.Batchable<sObject> {
global (Database.QueryLocator | Iterable<sObject>) start(Database.BatchableContext bc) {
// collect the batches of records or objects to be passed to execute
}
global void execute(Database.BatchableContext bc, List<P> records){
// process each batch of records
}
global void finish(Database.BatchableContext bc){
// execute any post-processing operations
}
}
Mรฉtodo Database.executeBatch
O mรฉtodo Database.executeBatch รฉ usado para executar uma classe em lote.
Este mรฉtodo recebe dois parรขmetros: uma instรขncia da classe de lote a ser processada e um parรขmetro de escopo opcional para especificar o tamanho do lote. Se nรฃo for especificado, o tamanho padrรฃo de 200 serรก utilizado.
Sintaxe de Database.executeBatch:
Database.executeBatch(myBatchObject, scope)
Executando uma classe em lote chamada MyBatchClass:
MyBatchClass myBatchObject = new MyBatchClass(); Id batchId = Database.executeBatch(myBatchObject, 100);
Banco de dados com estado
Por padrรฃo, uma classe em lote nรฃo mantรฉm estado. Cada vez que o mรฉtodo execute รฉ chamado, uma nova cรณpia do objeto รฉ recebida e todas as variรกveis โโda classe sรฃo inicializadas.
O mรฉtodo `Database.Stateful` รฉ implementado para tornar uma classe de lote com estado.
Se sua classe de lote implementar o banco de dadosNa interface .Stateful, todas as variรกveis โโde instรขncia mantรชm seus valores, mas as variรกveis โโestรกticas sรฃo redefinidas entre as transaรงรตes.
Apex assรญncrono alรฉm do Batch
O Batch Apex รฉ apenas uma das vรกrias maneiras de executar cรณdigo de forma assรญncrona. O Salesforce oferece quatro opรงรตes assรญncronas, e a escolha da mais adequada depende da quantidade de dados que vocรช processa e se os trabalhos precisam ser encadeados ou agendados.
- Mรฉtodos futuros: Anotadas com @future, essas sรฃo as melhores para operaรงรตes simples e rรกpidas, como chamadas para serviรงos web externos.
- Apex enfileirado: Implementa a interface Queueable, aceita tipos de objetos complexos, retorna um ID de tarefa e suporta o encadeamento de uma tarefa a outra.
- Apex em lote: Processa volumes de dados muito grandes em partes, conforme descrito acima.
- รpice programado: Implementa a interface Schedulable para que uma classe seja executada em um horรกrio especรญfico, como uma tarefa de limpeza noturna.
| Formato | Melhor Para | Capacidade chave |
|---|---|---|
| Mรฉtodo futuro | Chamadas simples | Dispare e esqueรงa |
| Apex enfileirado | Processamento sequencial | Encadeamento e monitoramento de tarefas |
| Batch Apex | Milhรตes de registros | Processamento em blocos |
| รpice programado | Tarefas recorrentes | Temporizaรงรฃo baseada em cron |
Independentemente do modelo de execuรงรฃo escolhido, todas as transaรงรตes continuam sendo avaliadas em relaรงรฃo aos limites de governanรงa da plataforma listados abaixo.
Limites do Governador Apex
Os limites de governanรงa do Apex sรฃo limites impostos pelo mecanismo de tempo de execuรงรฃo do Apex para garantir que nenhum cรณdigo ou processo Apex descontrolado monopolize os recursos compartilhados e nรฃo interrompa o processamento de outros usuรกrios no ambiente multilocatรกrio. Esses limites sรฃo verificados em cada transaรงรฃo do Apex. A seguir, estรฃo os limites de governanรงa definidos pela Salesforce para cada transaรงรฃo do Apex:
| Descriรงรฃo | Limitar |
|---|---|
| Consultas SOQL que podem ser feitas em uma transaรงรฃo sรญncrona | 100 |
| Consultas SOQL que podem ser feitas em uma transaรงรฃo assรญncrona | 200 |
| Registros que podem ser recuperados por uma consulta SOQL | 50,000 |
| Registros que podem ser recuperados por Database.getQueryLocator | 10,000 |
| Consultas SOSL que podem ser feitas em uma transaรงรฃo Apex. | 20 |
| Registros que podem ser recuperados por uma consulta SOSL | 2,000 |
| Instruรงรตes DML que podem ser executadas em uma transaรงรฃo Apex. | 150 |
| Registros que podem ser processados โโcomo resultado de uma instruรงรฃo DML, Approval.process ou database.emptyRecycleBin | 10,000 |
| Chamadas que podem ser feitas em uma transaรงรฃo Apex | 100 |
| Limite de tempo limite cumulativo em todas as chamadas externas que estรฃo sendo realizadas em uma transaรงรฃo Apex. | 120 segundos |
| Limite de tarefas Apex que podem ser adicionadas ร fila com System.enqueueJob | 50 |
| Limite de tempo de execuรงรฃo para cada transaรงรฃo Apex | 10 minutos |
| Limite de caracteres que podem ser usados โโem uma classe Apex e gatilho | 1 milhรตes |
| Limite de tempo de CPU para uma transaรงรฃo sรญncrona | 10,000 milissegundos |
| limite de tempo de CPU para uma transaรงรฃo assรญncrona | 60,000 milissegundos |
| Tamanho total do heap | 6 MB (sรญncrono) / 12 MB (assรญncrono) |
Como escrever uma classe de teste em Apex
A Salesforce exige que pelo menos 75% do seu cรณdigo Apex seja coberto por testes unitรกrios antes de ser implantado em produรงรฃo, e cada gatilho deve ter alguma cobertura. Portanto, escrever classes de teste รฉ uma habilidade essencial do Apex, nรฃo um extra opcional.
Uma classe de teste รฉ anotada com @isTest, e cada mรฉtodo de teste tambรฉm รฉ marcado com @isTest. Os mรฉtodos de teste nรฃo gravam dados no banco de dados e nรฃo tรชm acesso ร maioria dos dados existentes da organizaรงรฃo; portanto, cada teste cria seus prรณprios registros. Os mรฉtodos Test.startTest() e Test.stopTest() fornecem ao cรณdigo em teste um novo conjunto de limites de governanรงa, e as asserรงรตes verificam se a lรณgica se comportou conforme o esperado.
Aqui estรก uma classe de teste simples para a lรณgica de criaรงรฃo de conta:
@isTest
private class AccountHandlerTest {
@isTest
static void testCreateAccount() {
Account acc = new Account(Name = 'Test Account');
Test.startTest();
insert acc;
Test.stopTest();
Account result = [SELECT Id, Name FROM Account WHERE Id = :acc.Id];
System.assertEquals('Test Account', result.Name);
}
}
Siga estas orientaรงรตes ao elaborar testes:
- Utilize o mรฉtodo @testSetup para criar dados de teste compartilhados uma รบnica vez para todos os mรฉtodos de teste da classe.
- Teste o comportamento em lote inserindo 200 registros, e nรฃo apenas um.
- Abrange cenรกrios positivos, negativos e de usuรกrio restrito.
- Inclua sempre declaraรงรตes System.assert significativas; cobertura sem asserรงรตes nรฃo prova nada.
Melhores Prรกticas da Apex
Iniciantes frequentemente escrevem cรณdigo Apex que funciona para um รบnico registro, mas falha em operaรงรตes em massa no mundo real. As prรกticas abaixo mantรชm seu cรณdigo dentro dos limites de recursos e facilitam a manutenรงรฃo:
- Organize tudo em lote: Escreva uma lรณgica que lide com coleรงรตes de registros, pois os gatilhos podem receber atรฉ 200 registros em um รบnico lote.
- Mantenha SOQL e DML fora dos loops: Realize uma consulta antes do loop, colete as alteraรงรตes em uma lista e execute uma instruรงรฃo DML apรณs o loop.
- Um gatilho por objeto: Mantenha os gatilhos sem lรณgica e delegue o trabalho ร s classes de tratamento, o que torna a ordem de execuรงรฃo previsรญvel.
- Use com compartilhamento: Imponha seguranรงa em nรญvel de registro, a menos que haja um motivo documentado para executar no contexto do sistema.
- Evite inserir IDs diretamente no cรณdigo: Os IDs de registro diferem entre os ambientes de teste (sandbox) e de produรงรฃo, portanto, consulte-os ou use metadados personalizados.
- Monitorar limites no cรณdigo: Os mรฉtodos da classe Limits, como Limits.getQueries(), permitem verificar o consumo de recursos em tempo de execuรงรฃo.
๐ก Dica: Execute seu cรณdigo em 200 registros em um ambiente de teste (sandbox) antes de implantรก-lo. A maioria das falhas de limite de recursos (governant limit) ocorre apenas em volumes grandes, e detectรก-las precocemente รฉ muito mais barato do que depurรก-las em produรงรฃo.







