Defensive Apex Programming
Dan Appleman
CTO – Full Circle Insights, Author of Advanced Apex Programming
dan@fullcircleinsights.com
@danappleman
What is the difference between a coder (“code monkey”)
and a software developer?
Say what???
The Software Application Life-Cycle
Requirements
Design
Code
Test/QA/Doc
Maintenance
The Software Application Life-Cycle - Traditional
Requirements
Design
Code
Test/QA/Doc
Maintenance
• Bug fixes
• New OS version/browser
• Platform changes
• Regression testing of
changes by developers
• Critical features
The Software Application Life-Cycle – Salesforce Platform
Requirements
Design
Code
Test/QA/Doc
Maintenance
• Bug fixes
• Platform updates (3x per year)
• Regression testing of changes
by developers
• Critical features
• Metadata changes that
change the behavior of the
code.
Traditional Applications
Platform
Your App
Platform
Apex
Other declarative
metadata changes
Apex Applications
Defensive Apex Programming
Making a Future Call – The Wrong Way
public void CallFuture1()
{
vulnerableFutureCall();
}
@future
public static void vulnerableFutureCall()
{
// Do something here
}
Making a Future Call – The Wrong Way
public void CallFuture1()
{
vulnerableFutureCall();
}
@future
public static void vulnerableFutureCall()
{
// Do something here
}
• Other app calls this in a future context?
• Batch calls this?
• Other code makes future calls and we hit limit?
• An error occurs during the future call?
(you’ll never know it)
Defensive Future Calls
public void CallFuture2()
{
if(System.isFuture() || system.isBatch()) defensiveFutureCallSync();
else {
if(Limits.getFutureCalls()< Limits.getLimitFutureCalls())
defensiveFutureCallAsync();
else { // ????
}
}
}
@future
public static void defensiveFutureCallAsync()
{
defensiveFutureCallSync();
}
public static void defensiveFutureCallSync()
{
// Do something here
}
• Backs up to sync pattern (if applicable)
• Alternatives include try/catch & logging errors
instead
• Reliable async is a much bigger topic...
Using a Custom Setting – The Wrong Way
Boolean enabled = ConfigSettings__c.getInstance('default').Application_Enabled__c;
Guaranteed null reference exception on:
• Uninitialized orgs/sandboxes (metadata push)
• SeeAllData false tests on methods that don’t initialize setting
• SeeAllData false tests on managed package tests that can’t initialize
setting.
Defensive Custom Settings
private static ConfigSettings__c testConfig;
public static ConfigSettings__c getConfig()
{
if(Test.isRunningTest() && testConfig!=null) return testConfig;
ConfigSettings__c result = ConfigSettings__c.getInstance('default');
if(result==null)
{
result = new ConfigSettings__c(name='default', Application_Enabled__c= false);
}
if(Test.isRunningTest()) testConfig = result;
return result;
}
Then...
Boolean enabled = ConfigurationClass.getConfig().Application_Enabled__c;
• Can’t return null
• Protects from DML
errors on parallel tests
• Simplifies test setup
Detecting a Field Change
Demo
Updating Records – Watch For Concurrency Errors
update listOfRecords;
or
List<Database.SaveResult> dmlResults =
Database.Update(listOfRecords, false);
for(Integer x = 0; x< ops.size(); x++)
{
Database.SaveResult sr = dmlResults[x];
if(!sr.isSuccess())
{
for(Database.Error err: sr.getErrors())
{
if(err.getStatusCode() == StatusCode.UNABLE_TO_LOCK_ROW)
{
// Concurrency error
}
}
}
}
Variations include
• try/catch blocks
• setSavePoint/rollBack
• all or nothing
• Logging vs retry
You can’t defend against every metadata change!
Continuous Integration – In Traditional Software Development
Software
repository
Jenkins Build
Developer
Developer
Developer
Continuous Integration – In Salesforce Too!
OrgJenkins Build
Developer
Developer
Developer
Continuous Integration – In Salesforce Too!!!!!!!!!
Org
Developer
Developer
Developer
CI app
Continuous Integration – In Salesforce Too!!!!!!!!!
Org
Developer
Developer
Developer
CI app
Managed PackageCI App
Native TestTracker App
http://AdvancedApex.com/TestTracker
Free private managed package
Open Source
Questions?
Test Tracker tool
http://AdvancedApex.com/testtracker
For more information, see chapter the new chapter
12 “Maintaining Apex” of the just released third
edition.
Also check out:
Career Strategies and Opportunities for Salesforce
Platform Developers on pluralsight.com

Defensive Apex Programming

  • 1.
    Defensive Apex Programming DanAppleman CTO – Full Circle Insights, Author of Advanced Apex Programming dan@fullcircleinsights.com @danappleman
  • 2.
    What is thedifference between a coder (“code monkey”) and a software developer? Say what???
  • 3.
    The Software ApplicationLife-Cycle Requirements Design Code Test/QA/Doc Maintenance
  • 4.
    The Software ApplicationLife-Cycle - Traditional Requirements Design Code Test/QA/Doc Maintenance • Bug fixes • New OS version/browser • Platform changes • Regression testing of changes by developers • Critical features
  • 5.
    The Software ApplicationLife-Cycle – Salesforce Platform Requirements Design Code Test/QA/Doc Maintenance • Bug fixes • Platform updates (3x per year) • Regression testing of changes by developers • Critical features • Metadata changes that change the behavior of the code.
  • 6.
    Traditional Applications Platform Your App Platform Apex Otherdeclarative metadata changes Apex Applications
  • 7.
  • 8.
    Making a FutureCall – The Wrong Way public void CallFuture1() { vulnerableFutureCall(); } @future public static void vulnerableFutureCall() { // Do something here }
  • 9.
    Making a FutureCall – The Wrong Way public void CallFuture1() { vulnerableFutureCall(); } @future public static void vulnerableFutureCall() { // Do something here } • Other app calls this in a future context? • Batch calls this? • Other code makes future calls and we hit limit? • An error occurs during the future call? (you’ll never know it)
  • 10.
    Defensive Future Calls publicvoid CallFuture2() { if(System.isFuture() || system.isBatch()) defensiveFutureCallSync(); else { if(Limits.getFutureCalls()< Limits.getLimitFutureCalls()) defensiveFutureCallAsync(); else { // ???? } } } @future public static void defensiveFutureCallAsync() { defensiveFutureCallSync(); } public static void defensiveFutureCallSync() { // Do something here } • Backs up to sync pattern (if applicable) • Alternatives include try/catch & logging errors instead • Reliable async is a much bigger topic...
  • 11.
    Using a CustomSetting – The Wrong Way Boolean enabled = ConfigSettings__c.getInstance('default').Application_Enabled__c; Guaranteed null reference exception on: • Uninitialized orgs/sandboxes (metadata push) • SeeAllData false tests on methods that don’t initialize setting • SeeAllData false tests on managed package tests that can’t initialize setting.
  • 12.
    Defensive Custom Settings privatestatic ConfigSettings__c testConfig; public static ConfigSettings__c getConfig() { if(Test.isRunningTest() && testConfig!=null) return testConfig; ConfigSettings__c result = ConfigSettings__c.getInstance('default'); if(result==null) { result = new ConfigSettings__c(name='default', Application_Enabled__c= false); } if(Test.isRunningTest()) testConfig = result; return result; } Then... Boolean enabled = ConfigurationClass.getConfig().Application_Enabled__c; • Can’t return null • Protects from DML errors on parallel tests • Simplifies test setup
  • 13.
    Detecting a FieldChange Demo
  • 14.
    Updating Records –Watch For Concurrency Errors update listOfRecords; or List<Database.SaveResult> dmlResults = Database.Update(listOfRecords, false); for(Integer x = 0; x< ops.size(); x++) { Database.SaveResult sr = dmlResults[x]; if(!sr.isSuccess()) { for(Database.Error err: sr.getErrors()) { if(err.getStatusCode() == StatusCode.UNABLE_TO_LOCK_ROW) { // Concurrency error } } } } Variations include • try/catch blocks • setSavePoint/rollBack • all or nothing • Logging vs retry
  • 15.
    You can’t defendagainst every metadata change!
  • 16.
    Continuous Integration –In Traditional Software Development Software repository Jenkins Build Developer Developer Developer
  • 17.
    Continuous Integration –In Salesforce Too! OrgJenkins Build Developer Developer Developer
  • 18.
    Continuous Integration –In Salesforce Too!!!!!!!!! Org Developer Developer Developer CI app
  • 19.
    Continuous Integration –In Salesforce Too!!!!!!!!! Org Developer Developer Developer CI app Managed PackageCI App
  • 20.
  • 21.
    Questions? Test Tracker tool http://AdvancedApex.com/testtracker Formore information, see chapter the new chapter 12 “Maintaining Apex” of the just released third edition. Also check out: Career Strategies and Opportunities for Salesforce Platform Developers on pluralsight.com