Starting out as a Salesforce Developer can be a daunting experience. With buzzwords thrown around left and right, it can be difficult to understand what everyone’s actually talking about.
To help, I’ve put together a glossary of keywords that I (and teams I’ve worked with) use frequently, in the hope that, when you next hear one of these terms, you can nod in agreement – rather than feeling like you’ve landed in a scene from Star Trek with a broken universal translator!
An abstract class is a class that has been defined with the “abstract” keyword. This keyword drastically alters the class’s behavior in the following ways:
- Prevents the class from being initialized directly.
- Allows the definition of abstract methods (methods which just have a signature defined and no body).
- Allows the definition of virtual methods (see Virtual Class for more details).
- Allows the use of protected methods (see Protected Method for more details).
- Variables can be defined and used in classes extending the abstract class.
This class becomes a template class for other classes to extend and define the specific behavior. While the behavior is similar to interfaces, abstract classes should be used to share code and variable declarations among several closely related classes. A class can only extend one other class.
A special type of SOQL query which, rather than returning a list of records from the database, instead returns a List of AggregateResult SObjects whose values and fields depend upon what was present in the SELECT query.
Aggregate queries can be further customized using different aggregate functions:
- AVG() – Returns the average (mean) of a field value.
- COUNT() – Returns the number of rows matching the query.
- COUNT_DISTINCT() – Returns the number of unique and non-null field values matching the query.
- MIN() – Returns the minimum value of a field (does not need to be a numeric field).
- MAX() – Returns the maximum value of a field (does not need to be a numeric field).
- SUM() – Returns the total summed value of a number field.
These functions can be further enhanced by using GROUP BY clauses (see GROUP BY for more details).
A modifier to a class, method, or variable, which alters its behavior. All annotations start with “@”. In Apex we have access to the follow annotations:
A SOQL query against a table, whose WHERE clauses include a subquery used within a NOT IN clause.
Below is an example which returns the Accounts that don’t have an Opportunity that has been closed won this month.
The values passed into a method when it is called during runtime. This is in contrast to the parameters, which is the variable we define when we are writing our code.
Code which does not immediately execute upon being called. There are four ways to run Apex asynchronously:
- Queueable Apex – see Queueable Class.
- Schedule Apex – see Scheduled Class.
- Batch Apex – see Batch Class.
- Future methods – see Future Method.
An annotation on a static method, or an instance variable to flag its use within Lightning Components or Flow.
- Static method: Flags this method as being callable by a Lightning Component. In this use case the annotation can also be defined as “@AuraEnabled(cacheable=true)”, which caches the return value client side, allows the method to be used by the Wire service, and prevents any DML from being done.
- Instances variable: Indicates that this variable should be serialized when sent to a Lightning Component, or that the class and variable can be used as a custom data type within a Flow. If the variable is defined as a variable with a valid get and set block, it allows a Lightning Component to use this data type as parameters in AuraEnabled methods.
A class which implements the Batchable interface, enabling the class to be executed as a batch job. Batch Apex runs asynchronously and can process a large number of records in batches with a size between 1 and 2000.
The Batchable interface is made up of three methods:
- Start: Used to get the records/objects which will be processed by the batch job, usually this will return a QueryLocator for a query instead of a list of records.
- Execute: The doing part of the batch class, this method is called for each batch to be processed.
- Finish: Called after all the batches have been processed (regardless of whether they succeeded or not), used for any post job actions, e.g., sending status emails to an admin about the job status.
A HTTP request to an external service outside Salesforce. These utilize the Http, HttpRequest, and HttpResponse classes to allow a piece of Apex code to communicate with an external web service – usually by transmitting some JSON or XML.
The specifics of a callout depends entirely on the external service to be called, but when we’re talking about how we communicate with them, it’s almost always through the use of a callout.
A class which acts as the logic behind a Visualforce page or exposes AuraEnabled methods for consumption within a Lightning Component, e.g. gets records or updated records. These classes are named due to the Model View Controller design pattern for user interfaces.
These classes will usually be named as so:
Custom Metadata (CMDT)
Custom metadata types are like special types of objects defined separately from standard objects. These are custom pieces of metadata that you have control of (as a developer), allowing you to build customizable pieces of code rather than having to hard code everything.
Using CMDT allows you to create records/instances of the type which can be queried/accessed at run time to customize how a piece of code runs. This could be anything from defining fields or dynamically building a custom related list, to defining the specific slug for use within an integration.
These records are then accessible through both code and config tools, with the ability to access them declaratively by name or through programmatic techniques, such as free SOQL queries (since they are cached!).
Custom settings are very similar to CMDT and come in two distinct types:
- List: These behave similarly to custom metadata, except they can be written to synchronously by Apex, just like a normal record. If this is not a requirement, CMDT is a better choice!
- Hierarchical: These allow customizations to be defined on a hierarchical nature, ranging from org-wide defaults to specific customizations based on a profile or even on a user-by-user basis.
A design technique in which the dependencies of a class are externally defined and any dependency a class may have on external classes is no longer tightly coupled to a class, enabling it to be mocked during a test.
Using this technique, a class instead receives its dependencies externally, usually via constructors or less favorable @TestVisible static variables. This means that when we wish to test a class that consumes other classes, we can mock the other classes and their return values. Essentially, this allows us to test a specific piece of code in isolation, without needing to implicitly test other pieces of code (which should have their own tests!). This increases reusability, testability, and maintainability of our codebase, but can be more difficult to begin developing with initially!
DML, short for Data Manipulation Language, describes a statement we use to manipulate data stored in the database.
We use the following keywords throughout our code to achieve this:
Some of these DML statements are also present within the Database class, alongside some other methods which do not have corresponding statements, such as convertLead().
Usually, when we’re writing Apex code we do so declaratively – that is, we are explicitly stating what our intent is, e.g. what fields and objects we are working with. This is usually done via dot notation when accessing fields on an object, or by using the square brackets when writing a SOQL query. We have explicitly written what we wish to happen at design time.
Dynamic programming turns this process on its head by having the specifics about an action or a query be inferred at run time based on the pieces of data available. This could be as simple as dynamically building a query from a field set, to something more complex such as creating a parent and a child record based on abstract data.
An error thrown by code which disrupts the normal execution of code. These usually happen when a piece of code is attempting to do something it cannot (e.g., access a field on an Account variable which has never been set). There are many built-in exceptions, but user defined ones can be written to customize the execution flow of custom code where appropriate.
If an exception is thrown and not handled, the transaction will be terminated and rolled back.
A static method annotated with the “@future” annotation, the flags that the method runs asynchronously in the background after the transaction which called it finishes. This is useful for running any operation that needs to be run asynchronously, such as callouts to external systems, or mixed DML operations. Future method parameters must be primitives only, not allowing complex parameters such as SObjects.
Usually, when needing new asynchronous methods, Queueable Apex should be chosen over future methods as Queueable Apex is the evolution of future methods. However, some use cases, such as conditionally running asynchronously, still favor future methods.
A common name for a class which contains some code destined to be reused within many different classes across the codebase e.g., you may have a JwtHelper class to assist in the creation of JSON web tokens.
Migrating the code out into its own class helps to improve the maintainability of the system. While it can be common for these classes to have the suffix “Helper”, it isn’t a requirement, and any piece of code intended to be reused may be called a helper class, a module, or a utility class.
When a class extends a virtual/abstract class, we call this inheritance. This enables one class (the subclass) to inherit behaviors (in the form of methods and potentially variables/properties) from another class (the super class). This is done using the “extends” keyword in the class’s signature.
Inheritance is a core concept of Apex and can facilitate greater maintainability of complex codebases when done correctly.
It can also be found in use within the standard Apex toolset, for example, the Account SObject class inherits from the base SObject class, granting the Account class the ability to call the generic methods such as get() and put() which are present on the SObject class. It also allows things such as List<SObject> to be able to contain any type of SObject since they all inherit from the base SObject, and so can all be treated as instances of it.
An interface is a way for us to define a template for a class, defining the methods which it must implement, but not the method bodies. Another class which wishes to consume the interface can do so by stating in its class definition that it implements it. This then forces the class to define and implement the methods listed in the interface. Unlike class extensions (see abstract and virtual classes), a class can implement as many interfaces as required.
A common example of interfaces can be found within the standard Batchable, Schedulable, and Queueable interfaces provided to us by Salesforce.
A static or instance variable which has been modified to include a getter and a setter. These are small pieces of code that are run when accessing or setting the variable. This can be useful for lazy initialization of variables. These can also be used to provide different access modifiers to read and write e.g. a private write variable.
A method with the access modifier “protected” (as opposed to the usual public/private). This acts like a private method, with one major exception; a protected method is accessible to any class extending the class where it is defined.
A type of asynchronous Apex designed to be the evolution of future jobs by combining their simplicity with the power of batch jobs. Queueable classes provide us with a structure to enable advanced asynchronous processing by defining our class (which does the processing), then invoking it and getting a job Id so we can track it if required.
Queueable Apex takes future methods a step further by allowing us to use complex objects (including SObjects) as parameters when queuing the job – a major advantage over future methods which only allow primitives.
Jobs can also initialize another queueable, allowing for jobs to be chained (starting one when one finishes) to allow sequential processing. A transaction finalizer can also be attached to a queueable, allowing actions to be taken upon the completion of a queueable job, such as handling errors.
A SOQL query which references related objects to the queried object.
- Child query: A subquery added into the SELECT clause that returns child records alongside the queried records. This type of query uses the plural relationship name.
- Parent query: Fields included in the SELECT clause which target a record that the target object looks up to. This is done via dot notation e.g., Account.Name, for custom objects the relationship field is suffixed with __r instead of __c.
A class which can be set to run at a specific time (give or take a little), either by queueing it with other Apex code and providing it a cron expression of when to run, or through the UI to schedule it with far less precision.
These classes feature an execute method which is called when the platform invokes the method at the scheduled time. This can be useful for periodic syncs with external systems, or for checking whether or not a batch class is required to be queued for an overnight job.
A SOQL query against a table, whose WHERE clauses include a subquery used within an IN clause. Below is an example which returns the Accounts which have an Opportunity which has been closed won this month.
A design pattern for a class that only allows a single instance of a class to ever be initialized at once. Typically, this type of class will have a private constructor. When we wish to get an instance of this class, we will call a public static method which either initializes or returns the already initialized instance of the class.
Singletons are useful when specific expensive actions (e.g., get an Account Id for a specific business unit) might need to be performed or potentially repeated throughout a transaction – singletons can be a good choice in ensuring these actions are performed only as required.
The query language used to interact with the Salesforce database. Unlike SQL, SOQL is only used for reading data from database tables, not for writing records, which instead uses DML within Apex.
Triggers are pieces of Apex code invoked on database actions (e.g., record creation or update), enabling custom pieces of functionality to be run. This ranges from calculations and complex validation to preventing record deletion.
Triggers are split into two types:
Before trigger: Run before a record has been saved into a database and commonly used to perform same record calculations and validations.
After trigger: Run after the record has been saved to the database. The records going through an after trigger are read only and so these types of triggers are usually used when fields set by Salesforce are required (e.g. a record Id in a create trigger), or when performing actions on records other than the record which caused the trigger to be invoked.
A trigger framework is a standardized way of writing triggers within Salesforce. There are many different trigger frameworks and approaches, but they all share a common goal of shifting any logic out of the trigger and into separate classes which can be more easily maintained and tested.
Usually trigger frameworks make use of virtual classes, interfaces, or a static trigger handler class to facilitate the invoking of business logic in a generic and consistent manner (which the actual trigger delegates to when it is run).
Some trigger frameworks come with additional functionality, such as allowing configuration to control which actions are invoked and their invocation order (e.g., EDAs TDTM), whereas others may be entirely written in code.
A construct to handle exceptions thrown by code. These consist of two or three blocks of code:
- Try: This block of code is where some dangerous code is executed.
- Catch: One or more blocks of code which have a parameter, this parameter is the type of exception to be handled. This block is only called if an exception is thrown within the try block, and the exception type matches the catch’s parameter – this can be the generic Exception to handle all exceptions thrown.
- Finally: A block of code to execute after the try or any catches has finished executing.
A DML statement which is a combination of insert and update. If a record Id is specified, this operation acts like an update. If no record Id is specified, this operation acts like an insert. This operation can also take in an additional parameter, an external Id field, which when specified is used to determine whether a record should be updated or inserted.
A class which has been defined with the “virtual” keyword. This type of class is very similar to an abstract class, except virtual classes can be initialized. Virtual classes allow the use of virtual methods; these methods are the same as normal methods, except the virtual keyword allows a class which extends a virtual class to optionally override the behavior of a virtual method. A class can only extend one other class.
A design pattern and common term for when pieces of disparate information need to be grouped together to simplify the transferal or manipulation of these pieces of information, but without requiring its own methods. These are commonly used within Lightning Components and VisualForce to group SObjects and related information (e.g., sibling records or computed values) to be consumed in the UI, which would otherwise be difficult to do without a wrapper class.
There are a lot of different terms floating around the subject of Apex development – some of which require technical skills and experience to fully understand. Hopefully, after reading this glossary, the next time you hear one of these terms thrown across a room you’ll be fully ‘in the know’… or at the very least you’ll know what to Google afterwards – something even us pro Salesforce Developers do all the time!