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.






