While there is no doubt there is an abundance of Apex programming documentation for both the novice and the advanced developer available, we often find the material is too broad or potentially written by a marketing or tech writer rather than day to day developers.
Dan’s book on Advanced Apex Programming is written by a seasoned developer (himself) in which he provides real-world concepts about Apex design patterns, best practices, and solutions to greatly increase your Apex programming proficiency.
Since this is the 4th edition of Dan’s book, a few items to note of significance:
- Primary focus is on SalesforceDX and Lightning
- Rather than unmanaged packages and zip files, the sample code is provided in Dan’s GIT repository
- Code examples are broken out and associated by branches in GIT to directly associate to the chapter being discussed for easier correlation
- Due to Salesforce’s continuous re-branding, Dan uses terms interchangeably whether we’re talking about force.com, the Salesforce platform, or the Lightning platform
Two of the core concepts that Dan initially covers which help in the core understanding of Apex development are:
- Understanding how Apex interacts with the underlying Salesforce system as a whole
- In depth understanding about: Execution Contexts, Static Variables, Bulk Patterns and Governor Limitations
These philosophies may be common place for an experienced Salesforce developer (probably 5+ years), but for those who have a traditional Java, C#, VB, .NET, and other structured language background, these are concepts (and associated challenges) that directly relate to cloud computing, particularly on the Salesforce platform.
Let’s dive into what some of these mean for a Salesforce developer and how one leads to the next:
- Execution Context: Multiple triggers on an event can cause the developer to have no control of the order the triggers execute in causing massive confusion and unwanted outcomes (i.e. trigger calls another trigger that calls a workflow that then calls another trigger).
- Using static variables: Allows a developer to help control the Apex execution, context and scope to help prevent code being called multiple times undesirably, while also running into Governor limits.
- The understanding of Apex limits and how it has a profound impact on your architecture and design patterns. Although, most developers will rarely run into SOQL query limits, this book helps enforce the importance of: bulk syntax, using Before versus After triggers, caching data results, and limiting the fields you bring back in your queries. Other limitations that Dan covers include limits on CPU time (particularly in bulk operations), DML operations, Heap Size, Call Outs/API’s/Emails and 24-hour limits such as Batch Apex, Future Methods, Queueable and Extended Apex.
- Bulk patterns: one of the most important patterns that Dan educates the reader on is bulk patterns and if you can think and design your code to handle bulk operations, you’ll be able to build more efficient solutions up front, versus writing code for a single object and then having to convert it later.
To the novice developer, they may never imagine how their process could run into a governor limit, but Dan provides examples of how processing 1 piece of logic without taking bulk into account could quickly escalate into problems, not just in the internal processing, but also at the external web services layer as well.
The next area that Dan drills into further is best practices around architectural and design patterns along with possible underlying issues that may be presented.
- Collections: how to keep track of only the objects that need to be updated to help improve the efficiency of your operations. For example, triggers and how to programmatically provide better predictability within your application by maintaining a centralized trigger framework that controls the order of execution.
- Asynchronous operations: how to work around not being able to make a callout to web services within a trigger, the number of callouts you’re limited to, the amount of data that you can pass, the timeouts associated to external server’s response times. As well as the value and drawbacks to: Batch Apex, Scheduled Apex, Future Calls, Queueable Apex and Platform Events.
- Application configuration: Database objects, custom settings, and custom metadata and determining which is the best approach based on your specific requirements along with the design patterns to work around query limits by combining the different solutions.
The third section that Dan covers which is probably the most important as it has the biggest impact on the outcome of your development success: testing, debugging, and deploying your Salesforce solutions with a strong emphasis on SalesforceDX, as this tool is now fitting more into the modern development methodology many of us are used to such as source control, automated testing and building, as well as continuous integration.
As most developers know, when it comes to debugging and diagnosing Apex, the 3 essential areas that are involved are:
- A way to reproduce the issue
- A way to capture data about the issue
- A way to modify the code to remedy the issue
If you find yourself running into constraints among these 3, Dan provides some ideas and examples to overcome them by building a diagnostic framework.
- Creating a diagnostic instrumentation class that acts as a call stack to quickly find where the problem lies versus filtering through unnecessary lines in the debug log.
- A centralized trigger dispatcher that allows every method to have its own exception handler to account for the annoying, cryptic error messages a user receives (Apex: Unexpected Exception, Null Pointer Exception, blah, blah, blah).
- Creating a custom object to monitor users 24X7 to overcome limitations of the debug log size (which I believe has also increased over the last few releases based on developers feedback).
When it comes to unit testing, traditionally, developers make sure their code doesn’t break other developer’s code, but when it comes to Salesforce, the bigger challenge is the declarative metadata update that an admin makes and the adverse impacts it can have. Due to this, Dan advises that functional and integration testing should be a higher priority versus unit testing and provides these 4 test patterns:
- Centralizing object initializing for easier code maintenance
- Using Test.loaddata to allow for loading test data from a static resource
- Organizing tests into classes with multiple test methods to allows tests to relate to each other
- Using the @Testsetup annotation to initialize your data for all your test methods for a given class
Additionally, Dan highlights the importance of building every unit test as a bulk test and to make sure your batch size is configurable. This will allow all the benefits for bulk testing at almost no cost in relation to validating the functionality of your batch handling and assuring your processing meets the required Salesforce governor limits.
When it comes to managed packages, Dan also has you covered, regarding some of the challenges with namespaces and the behavioral differences with these such as:
- Inability to access custom settings that are not part of the package
- Duplicate fields that appear in SOQL queries
Dan provides suggestion to these either with SalesforceDX using namespaced Scratch Orgs or by having customers make modifications to their existing code and to use custom metadata. Additionally, the book also goes into detail regarding best practices for designing managed packages using Dynamic SOQL and Dynamic Apex.
The last great point the author points out regarding Apex development and the maintenance of your Apex code, is that coding makes up about 10% of a projects lifecycle and the other 90% includes requirements gathering, design documentation, testing and maintenance. Therefore, once code has been deployed, the costs of a bug increase dramatically, and not just bugs from a developer’s error, but when metadata changes occur such as a workflow, validation rule, flow or lightning process, as well as Salesforce’s seasonal releases which are uncontrollable.
In conclusion, this book covers much more than writing code, but rather how to create patterns and frameworks to help reduce the maintenance costs. This includes, centralized exception handling, defensive programming to account for metadata changes, and better diagnostics to help monitor your application.
Outside of these concepts, Dan also recommends the use of SalesforceDX as your single source of truth, using a testing Sandbox to stage and test your metadata changes, and lastly having the proper internal governance and change management processes in place, which I think we can all agree always can be better.
This book can be found on Amazon at: