Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Save more on your purchases now! discount-offer-chevron-icon
Savings automatically calculated. No voucher code required.
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Conferences
Free Learning
Arrow right icon
Arrow up icon
GO TO TOP
Mastering Apex Programming

You're reading from   Mastering Apex Programming A Salesforce developer's guide to learn advanced techniques and programming best practices for building robust and scalable enterprise-grade applications

Arrow left icon
Product type Paperback
Published in Nov 2023
Publisher Packt
ISBN-13 9781837638352
Length 394 pages
Edition 2nd Edition
Languages
Concepts
Arrow right icon
Author (1):
Arrow left icon
Paul Battisson Paul Battisson
Author Profile Icon Paul Battisson
Paul Battisson
Arrow right icon
View More author details
Toc

Table of Contents (28) Chapters Close

Preface 1. Section 1: Triggers, Testing, and Security
2. Chapter 1: Common Apex Mistakes FREE CHAPTER 3. Chapter 2: Debugging Apex 4. Chapter 3: Triggers and Managing Trigger Execution 5. Chapter 4: Exceptions and Exception Handling 6. Chapter 5: Testing Apex Code 7. Chapter 6: Secure Apex Programming 8. Section 2: Asynchronous Apex
9. Chapter 7: Utilizing Future Methods 10. Chapter 8: Working with Batch Apex 11. Chapter 9: Working with Queueable Apex 12. Chapter 10: Scheduling Apex Jobs 13. Section 3: Integrations
14. Chapter 11: Integrating with Salesforce 15. Chapter 12: Using Platform Events 16. Chapter 13: Apex and Flow 17. Chapter 14: Apex REST and Custom Web Services 18. Chapter 15: Outbound Integrations – REST 19. Chapter 16: Outbound Integrations – SOAP 20. Chapter 17: DataWeave in Apex 21. Section 4: Apex Performance
22. Chapter 18: Performance and the Salesforce Governor Limits 23. Chapter 19: Performance Profiling 24. Chapter 20: Improving Apex Performance 25. Chapter 21: Performance and Application Architectures 26. Index 27. Other Books You May Enjoy

Retrieving configuration data in a bulkified way

No book on Apex is complete without some discussion around bulkification. Bulkification is a requirement in Salesforce due to governor limits that are imposed on developers because of the multi-tenant nature of the platform. Many developers that are new to the platform see the governor limits as a hindrance rather than an assistance. We will cover this in more detail in Chapter 18, Performance and the Salesforce Governor Limits. However, a common mistake that developers make on the platform is to not bulkify their code appropriately—particularly, triggers. It is also common for intermediate developers to not bulkify their non-trigger code appropriately either. We will discuss the bulkification of triggers more explicitly in Chapter 3, Triggers and Managing Trigger Execution, and will cover querying and Data Manipulation Language (DML) within loops later in this chapter. Firstly, however, I want to discuss bulkifying the retrieval of data that is not typically stored in a custom or standard object—configuration data.

Hot and cold data

I want to begin this section with a discussion on hot and cold data within the system, as well as the implications this has on bulkification. For all of the data within our system, let us assume that the data starts off with a temperature of 0 (our scale should not matter, but let us assume we are using Celsius, where 0 is freezing and 100 is boiling). Every time our data is written to, its temperature increases by one degree, and if an entire day goes without it being updated, it drops a degree and decreases by one. If we were to run this thought experiment across our data, we would then obtain a scale for each data type we are retrieving, where the data would range from very cold (that is, hardly ever written to) through to extremely hot (edited multiple times a day).

For most objects in Salesforce, the temperature graph of the data would appear in a long-tailed distribution manner—that is, an initial peak of activity as a record is created and then updated until it reaches a stage in its life cycle where it is no longer viewed and only really included for auditing and reporting purposes. Think of an opportunity record, for example: a lot of initial activity until it is closed, won, or lost, and then it is used mainly for reporting. When working with these records in Apex, we will need to ensure we query for them to get the latest version for accurate and up-to-date data. As we are in most cases not writing Apex to work on “cold” instances of this data, we need to be aware of the fact that these records may change during the scope of a transaction due to an update we are making. Our normal bulkification practices, discussed next, will help us manage this.

What about data that is truly cold—that is, created for all intents and purposes but never updated? Think of a custom metadata record that holds some configuration used in an Apex process. Such information is created and then only updated when the process itself changes. For such data, we actively want to avoid querying multiple times during a transaction yet ensure that it can be made available across the entire transaction as needed. As Salesforce applications have grown and more custom configuration has been added to make the applications more dynamic and easier to update, more organizations (orgs) have deployed custom metadata, custom settings, and custom configuration objects (although these are now largely superseded by custom metadata and custom settings). How do we as developers manage retrieving this data in a manner that is bulkified and that allows us to reuse this data across a transaction?

Retrieving and sharing data throughout a transaction

For this use case, a developer can either use the singleton pattern or make appropriate use of static variables to manage the retrieval of this data. We could implement a singleton utility class, as follows:

public class ExampleSingleton {
    private static ExampleSingleton instance;
    private Example__mdt metadata;
    public static ExampleSingleton getInstance() {
        if(instance == null) {
            instance = new ExampleSingleton();
        }
        return instance;
    }
    private ExampleSingleton() {
    }
    public Example__mdt getMetadata() {
        if(metadata == null) {
            metadata = [SELECT Id FROM Example__mdt LIMIT 1];
        }
        return metadata;
    }
}

Our private static member variable—instance—holds the unique instance of the ExampleSingleton class for the transaction. The getInstance method is the only way of either instantiating or retrieving the instance for use, and we have ensured this by making the default constructor private. We can use this instance to retrieve our Example__mdt record, using the getMetadata method on our returned instance. The actual instance of the Example__mdt record is stored as a private member for the class and is state abstracted away from the change.

The benefit of such an approach is that we can encapsulate both our data and its workings and ensure that we are only ever retrieving the information from the database once. This singleton could be used to hold many different types of data as needed so that the entire transaction can scale in its usage of such data in a common way.

Alternatively, we could implement a static class such as the following one:

public class ExampleStatic {
    private static Example__mdt metadata;
    public static Example__mdt getExampleMetadata() {
        if(metadata == null) {
            metadata = [SELECT Id FROM Example__mdt LIMIT 1];
        }
        return metadata;
    }
    private ExampleStatic() {
    }
}

Again, we have ensured that our metadata will only be loaded once across the transaction and have a smaller code footprint to manage. Note that this is not a true static class, as these are not available in Apex. However, there is a close enough analogy to this in the language that we can consider as a static class (it cannot be externally instantiated due to its private constructor).

For cold data such as custom metadata, custom settings, or any custom configuration in objects, the use of a singleton or a static class can greatly improve bulkification. I have seen instances in production where the same set of metadata records was retrieved multiple times during a transaction as the code began to interact by recursively firing triggers through a combination of updates.

Singleton versus static class

It is a fair question to ask right now whether a singleton or a static class instance should be used in utility classes. The answer (as with all good questions) is it depends. While both have similar functionality from our perspective in terms of retrieving data only once, singletons can be passed around as object instances for use across the application. They can also extend other classes and implement interfaces with the full range of Apex’s object-oriented (OO) features. While static classes cannot do this, they are more useful in lightweight implementations where the OO features of the language are not required.

As we will discuss in the final section of the book when speaking about performance, we must always be aware of the trade-offs we are making when we are implementing a particular performance improvement. In this instance, we have statically cached our data to reduce the number of queries we are making within our code. In doing so, we have increased the amount of data stored on the heap. The heap is also a finite resource with a fixed governor limit, and as such, statically caching too much data can cause us to overuse the heap and fall foul of that governor limit. Thus, we must always be careful of the choices we are making and the implications of any performance improvement. We will cover this in much more detail in the final section of the book, but I wanted to ensure this was called out now to highlight the fact there is always a trade-off.

You have been reading a chapter from
Mastering Apex Programming - Second Edition
Published in: Nov 2023
Publisher: Packt
ISBN-13: 9781837638352
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at €18.99/month. Cancel anytime