Search icon CANCEL
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 developer's guide to learning advanced techniques and best practices for building robust Salesforce applications

Arrow left icon
Product type Paperback
Published in Nov 2020
Publisher Packt
ISBN-13 9781800200920
Length 368 pages
Edition 1st Edition
Languages
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 (21) 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 and Apex REST
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. Chapter 11: Using Platform Events 14. Chapter 12: Apex REST and Custom Web Services 15. Section 3 – Apex Performance
16. Chapter 13: Performance and the Salesforce Governor Limits 17. Chapter 14: Performance Profiling 18. Chapter 15: Improving Apex Performance 19. Chapter 16: Performance and Application Architectures 20. Other Books You May Enjoy

Hardcoding

The final common mistake I want to discuss here is that of hardcoding within Apex—particularly, hardcoding any type of unique identifier such as an ID or a name. For IDs, it is probably quite obvious for most developers as it is well established that between different environments, including sandbox and production environments, IDs can and should differ. If you are creating a sandbox from a production environment, then at the time of creation, the IDs are synchronized for any data that is copied down to the sandbox environment. Following this, IDs do not remain synchronized between the two and are generated when a record is created within that environment.

Despite this, many developers, particularly those working within a single environment such as consultants or in-house developers, will hardcode certain IDs if needed. For example, consider the following code:

for(Account acc : Trigger.new) {
	if(acc.OwnerId = 'SOME_USER_ID') {
		break;
	}
	//do something otherwise
}

This code is designed to skip updates on account records within our trigger context owned by a particular user, most commonly an application programming interface (API) user or an integration user. This pattern enables a developer to filter these records out so that if an update is coming via an integration, actions are skipped and the integration can update records unimpeded.

Should this user ID change, then we will get an error or issue here, so it is wise to remove this hardcoded value. Given that the ID for the user should be copied from production to any sandboxes, you may ask why this is needed. Firstly, there is no guarantee that the user will not be changed for the integration, going forward. Secondly, for development purposes, when initially writing this code, the user will not likely exist in the production organization (org), and so, in your first deployment, you will have to tweak the code to be environment-specific. Thirdly, this also limits your ability to test the code effectively, going forward. We will see how shortly.

As an update to this code, some may recommend making the following change (note that this is precisely the instance where we would extract this query to a utility class; however, we are inlining the query here for ease of display and reading):

for(Account acc : Trigger.new) {
    User apiUser = [SELECT Id FROM User WHERE Username = 'my.    api@user.com'];
    if(acc.OwnerId = apiuser.Id) {
		break;
    }
    //do something otherwise
}

This code improves upon our previous code in that we are no longer hardcoding the user record ID, although we are still hardcoding the name. Again, should this change over time, then we should still have an issue, such as when we are working in a sandbox environment and the sandbox name is appended to the username. In this instance, the code would not be executable, including in a test context, without updating the record to be correct. This could be done manually every time a new sandbox is created, or through the code in the test. This means that our test is now bound to this user, which is not a good practice for tests, should the user change again.

In this instance, we should remove the name string to a custom setting for flexibility and improved testability. If we were to define a custom setting that held the value (for example, Integration_Settings__c), then we could easily retrieve the custom setting and the username for a query at runtime without the query, as follows:

for(Account acc : Trigger.new) {
    Integration_Settings__c setting = Integration_Settings__c.    getInstance();
    User apiUser = [SELECT Id FROM User WHERE Username =     setting.Api_Username__c];
    if(acc.OwnerId = apiuser.Id) {
		break;
    }
    //do something otherwise
}

Such a pattern allows us many benefits, as follows:

  • Firstly, we can now apply different settings across the org and profiles, should we so desire. This can be increasingly useful in orgs where multiple business units operate.
  • Secondly, for testing, we can create a user within our test data and assign their username to the setting for the test within Apex. This allows our tests to run independently of the actual org configuration and makes processes such as continuous integration (CI) simpler.
  • Finally, we could extract both of these lines (the retrieval of the custom setting and the user query) to a utility class to abstract away, for the entire transaction to use as needed.
You have been reading a chapter from
Mastering Apex Programming
Published in: Nov 2020
Publisher: Packt
ISBN-13: 9781800200920
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 $19.99/month. Cancel anytime