Salesforce Test Driven Development

I’ve been fortunate to have worked as a consultant Salesforce architect for the last decade, during this time I’ve encountered an interesting variety of approaches to Agile in the Salesforce space – most of which fitting with the hybrid model unfortunately – what has been noticeably absent is the application of agile engineering practices. Test Driven Development (TDD) is one of most widely understood agile engineering practices (alongside Pair Programming) – and is perhaps the most practical to adopt, however despite the benefits, despite the level of lip-service paid to the subject in practice TDD remains a rarity. With this post I hope to provide a convincing argument to Salesforce developers and architects that TDD does not add overhead to the development lifecycle and in fact the opposite is true. The Salesforce platform in development terms is maturing, the introduction of new tools and techniques such as Salesforce DX (SFDX) are testimony to this. In this context, the idea of developers working ad-hoc and in an undisciplined manner doesn’t fit, instead the consistent application of established engineering practices will play a key role moving forward. No more low quality unit tests (written as an afterthought) and no more random coding conventions and inconsistent standards. Salesforce development teams can no longer choose to hide in the void that sits between declarative development and traditional software engineering, it’s definitely time for some new habits.

This blog post draws together a high-level conceptual view of Test Driven Development with the implementation practicalities unique to the Salesforce platform.

Let’s start with great quote to set the scene.

Build it right to build the right thing“, Ron Jeffries. The concept is simple; build the product right, repeat until it’s the right product.

Test Driven Development

Test Driven Development is an XP agile engineering practice. eXtreme Programming (XP) is a software development methodology focused on customer value, continuous feedback, incremental feature delivery and team empowerment. It is a widely recognised fact that the earlier testing is applied in the software development lifecycle – the greater the value (shorter development timescales, more reliable code etc.). TDD takes this idea to its ultimate conclusion where testing occurs in front of actual coding. This may seem counterintuitive. In order to understand the impact of this fully it’s important to understand the high-level approach.

(1) Identify a low-level requirement (PBI, Task etc.)
(2) Describe the logical tests necessary to confirm that code satisfies the requirement
(3) Write the minimum code necessary to pass the tests
(4) Tidy-up the code to remove clutter, complexity and duplication

The steps above describe a design process where software evolves in very small increments with a focus on simplicity and testability. This step-by-step approach results in emergent design, where the code informs the design approach and guides the developer toward the best solution. This is the direct opposite of the traditional big-design-upfront (or BDUF) approach. The goals and benefits of TDD are many; “clean code that works” is a phrase that best summarises this (another golden Ron Jeffries quote). Note, TDD is often referred to as Test Driven Design in recognition of this emergent design side-effect.

TDD Cycle

It is imperative to understand the conceptual aspects of TDD in order to gain the full benefits, thankfully the practical application follows a relatively straightforward and approachable 3-stage cycle (Red-Green-Refactor).

Stage 1 – Red : Write the minimum code needed for a failing test. This may entail development of (or extension to) a test harness, plus the unit test code required to exercise the logical test case. The test code could be completely new or simply an augmentation to existing tests. In writing the test code the developer is forced to think through the requirement in detailed, logical terms – the type of thinking more typically applied at a later stage when writing the functional code.

It is imperative that test code evaluate predictable logical test conditions. The test code should fail for a specific, expected reason – not due to a test harness issue or due to the fact the test code itself is invalid.

Stage 2 – Green : Write the minimum amount of code needed to pass the test. The code written here must satisfy the test condition and nothing more – no embellishments.

Discipline is required to avoid the developers innate tendency to create.

Stage 3 – Refactor : The functional code should be reviewed and modified to remove clutter, complexity and duplication. Code should work (of course) but also (critically) be readable, updateable and testable.

Clean code is the objective here; if every tiny incremental addition of code satisfies the clean code criteria (readable, updateable and testable) the outcome will be a highly organised and easily maintainable code base that can be extended with new features at a consistent level of effort over time. Where such an approach is not applied it is often inevitable that a complete re-write becomes necessary once the steadily increasing incremental cost (time) of adding new features becomes intolerable.

The TDD cycle then repeats over and over until all requirements are addressed. The incremental design approach focuses upon each individual requirement one at a time. This minimalist, simple design lead approach can be difficult for experienced developers to adopt, however once the learning curve is addressed the focus on simpler designs allows easier modification, more efficient testing and faster production.

TDD in the Salesforce Context

The Salesforce (or Force.com) cloud platform is an ideal software development environment in which to adopt the Test Driven Development (TDD) agile engineering practice. The Apex programming language has integrated unit testing capabilities which reduce the level-of-effort required. Salesforce Developers are also accustomed to the idea that code requires a (platform enforced) test coverage level of 75% for production deployment. In the Salesforce development context therefore the tools are provided and concepts relating to unit test development well understood. The only challenge remaining is the mind-set shift from big-design-upfront and retrospective test code development to TDD and the agile benefits of emergent design, clean resilient code and reduced development effort.

Unit Testing on the Salesforce Platform

An Apex class can be easily annotated (@isTest) to indicate its role as a unit test class. The snippet below shows a very basic example.

@isTest(SeeAllData=false)
private class FeatureTestClass {
    
  @testSetup static void setup(){ 
    // populate custom settings.
    // create test data used by all tests.
  }
        
  /* **/
  static testMethod void isAccountProcessed() {
  
    // setup test specific test data and context
    insert new Account(Name='Acme Inc');
        
    Test.startTest();        
        
    // do something
    AccountProcessor.process();
                  
    Test.stopTest();
        
    // test outcome        
    System.assertEquals(1, [select count() from Account where IsProcessed__c=true]);               
  }
  /* */
}

The [SeeAllData=false] flag indicates that only test data created by the class is visible to the test method (plus some actual data; products, users etc.). There are circumstances where the flag must be set as [SeeAllData=true] flag, where test code is unable to create required test data due to object access permissions. The isTest annotation takes a second parameter [isParallel=true|false] which controls whether the test class can run in parallel with other tests (for expedient execution) or whether the behaviour requires serial execution (perhaps to avoid lock contention on shared resources such as custom settings).

Once a test class is implemented, adding individual tests becomes very straightforward. A standardised naming convention for the test cases can help the readability of the code; perhaps based on the expected outcome or the logical test case. Test code organisation at the class level should also be predictable and may follow a feature convention.

There are a number of methods available for the execution of test code on the Salesforce platform; Setup menu, Developer console and API (incl. IDE) as examples. Tests can also be executed asynchronously at a scheduled future time via Apex or the API (ApexTestQueueItem, ApexTestResult objects).

As the screenshot above shows the developer can configure a test execution to include all or selected test cases from multiple test classes. In the context of the TDD cycle the developer requires the ability to run just the one test case – not all, this would waste time.

Test Suites allow test classes to be grouped and executed together; this can be seen in screenshot below.

In the TDD context, where unit tests drive the development process it is important to have a clear naming convention defined for:

Test Case: expected outcome, or logical test case (readability is key)
Test Class: group of test cases relating to a given feature
Test Suite: group of test classes relating to a functional area

What is a Unit?

For the TDD cycle to be effective it can help to understand the level at which a unit test is applied. A unit is variably defined as the smallest testable part of an application, or the smallest change that still makes sense to be tested in the developer’s opinion. This of course is a subjective definition.

Common sense should be applied; a 200 line Apex trigger on Account will not be a single unit, a 20 field update on Contact also won’t be 20 units. Instead the feature being developed should be decomposed into a unit test per logical test case. This can take practice to get right, but striving to keep each test as simple as possible should be the primary guiding factor. Simple tests are easy to modify and provide a self-documenting benefit.

Advanced Unit Testing

The Apex language supports the advanced unit testing technique of Mocking which enables isolation of test execution from external factors such as API callouts or Salesforce configuration changes.

Mocking essentially involves the non-disruptive, dynamic substitution of a test specific class instance in the place of a functional class instance. Apex provides the HttpCalloutMock interface to allow test code to utilise pre-fabricated Http callout responses. The Stub API (StubProvider interface and Test.createStub method) supports the development of Mocking frameworks that enable any class to be substituted dynamically at runtime.

References

Apex Developer Guide > Testing Apex

Ron Jeffries Blog – All things XP and much more

Martin Fowler – All things Code Refactoring and much more

Apex Debugger

A quick video post providing a demonstration of the interactive Apex Debugger. The context of the demonstration is an ISV partner debugging a packaged code issue in a subscriber (customer) org.

Salesforce Selective Queries

A basic understanding of the selective query concept is fundamental to scalability on the Salesforce platform. Non-selective queries have a significant performance impact on List Views, Reports and SOQL and can often result in Apex Trigger runtime exceptions as below – as the data volume increases over time.

System.QueryException Cause: null Message: Non-selective query against large object type (more than 200000 rows)

SOQL queries executed from Apex Triggers have to be selective where the record count in the queried object is 200,000 or more. The determination of a selective query is a function of volume plus field-level selectivity. It is therefore the case that the selectivity state of a given query is volatile meaning in practical terms that the initiating Apex Trigger may work one day and not the next.

Selective Query Definition

Selectivity is determined by the index state of the query filter conditions and the number of records the filter returns (selectivity) versus the object total records. The thresholds below show the difference between the selectivity calculation for a standard index versus a custom index.

Selectivity Thresholds:
Standard Index – 30% (first 1M) then 15%
Custom Index – 10% (first 1M) then 5%

Unary filter:

e.g. select Name from Account where IndexedField__c=’ABC’

With a custom index on IndexedField__c the filter must return <10% of the total records in the object to be considered selective – up to the first 1 million records from that point the threshold drops to 5%.

Multiple filters AND (exclusively):

e.g. select Name from Account where IndexedField__c=’ABC’ and SecondIndexedField__c=’123′

The Query Optimiser will set the leading operation on the basis of lowest cost. If no filters are selective a table scan is performed.

If all filters have an index then a Composite Index Join optimisation can be applied.

In this case each filter must be less than 2x (two-times) the selectivity threshold.
All filters combined must be less than selectivity threshold.

If all filter fields are standard then use the standard index selectivity threshold – otherwise use custom index selectivity threshold.

Multiple filters OR (at least one):

e.g. select Name from Account where IndexedField__c=’ABC’ or SecondIndexedField__c=’123′

Selective AND filter indexes could be set as the Leading Operation – if none exist, then a table scan occurs unless all filters have an index then a Composite Index Union optimisation becomes possible.

In this case each filter must be less than selectivity threshold.
All filters combined must be less than selectivity threshold.

If all fields are standard then use the standard index selectivity threshold – otherwise use custom index selectivity threshold.

Parent Field Filter:

e.g. select Name from Contact where IndexedField__c=’ABC’ and Account.IndexedField__c=’ABC’

Where parent object fields are referenced in a filter, each filter index is individually and the lowest cost option selected as the leading operation.

Note, the parent field is not indexed on the queried object, so Account.Id can incur a table scan on Opportunity whereas AccountId may allow the standard index to become the leading operation.

The notes above provide a basic outline of the concepts but should be sufficient to convey the key concepts.

 

Implementation Approach

As data volumes grow query behaviour can change dramatically, to mitigate this database queries originating in Apex code, list view and report definitions must consider the future peak data volume and field-level data characteristics (primarily selectivity). This considered approach can help identify an appropriate indexing strategy that maintains query performance by ensuring query selectivity. So, forward planning is absolutely key; queries should be designed to be selective up to the projected peak data volumes. Thinking ahead to this extent is very seldom applied in my experience, particularly where the Salesforce implementation evolves project-by-project and the longer term picture is not a priority.

In order to evaluate the selectivity of a given query – the following 2 approaches can be applied.

REST API Query Resource Feedback Parameter

The Force.com REST API exposes a Query resource that accepts an explain parameter which can set with a SOQL query, List View Id or Report Id. The results show the options considered by the Query Optimiser and the lowest cost option (leading operation) taken. A relative cost value of less than 1 indicates a selective query, anything higher indicates non-selective. The example below shows the output for a report where a report filter hits an indexed field.

selective-queries-api

Developer Console Query Plan

From Summer ’14 on the Developer Console can be enabled [Help>Preferences>Enable Query Plan] to display a Query Plan option on the Query Editor tab. The construct of the output is the same as the API approach. Note, this appproach is limited to SOQL queries.

selective-queries-developer-console

The references section below provides link to the technical detail of the 2 approaches introduced above.

 

References

Query & Search Optimisation Cheat Sheet

Developing Selective Force.com Queries through the Query Resource Feedback Parameter Beta

Developer Console Query Editor

Improve performance with Custom indexes using Selective SOQL Queries

Custom Index Request Checklist

InvocableMethod Invocations via Process Builder

As I’ve previously stated the combination of Process Builder and Apex Actions is incredibly powerful.

This short post adds the answer to a frequently asked question; how many times is the InvocableMethod called when records are modified in bulk?

To answer this with an example. With default batch settings (200 records) and 201 modified records the InvocableMethod is called twice (2 times – 1 invocation per-batch), first call with 200 records then a second call with 1 record. Not 201 individual calls!

If the Process applies entry criteria met by only 10 of the first batch – plus the single record in the second batch – there would again be 2 calls (10, then 1). So the assertion holds true; one invocation per batch.

This bulk behaviour is why the @InvocableMethod input parameter is a list of course; however it isn’t obvious in the related documentation.

Process Builder Apex Actions

A technical best practice in the Salesforce domain is to employ Apex code predominantly as an enabler for the declarative platform capabilities. This light-touch approach is simple in concept; the minimum amount of Apex code necessary is introduced to enable non-technical build features to solution the functional requirement. In the majority case this works very well and provides a strong maintainability story. In more complex scenarios complete technical solution options can be warranted and are perfectly acceptable, but one should always preclude the Apex-as-glue approach first.

In practice this model can be challenging to implement. The solution design process must be driven by individuals who are both expert in the current-release declarative capabilities of the platform and have the skill and experience to deconstruct a requirement into a structured solution design composed of declarative and technical components. Typically functional experts revert to technical solution options as a last-resort and don’t always think in terms of blended solutions. Salesforce technical resources don’t usually have a deep understanding or practical experience of the functional capabilities of the platform – some do, most don’t consider this a development concern or don’t have the opportunity to build skills in this area.

The recent introduction of the (Lightning) Process Builder with its ability to invoke Apex Actions (via the InvocableMethod annotation) provides a powerful shared language between functional and technical perspectives, enabling a clear decomposition of functional and technical solution components. To elaborate on this, process automation solutions can be implemented (i.e. Processes) that are comprised of declarative functionality but also with delegation to Apex code where gaps exist. In other words a clear exemplar of the model described previously. Adding parameterised Apex Actions in this context enables declarative configuration of the technical component and removes the black-box issues related to Apex Trigger components etc.

The screenshot below shows an Apex Action invocation within the Process Builder design environment.

Process Builder - Apex Action

In consideration to the concept of Processes (or indeed Flows – the technology that underpins Process Builder) invoking Apex Actions, a new development paradigm becomes possible, one that avoids black box, inflexible Apex Triggers and places control and configuration in the hands of non-technical resources (business analyst, administrator, app builder etc.).

From the development perspective Apex Actions should be coded as reusable, encapsulated components with flexible configuration (via parameters) and simply dropped into Processes as required. Note, Actions are also invocable directly from the REST API – a further point of potential for this approach. This component-based architecture should work well for all parties. The question of when to write an Apex Trigger or an Apex Action will be influenced primarily by factors such as whether the logic applies to all record modifications or is selective and whether bulk operations must be supported at default batch sizes – at the time of writing there are governor limit considerations with Process Builder that should not apply to correctly written bulk-safe Apex Triggers.

Platform Cache – Salesforce Winter ’16

This video post provides a technical overview of the Platform Cache feature added in the Winter ’16 release.


Apex Unit Test Best Practice

This post provides some general best practices in regard to Apex Unit Tests. This isn’t a definitive list by any means, as such I’ll update the content over time.

Top 10 Best Practices (in no order)

1. TDD. Follow Test Driven Development practice wherever possible. There is no excuse for writing unit tests after the functional code, such an approach is indicative of a flawed development process or lax standards. It’s never a good idea to estimate or deliver functional code without unit tests – the client won’t appreciate an unexpected phase of work at the point of deployment, not to mention the pressure this approach puts on system testing.

2. Code Quality. Ensure unit tests are written to cover as many logical test cases as possible, code coverage is a welcome by-product but should always be a secondary concern. Developers who view unit tests as a necessary evil, or worse, need to be educated in the value of unit tests (code quality, regression testing, early identification of logical errors etc. etc.).

3. Test Code Structure. For some time now I’ve adopted a Test Suite, Test Helper pattern. A suite class groups tests related to a functional area. A test helper class creates test data for a primary object such as Account (i.e. AccountTestHelper.cls), secondary objects such as price book entry would be created within the product test helper class. The suite concept provides a logical and predictable structure, the helper concept emphasises that test data creation should be centralised.

4. Test Code Structure. Put bulk tests in a separate class e.g. AccountTriggerBulkTestSuite.cls (in addition to AccountTriggerTestSuite.cls). Bulk tests can take a long time to complete – this can be really frustrating when debugging test failures – particularly in production.

5. Test Code Structure. Ensure test classes contain a limited number of test methods. I tend to limit this to 10. As with point 4, this relates to test execution time, individual methods can’t be selectively executed – the smallest unit of execution is the class.

6. SeeAllData. Always use SeeAllData=true by exception and at the test method level only. Legacy test code related to pricebooks that historically required this can now be refactored to use Test.getStandardPricebookId(). Also, set the [Independent Auto-Number Sequence] flag to avoid gaps in auto number sequences through the creation of transient test data.

7. Test Case Types. As the Apex Language reference proposes, write unit tests for the following test case types.

Positive Behaviour – logical tests that ensure the code behaves as expected and provides successful positive outcomes
Negative Behaviour – logical tests for code behaviour where parameters are missing, or records do not adhere to defined criteria – does the code protect the integrity of unaffected records – does the runtime exception handling function as expected
Bulk – trigger related tests primarily – how the code behaves with a batch of 200 records – mix the batch composition to stress the code against governor limits
Restricted User – test relevant combinations of user role and profile – this test case type is prone to failure through sharing model adjustments – triggers should delegate processing to handler classes that have the “with sharing” modifier

8. Debugging. Always use the syntax below for debug statements within code (test and non-test code). An efficient practice is to add sensible outputs whilst writing the code. This approach avoids a code update or re-deployment to add debug statements during error diagnostics. Note – in such cases Checkpoints could be a better approach anyway – particularly in production. The use of the ERROR logging level enables a restrictive log filter to be applied such a clear debug log is produced and max log size truncation is avoided – note, log filters can also have a positive impact on transaction execution time.

System.debug(LoggingLevel.ERROR, 'my message');

9. Commenting. Always comment test methods verbosely to ensure the test case intent is clear and that the test code can be mapped to the related non-test code. Test classes should be fully self documenting and be viewed as the primary enabler for the future maintenance of the non-test code.

10. Maintenance. Test code is highly dependent on the environment state. Any configuration change can require test code to be updated; this could be a new mandatory custom field or a sharing model adjustment. In many cases the resultant unit test failure state is not encountered until the next deployment to production, which can’t proceed until the tests are fixed. This scenario will be familiar to many people. The mitigation requires the local administrator to understand the risk, frequently run the full set of unit tests and to manage the test code update cycle proactively.

Example Test Suite Class

/*
Name: RecordMergeTestSuite.cls
Copyright © 2014  CloudMethods
======================================================
======================================================
Purpose:
-------
Test suite covering RecordMerge operations.
Bulk tests are defined in the class RecordMergeBulkTestSuite.cls
======================================================
======================================================
History
------- 
Ver. Author        Date        Detail
1.0  Mark Cane&    2014-09-16  Initial development.
*/
@isTest(SeeAllData=false)
public with sharing class RecordMergeTestSuite {
	/*
     Test cases:	
        singleTestCase1 - postive code behaviour/expected outcome test case 1.
        negativeTestCase1 - negative outcome test case 1.
        restrictedUserTestCase1 - postive/negative code behaviour in the context of specific user role/profile combinations.
        ..
        future test cases to cover : * some coverage provided
        1. tbd.
        2. tbd.
    */
    
    /* */
	static testMethod void singleTestCase1() {
		// Test case 1 : postive outcome test case 1.
        setup();

		// Steps - 1. 
		// Logical tests - 1.
    }
    /* */    

    /* */
	static testMethod void negativeTestCase1() {
		// Negative test case 1 : negative outcome test case 1.
        setup();

		// Steps - 1.
		// Logical tests - 1. 
    }
    /* */    

    /* */
	static testMethod void restrictedUserTestCase1() {
		// Restricted user test case 1 : postive/negative code behaviour in the context of specific user role/profile combinations.		    	    			
		List<User> users;
		
		System.runAs(new User(Id = Userinfo.getUserId())){ // Avoids MIXED_DML_OPERATION error (when test executes in the Salesforce UI).
			setup();		    					
			users = UserTestHelper.createStandardUsers(2, 'Sophie', 'Grigson');
		}
		
		System.runAs(users[0]){
			accounts = AccountTestHelper.createAccounts(1, 'Abc Incorporated');
			
			// Steps - 1. 
			// Logical tests - 1.
		}		
    }
    /* */
	
	// helper methods    
    private static void setup(){
   		SettingsTestHelper.setup();    	
    }
    // end helper methods
}

Technical Naming Conventions

Challenge – outside of the ISV development model there is no concept of an application namespace that can be used to group the technical components related to a single logical application. To mitigate this issue, and to provide a means to isolate application-specific components, naming schemes such as application specific prefixes are commonplace.

Risk – without application/module/function namespaces etc. all technical components reside as an unstructured (unpackaged) collection, identified only by their metadata type and name. As such maintainability and future extensibility can be inhibited as the technical components related to multiple logical applications converge into a single unstructured code-base.

Options –
1. Application specific prefix. All components related to a specific application are prefixed with an abbreviated application identifier, e.g. Finance Management = “fm”, HR = “hr”. This option addresses the requirement for isolation, but inevitably causes issue where helper classes or classes related to common objects span multiple applications. This option has the advantage of minimising the effort required to remove functionality related to a logical application, only shared classes would need to be modified.

2. Object centric approach. In considering a Salesforce org as a single consolidated codebase where most components (technical or declarative) relate to a primary data object, a strict object-centric approach can be taken to the naming of technical components. With such a mindset, the concept of a logical application becomes less significant, instead components are grouped against the primary data object and shared across the custom functionality that may be related to the object. A strictly governed construction pattern should promote this concept with the main class types defined on a per-object basis. Functional logic not related to a single object should only every reside in a controller class, web service class or helper class. In the controller and web service cases, the class should orchestrate data transactions across multiple objects to support specific functionality. In the helper class case a function-centric approach is appropriate.

In architectural terms, an object-centric data layer is introduced that is called from a function-centric presentation layer.

presentation layer [Object][Function].page —
SalesInvoiceDiscountCalc.page
SalesInvoiceDiscountCalcController.cls

data layer [Object][Class Type].cls —
SalesInvoiceManager.cls
AccountManager.cls

business logic layer [Function][Helper|Utility]–
DiscountCalcHelper.cls

The downside of this approach is contention on central classes in the data layer when multiple developers are working in a single org, plus the effort required to remove functionality on a selective basis. In the latter case using a source code management system such as Git with a smart tagging strategy can help to mitigate the issue. Additionally, code commenting should always be used to indicate class dependencies (i.e. in the header comment) and to convey the context in which code runs, this is imperative in ensuring future maintainability.

Recommended Approach –
1. Option 2. In summary, naming conventions should not artificially enforce the concept of a logical application – the composition of which is open to change by Admins, instead an object-centric approach should be applied that promotes code re-use and discipline in respect adherence to the applied construction patterns.

Whichever approach is taken, it is highly useful to consider how the consolidated codebase will evolve as future functionality and related code is introduced. A patterns-based approach can mitigate the risk of decreasing maintainability as the codebase size increases.

Apex Trigger Exceptions

Custom Apex Triggers execute on standard CRM objects (Account, Contact, Lead etc.) and custom objects in response to all data modifications applied via the Salesforce web application, API transactions and custom Apex script. As such it is imperative that trigger code adheres to patterns that promote performance and maintainability, guards against recursive behaviour and most critically protects data integrity.

Apex code outside of triggers (Batch Apex, Visualforce Controllers etc.) is completely isolated to the specific context, trigger code is not; the effect of errant code is felt across the standard web app, mobile apps, API-based integration flows, data loads and so on. As such triggers must be used judiciously and avoided wherever possible on the core standard objects. I often come across multiple complex triggers defined on Account, where the logic applied is non-time critical and could have been handled by Batch Apex, or indeed by declarative methods. In certain circumstances this idealistic view is impractical and triggers are a necessary friend. When writing triggers always stick to a proven pattern, good examples provided by community experts are easy to find, and read the relevant sections in the Apex Language Reference if you haven’t done so for a while.

This post aims to provide some practical insight related to exception behaviour within Apex Triggers that may not be obvious from the referenced resources.

Key Concepts
1. DML Processing Mode
All bulk DML transactions on the platform run in either allOrNothing or partial processing mode. In some cases the behaviour is implicit and fixed, in other cases flags can be set to override the default behaviour.

allOrNothing
– Apex Database statements (e.g. update contactsToUpdate;)

partial processing
– Apex Database methods (Database.update(contactsToUpdate);. The default behaviour can be overridden via DmlOptions.
– API (default behaviour – can be overridden)

2. .addError()
The .addError(custom message) method can be invoked at the record or field level within the trigger context to flag a record as invalid. This is particularly useful in asserting logical errors. A best practice in regard to the custom messages is to use Custom Labels with a defined Apex Trigger Error category.

3. Runtime Exceptions
If an unhandled runtime exception is thrown then the Apex Transaction will immediately rollback and Apex exception notifications will occur. Structured exception handling can be added to the trigger code to catch runtime exceptions and to apply custom handling logic.

Apex Trigger – Exception Test Cases
The following test cases highlight the impact of the .addError() method and runtime exceptions in the context of the 2 processing modes. Tests were conducted using Execute Anonymous and the Apex Data Loader at API version 30.0.

Test Case 1 – Does code continue after .addError()?
Result: Yes (this is necessary in both allOrNothing and partial processing cases to gather a complete set of errors).

Test Case 2.1 – all_or_none – Does .addError() rollback the transaction if any subset of records has .addError() applied?
Result: Yes – Full rollback.

Test Case 2.2 – all_or_none – Does .addError() rollback the transaction if all records have .addError() applied?
Result: Yes – Full rollback.

Test Case 2.3 – all_or_none – Does an un-handled runtime exception rollback the transaction if no records have .addError() applied?
Result: Yes – Full rollback.

Test Case 2.4 – all_or_none – Does a handled runtime exception rollback the transaction if no records have .addError() applied?
Result: No – Records are committed (complete trigger context – regardless of which record caused the runtime exception).

Test Case 3.1 – partial – Does .addError() rollback the transaction if any subset of records has .addError() applied?
Result: Yes – Full rollback of all uncommitted changes, the trigger fires again for the subset of records that have not had addError() applied. Up to 2 retries are performed, after which the “Too many batch retries in the presence of Apex triggers and partial failures.” exception is thrown.

Test Case 3.2 – partial – Does .addError() rollback the transaction if all records have .addError() applied?
Result: Yes – Full rollback.

Test Case 3.3 – partial – Does an un-handled runtime exception rollback the transaction if no records have .addError() applied?
Result: Yes – Full rollback.

Test Case 3.4 – partial – Does a handled runtime exception rollback the transaction if no records have .addError() applied?
Result: No – Records are committed (complete trigger context – regardless of which record caused the runtime exception).

Test Case 4 – partial – In a partial failure case are static variables set within the original trigger invocation reset before retry invocations?
Result No – Static variables are not reset between trigger invocations. This means that statics guard variables defined to protect against recursive behaviour will stop trigger logic being applied to records processed by retry invocations.

Conclusions
1) In all cases .addError() results in the full Apex Transaction being rolled back. Custom logging schemes such as writing exceptions to a Custom Object (including via @future) or sending notification emails are futile gestures when employed in conjunction with .addError().

2) Handled runtime exceptions result in the Apex Transaction being committed, unless .addError() is applied to at least one record.

3) In the partial processing case, governor limits are reset to their original state for each retry trigger invocation, static variables are not.

4) Where static guard variables are used to protect against re-execution of the trigger logic via field updates within update DML transactions, partial processing retry trigger invocations will also be blocked. Such invocations are consistent with those initiated by workflow field updates later in the order of execution.

In order to distinguish between a field update trigger execution and a partial processing retry it becomes difficult to use static variables – batch sizes can be equivalent, sequencing is unpredictable etc.

One possible approach is to use a custom field on the target object (Is Workflow Processing?), a field update action would be added to set this to “True” alongside the existing actions. In the trigger code we can now reliably test this field state to identify a workflow field update initiated trigger execution. The trigger code must always reset the field to “False” before returning, such that any partial processing retry executions safely proceed. Where trigger logic resides in an after update trigger, a before update trigger could be added simply for convenience of reseting the field – in this case a static could be set in the before context and referenced in the after context.

It’s possible there are more efficient ways to provide a robust solution to this. A complete Apex based solution would definitely be preferable to the custom field based solution.

Visualforce Controller Class Convention

A quick post to outline an informal convention for the definition of a Visualforce controller class, key maintainability characteristics being predictable structure, readability and prominent revision history. All developers have a subjective preference in this regard, however consistency is key, particularly in the Salesforce context where multiple developers/consultancies contribute to a codebase over its lifetime. A simple, logical approach always makes sense to maximise adoption.

/*
Name:  MyPageController.cls
Copyright © 2014  Force365
======================================================
======================================================
Purpose:
-------
Controller class for the VF page - MyPage.page
======================================================
======================================================
History
------- 
Ver. Author        Date        Detail
1.0  Mark Cane&    2014-05-20  Class creation.
1.1  Mark Cane&    2014-05-21  Initial coding for page initialisation.
*/
public with sharing class MyPageController {
	//& public-scoped properties.	
	public List<MyWrapperClass> wrapperClassInstances { get; set; }
	//& End public-scoped properties.
   				
	//& private-scoped variables.
	private Boolean isInitialised=false;
	//& End private-scoped variables.
	
	//& page initialisation code.
	public MyPageController(){
		initialise();
	}
	
	private void initialise(){ isInitialised=true; }
	//& End page initialisation code.
	
	//& page actions.
	public PageReference saveAction(){
		return null;
	}
	//& End page actions.
	
	//& data access helpers (class methods accessed from binding expressions).
	//& End data access helpers.
	
	//& controller code Helpers (class methods providing helper functions to data access helpers or actions).
	//& End controller code helpers.
	
	//& inner classes (wrapper classes typically, extending SObjects for convenience in the UI).
	public class MyWrapperClass {
		public MyWrapperClass(){}
	}
	//& End inner classes.
}