I’m studying for the Platform Developer 1 exam and refreshing myself on Apex concepts. Sure, I could just use guides provided on Focus-on-Force, but where’s the fun in that?
Honestly, I find more enjoyment in doing Trailmixes, creating my own study notes, and asking ChatGPT a billion clarification questions.
I figured I’d share some of what I’m working on with you guys. Most of this information comes directly from Salesforce’s Developer or Object Reference Guides. All I’ve done (for the most part) is aggregate them in one place, added clarification where I felt was necessary, and added as many links as possible to where I found the information. None of this information is mine, and I will never sell you any of these “cheat sheets”. I have to say this because there are so many people pretending to be me across various social media sites.
By the time this guide is complete, it will more than likely be 50+ pages. I’ll post what I’ve learned once a week until the next exam.
Things You Probably Didn’t Know You Could Do
You can pass values to the constructor of sObjects and custom objects in Apex when instantiating the objects. The actual implementation of this isn’t shown to you and the documents don’t do a good job at explaining this feature.
Example: Account a = new Account(name = 'Acme', billingcity = 'San Francisco');
Cloning sObjects will create a copy of an sObject record
Lightning Platform
The lightning platform is Salesforce’s SaaS offering that relies on its metadata-driven architecture. Because of this, it allows for a lot to be accomplished with declarative, or point and click development. It’s important to understand from a solutioning perspective when code should and should not be used.
Apex Basics
Apex is Salesforce’s Object-Oriented programming language. Apex is saved, compiled, and executed directly on the Lightning Platform.It supports many of the OOP principles that other languages have such as encapsulation, abstraction, inheritance, and polymorphism. Constructs such as classes, interfaces, properties, and collections are available as well.
Example Apex
public with sharing class HelloWorld {
public void printMessage() {
String msg = ‘Hello World’;
System.debug(msg);
}
}
Classes can have the following modifiers:
And can either implement an interface and/or extend another class. Below is an example displaying our options with valid syntax.
private | public | global
[virtual | abstract | with sharing | without sharing]
class ClassName [implements InterfaceNameList] [extends ClassName]
{
// The body of the class
}
Classes
Access Modifiers for Classes
Private: The private modifier specifies that the class can only be accessed from within the class itself, this same logic also applies to variables as well. In fact, most variables you create should be private. You really want to only allow outside classes or outside code to access pieces of your class that it should be able to access. Keep in mind that classes can be nested within classes.
Public: The public modifier specifies that the class can be accessed by another other class within the same Salesforce organization.
Global: A global class is accessible from any Apex code within or outside the current namespace. In other words, other Apex code in the same Salesforce organization or in different organizations can instantiate and use this class.
Protected (only applies to methods and variables): Protected variables and members can only be invoked within its own class or any subclasses that extend it.
Definition Modifiers
Virtual: Declares that a class/method can allow extensions and overrides. Class methods cannot be overridden unless the class has been defined as virtual, and child classes cannot be forced to implement the methods of the parent. That’s what Abstract classes are for. A virtual class can be instantiated directly, whereas an abstract class cannot. Virtual methods can have a default implementation that is inherited by child classes. Virtual classes can be instantiated directly, i.e new TestVirtualClass();
Abstract: Declares that a class contains abstract methods, methods that only have their signature declared and no body defined. Abstract classes can be extended as well, but their methods which are only signatures must be implemented in their child class. Only abstract classes may contain abstract methods. They can contain virtual methods as well. Abstract classes cannot be instantiated directly, i.e new TestAbstractClass(); However, they can have some implementation details in their non-abstract methods as noted below.
// DataFactory.cls
public abstract class DataFactory {
public abstract sObject getRecord();
public sObject createRecord() {
sObject record = this.getRecord();
insert record;
return record;
}
}
Here’s a chart, just in case the source is taken down
When using a class that is abstract or virtual, the usage is more of like a contract (ex: when extending this class, we guarantee that methods x, y, and z will be available. We also guarantee that variables a, b, and c will be available as well).
By relying on contracts, a change to a specific implementation of that contract is contained to 1 or 2 classes instead of changing the parent class which might cause every implementation of that class to change. The overall idea is that we want our code to be as resistant to change as possible and this is done by implementing our code like contracts.
With that being said, when you need to implement a contract, you’re more than likely going to be using abstract classes because you want consumers of the code to build specific implementations that will suit the task at hand, rather than a “catch all” implementation. Also, as stated earlier, abstract classes’ inability to be directly constructed is more useful.
With sharing: Enforce the sharing rules of the current user. Explicitly using this keyword ensures that Apex code runs in the context of the current user.
Without sharing: Ensure that the sharing rules for the current user are not enforced. For example, you can explicitly turn off sharing rule enforcement when a class is called from another class that is declared using ‘with sharing’.
Inherited sharing: run the class in the sharing mode of the class that called it.
Interfaces
An interface is like a class where none of the methods have been implemented OR have access modifiers. Essentially what you have are method signatures with NO body. To use an interface, another class has to implement it by providing a body for all of the methods contained in the interface.
Interfaces create a strict layer of abstraction between where a code is defined and where its implemented. This allows for many people to have different implementations of an interface’s methods for specific use cases.
Unlike Abstract and Virtual classes, developers must implement every method contained within an interface.
With interfaces, the goal is to create a new layer of abstraction
Real Life Use Case of an Interface
When unit testing in Apex, sometimes you will want to create a mock object, or a fake object that essentially imitates the behavior of a real one. Mock objects have an EXCELLENT use case in unit testing because they allow us to test for expected behaviors without having to rely on an underlying data source (like an external database or a server/api which could affect our test results due to downtime, for example).
What if we needed to test a class that made HTTP callouts? The more that I think about it, making repeat HTTP callouts, even when testing doesn’t seem like a good idea. You would probably be rate limited. (Someone clarify this for me please)
To test positively and avoid the negative side effects of repeat HTTP callouts, We could create an interface with method signatures that name the expected properties/behaviors of an HTTP Callout, and then create mock objects that implement that interface. Then, we have to implement the methods contained in the HTTP callout interface in our mock objects. In the actual implementation, we could have methods that expect certain information, throw exceptions at certain points based on what the user provided, and return valid outputs based on what the user provided.
The end result is that this interface we created for HTTP callouts allowed us to create a mock object which helps us get reliable, consistent result results.
We’ve separated the idea from the implementation in a practical manner. I believe this is rather scalable as well as a team of 10+ people could use the implementation that you created which contributes to not duplicating code. Keep in mind, as people create more classes, test classes must be written as well. Having so much code in an environment significantly increases the time it takes to do a deployment.