Salesforce Topics

One of the more interesting (but low-key) functional enhancements to arrive on the Salesforce platform over recent releases is Topics.

All Topics Page

A Topic can be viewed as a consolidation of the collective enterprise intelligence around a specific term or theme, across both the collaboration dialogue and the business processes managed within Salesforce. In practical terms this translates to Chatter posts and Object records being assigned one or more new or existing Topics. All assigned records and posts then display on the Topic page – providing the consolidated view of everything happening across the enterprise that pertains to the Topic. This is incredibly powerful in terms of both data categorisation and the insight possible from considering the holistic view of a contextual theme or initiative.

Topic Page - Feed tab

The Topic functionality doesn’t end there; from a Topic page (see screenshot above) it is possible to endorse users as experts on the Topic thereby harnessing knowledge within the enterprise and providing an effective means of channeling communication such as a questions, suggestions and so on. Note, users can elect to remove themselves from the Knowledgeable People list.

Topics can be followed (if feed tracking enabled for Topics) and favourited which enables interested users to be updated proactively. Discussion of Topics is tracked at the Group and User level, the Chatter tab also shows the Trending Topics area which highlights recent activity, this excludes Topic used solely in private Groups or record feeds.

Note, as a point of clarification Topics differ from Groups in that they collect posts from across Chatter and also records.

Primary Use Cases

1. Topics provide a good solution option for any data categorisation or notification requirement relating to enterprise-wide initiatives or themes.
2. Topics map well to Organisational concepts such as departments, virtual teams, projects etc.
3. Topics could provide a useful (albeit elective) notifications model where the Topic feed is used to push notifications to users interested in new transactional records related to the Topic theme, which could represent a reference data type such as a region, product or channel.

Key Considerations

Topics for Object. Once enabled for an object, records can suggest Topics based on the values in selected fields. Whilst a Topic has a feed, record assignment does not generate a post. To mitigate this, Topic assignment can occur via #hastag in a post to the record feed. Additionally, feed activity related to a record is not viewable on assigned Topic pages. The concept relates to grouping and categorisation of records, not consolidation of feed items.

Global Search enabled. Topics appear as a distinct Object within the Record search results.

List Views. Topics can be referenced in List View filter criteria.

Reports. With Winter ’15 the reporting options are limited to those below (to my understanding) via CRT. Reporting on record level assignment isn’t there as yet.
–Topic – list of topics with # talking about statistic
–Topic Assignment – count of assignment per record type (key prefix)

Knowledge Articles. Topics can be added to Knowledge articles enabling end-user categorisation of published articles in addition to pre-defined data categories.

Customisation. Apex triggers can be defined on the Topic and TopicAssignment (assignment of a topic to a FeedItem or a record) objects, which are also API accessible.

Permissions. Profile permissions (or permission set) control who can create, edit, delete and assign topics. Defined topics are public regardless of whether they are solely used in private groups or on records.

Topics for Objects – Screenshots

1. Add a Topic to a Record

Add Topic to Record

2. Topics Assigned to a Record

Record with Topics

3. Topic Page – Records Tab

Topic Page - Records Tab

Salesforce Environment Hub

Environment Hub was announced back in August 2012 and was initially made available as a Pilot feature of the Winter ’13 release. This post follows up (some 2 years later) on my initial interest in understanding the utility Environment Hub delivers in the context of environment/user management.

Environment Hub – What is it?
In simple terms Environment Hub is an org administration tool that enables multiple orgs (of any type) to be associated and accessed from a central location. Each connected org is a termed a Hub Member, with an imposed constraint that each Hub Member org can only be parented by one Hub org. It is therefore imperative that Hub Members are only added where there is no contention over the appropriateness of the parent Hub. Commonality of target production org or packaging org is a good starting point for this consideration, as is the rule that client orgs should never be parented by an ISV or Consultancy Hub org. The parent Hub org should always be the most-accessed org, the credentials for which will become those by which all org access is made.

For larger programmes of work Environment Hub provides a highly useful means to catalogue the org estate and to provide SSO between the constituent orgs. This latter point enables reduced password maintenance, simplified access and centralised user administration in terms of deactivating a user account in one place only and ability to view login history in once place.

Environment Hub Tab

Environment Hub is enabled by Salesforce support who will require confirmation to proceed with the change. From experience, the enablement process can take a few days.

Key Features

Connect Organisation
Connecting Hub Members to the Environment Hub occurs via the entry of an administrator username for the target org and subsequent OAuth authentication and authorisation flow. The User Permission “Connect Organisation to Environment Hub” is required.

Connect Organisation 1

Connect Organisation 2

Connect Organisation 3 - OAuth

Connected Organisation Detail Page

Once an org is connected to the Environment Hub interesting detail such as the Edition, Org Status and Org Expiry date is revealed. It is also possible to add custom name and description attributes to the Hub Member, which I really like, each org in the estate should be justifiable and have a specific purpose – here we can capture this plus accountable contact etc. A very useful means of cataloguing and tracking the org estate.

The Company Detail page in the connected org will now show the Environment Hub Org Id value as below.

Company Information Page

In addition to the “User Added” origin, Hub Members are also auto-discovered using existing org-to-org relationships as below.

Auto-discovery types; sandbox to production, patch orgs to release org, trialforce source org to trialforce management org, release org to LMO

Create Organisation
New development/test/demo orgs can be created directly within the Environment Hub – this replaces the functionality previously exposed via the Salesforce Partner Portal, for partners at least. I’m unclear how the types of org offered are affected by partnership status etc. or perhaps whether the Environment Hub itself is available only to partners.

Create Organisation

Create Organisation 2

Org types offered;
Development = PDE org.
Test/Demo = Pick Edition for a 30 day time expired org.

Useful information of the distinction between different org types can be found here.

Single Sign-on
SSO can be enabled between each Hub Member and the Hub org; in implementation terms this means the Hub org is configured as an Identity Provider with a Service Provider being configured (automatically via the SSO enablement process) in both the Hub Member org and the Hub org. Both IdP initiated (via the Environment Hub tab) and SPI-initiated (via enablement of the Service Provider as a Login Page Authentication Service) SAML flows are supported. The latter point meaning SSO could be enforced as the only authentication means – thereby switching off standard Salesforce authentication entirely. Each Hub Member Org must have a My Domain configured for SSO to function.

Note, enabling SSO creates a Service Provider in the Hub org, default permissions are provided to the Standard User and System Administrator profiles only. It is therefore a requirement to ensure relevant permissions (Profile or Permission Set) are provided.

Connected Organisation Detail Page SSO

Within the Identity Provider, the Hub Member specific Service Provider configuration is set with “Subject Type=User’s ID determined by Environment Hub”, this setting delegates the user mapping to the Environment Hub settings, defined as below.

3 types of SSO User Mapping;
Method 1. Mapped Users – 1 to 1 mapping of user names – per-user.
Method 2. Federation Id – boolean state, yes = attempt to map users on common Federation Identifier values.
Method 3. User Name Formula – formula expression = attempt to map users via formula result.

Where multiple mapping types are enabled the precedence order above applies. For SSO between a sandbox and production org, user mapping is implicit and not configured as above.

Customisation
Enabling Environment Hub adds the EnvironmentHubMember standard object which is open to the declarative build model; custom fields, page layouts. validation rules, workflow rules, approvals etc.. In addition Apex Triggers can be defined on this object, use cases for which may include notifications relating to status changes etc.

A second standard object EnvironmentHubInvitation is also added, however this object is inaccessible from the Setup menu (although it can be reached via /p/setup/layout/LayoutFieldList?type=EnvironmentHubInvitation&setupid=EnvironmentHubInvitationFields). I’m assuming this object to be either forward looking or a legacy of an invitation-based connection model (as per Salesforce to Salesforce). Regardless, records do seem to be added to this object, the logic for which is unclear.

Related Permissions
Hub Org –
Manage Environment Hub
Environment Hub App and Tab access
EnvironmentHubMember standard object access permissions
Environment Hub Connected App
SSO Service Providers e.g. [00_____0000Cj__] Service Provider Access for SSO (by Profile or Permission Set)

Hub Member Org –
Connect Organisation to Environment Hub

Environment Hub in Practice
For consulting projects Environment Hub offers significant value in terms of management and tracking of the org-estate and centralisation of user administration. In practice this would require all project contributors to access production (Hub) as the primary org and SSO into secondary (Hub Member) orgs as required. In this model, production could be utilised for project collaboration, bug-tracking, project management etc. which is a common approach. The obvious downside being the requirement to license the project team in production – a big challenge on many projects where user licenses aren’t provisioned until a late stage or business use runs parallel to project activity. In such examples, project contributors could be provisioned with low-end user licenses on a temporary basis. Ideally we could do this with a Chatter Plus license as users would only require Chatter, Custom Objects (10 or less) and Environment Hub access.

For ISV projects, the utility of Environment Hub relates more specifically to the ability to catalogue the multitude of environments required for development, test, i11n, packing, release and patch purposes, not to mention TrialForce. Efficiency of access across this estate is also a key factor.

References
Environment Hub Online Help

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
}

Salesforce Release Methodology – Change Control

This post presents a basic model for the control of change within a Salesforce development process. Best practice suggests that all non-trivial projects should implement some degree of governance around environment change, i.e. Change Control. This is perhaps obvious, what isn’t necessarily obvious is how to achieve effective change control without introducing friction to the develop->test->release cycle.

In simplistic terms a change control process should ensure that all changes are applied in a controlled and coordinated manner. The term controlled in this context relates to audit-ability, acceptance and approval. The term coordinated relates to communication, transparency and orchestration of resources. The foundation upon which such control and coordination is achieved is accurate recording of changes and their application to specific environments, the object model below shows one approach to this.

Note, where feasible I recommend using the production org for this purpose, which may be challenging from a licensing perspective, however this approach has many advantages over off-platform alternatives such as Excel spreadsheets for tracking change. Chatter provides excellent support for collaboration on deployments.

Change Control Object Model

Key Principles
1. For most projects tracking change at the component level (Custom Field, layout adjustment etc.) is time expensive and impractical in terms of associated overhead.

2. The model does not require change to be recorded at the component level. Instead change summaries are recorded and the flow of change between environments tracked. The exception to this is Manual Change, where the component type is not supported by the API or Change Set approach, in such cases Manual Changes are recorded individually.

3. Sandbox to sandbox deployments should be recorded (as the internal deployment type) and tracked.

4. A Deployment will be comprised of Manual Changes organised into Pre and Post Actions, plus a set of grouped Automated Changes. Manual changes may be configuration or data in type.

5. A periodic audit should be conducted to compare the Change Control Log for an Environment against the Setup Audit Log within the org.

6. A production deployment should always be preceded by a full deployment verification test (DVT) that replicates exactly the conditions of deployment to the production org.

7. A Deployment that targets the Production org should always require approval. A standard Approval Process should be introduced, with Chatter Post approval where appropriate.

References
Components supported by Change Set
Metadata API Unsupported Component Types

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.

Salesforce Application Types

In a typical development process requirements are captured and the information synthesised to form a solution design. The constituent components of the solution design are ultimately translated into physical concepts such as a class, page or sub-page view. This analysis, design, build cycle could be iterative in nature or fixed and may have different degrees of detail emerging at different points, however the applied principle is consistent. In considering the design element of the cycle, interaction design techniques suggest a patterns-based approach where features are mapped to a limited set of well-defined and robust user interface patterns, complemented by policies for concepts that transcend the patterns such as error handling, validation messages, stylistic aspects (fonts, dimensionality etc.). This process delivers efficiency in terms of reusability of code and reduced technical design and testing, but also critically provides a predictable, consistent end-user experience. When building custom applications using the declarative tools, we gain all of these advantages using pre-defined patterns and pre-fabricated building blocks. When building using the programmatic aspects of the platform a similar approach should be taken, meaning follow established patterns and use as much of the pre-fabricated components as possible. I can never fathom the driver to invent bespoke formats for pages that display within the standard UI, the end result is jarring for the end-user and expensive to build and maintain. In addition to delivering a consistent, predicative end-user experience at the component level, the containing application itself should be meaningful and appropriate in type. This point is becoming increasingly more significant as the range of application types grows release-on-release and the expanding platform capabilities introduce relevance to user populations outside of the front-office. The list below covers the application types possible at the time of writing (Spring ’14).

Standard Browser App
Standard Browser App (Custom UI)
Console (Sales, Service, Custom)
Subtab App
Community (Internal, External, Standard or Custom UI)
Salesforce1 Mobile
Custom Mobile App (Native, Hybrid, browser-based)
Site.com Site
Force.com Site

An important skill for Salesforce implementation practitioners is the accurate mapping of required end user interactions to application types within an appropriate license model. This is definitely an area where upfront thinking and a documented set of design principles is necessary to deliver consistency.

By way of illustration, the following exemplar design principles strive to deliver consistency across end user interactions.

1. Where the interaction is simple, confined to a single User, the data relates to the User and is primarily modifiable by the User only and has no direct business relevance then a Subtab App (Self) is appropriate. Examples: “My Support Tickets”, “Work.com – Recognition”.
2. Where a grouping of interactions form a usage profile that requires streamlined, efficient navigation of discrete, immersive, process centric tasks then a Console app is appropriate. Examples: “IT Helpdesk”, “Account Management”
3. Where a grouping of interactions from a usage profile that is non-immersive, non-complex (i.e. aligned with the pattern of record selection and view/edit) and likely to be conducted on constrained devices then Salesforce1 Mobile is appropriate. Examples: “Field Sales”, “Executive Insight”.

Design principles should also provide a strong definition for each application type covering all common design aspects to ensure consistency. For example, all Subtab apps should be built the same way technically, to the same set of standards, and deliver absolute consistency in the end user experiences provided.

Salesforce Release Methodology – Simple Case

A very common challenge addressed by architects working with Salesforce is the definition of an appropriate release methodology. By this I mean the identification of the Salesforce orgs required to support the project delivery whether serial or concurrent in nature, the role and purpose of each org and critically, the means by which change is managed and synchronised across environments. With this latter point, a clear definition of the path-to-production is imperative.

In the large-scale, complex project case there is typically time and expertise available to define a bespoke methodology, with build automation, source code control system integration and so forth tailored to the specifics of the programme environment. There’s an abundance of best-practice information available online to help guide the definition of a release methodology for complex projects. For less complex projects, such as those employing the declarative build model only, there is less information available, in such cases what is typically required is a standardised, best-practice approach that can be adopted as-is.

The remainder of this post provides an outline view of an exemplar release methodology for small-to-medium scale, configuration-centric projects (i.e. no Apex code or technical complexities). This information is provided for reference purposes only.

Environment Strategy
The following diagram outlines the environments and their purpose, the defined release steps and a basic approach to change management.

Release Methodology - Simple Case

Key Principles
1. Isolate development from testing activities. This is the golden rule. Testing requires a stable environment unaffected by ongoing development. Development shouldn’t grind to a halt while system testing and acceptance testing processes are applied.
2. Utilise the minimum number of sandboxes as possible. Synchronisation of change is time expensive and error prone, avoid this wherever possible. Preparation of standing data post sandbox refresh can also take time, as can the communication required to establish that a refresh can proceed.
3. Don’t over specify the sandbox type. Sandboxes are an expensive asset, especially full-copy and partial-data sandboxes. Calculate the required storage capacity and map to either Developer or Developer Pro. Retain full-copy sandboxes for purposes that do actually require the copied data.
4. Maintain a Change Control Log in the production org to record all changes (at a reasonably high-level) against applied environments.
5. Use the production org for implementation project collaboration. It can also be a useful adoption tool to create Chatter groups such as “Salesforce: Marketing”, “Salesforce: Finance” where collaboration can occur directly with the business users whilst the project is in flight.
6. Accept that change will inevitably be applied to the production org first; record such changes and apply to development and testing sandboxes asap.
7. Always verify the Change Control Log against the Setup Audit Trail before deployments.
8. Use Change Sets for deployment wherever possible.
9. Encourage a development process where Change Sets are updated continually, rather than retrospectively.
10. Always verify the Change Control Log against the list of Change Set support components.
11. On larger projects a Change Set partitioning strategy may be required; along functional lines, by team or by component type etc.
12. Ensure releases to production are documented and approved. A simple Deployment Request Form (DRF) template should be defined and used to gain approval. This process is key to communication and governance but also helps the team consider fully the pre- and post- deployment steps, risks and rollback strategy.
13. Post-release. Communicate how business processes have been mapped to Salesforce concepts, and the permissions model. Understanding how things work in simple terms can help avoid end-user frustration with a new system. This can also reduce the support burden as end-users can often self diagnose the cause of a problem.

The org strategy diagram above presents an appropriate approach for a serial-release model, i.e. one project or one sprint at a time is being developed, tested then released. In the concurrent-release model, where multiple parallel projects are converging into a single production org, isolated develop and test sandboxes will be duplicated per project with an integration (or pre-production) org providing a synchronisation point where the combined state is validated prior to deployment to production.

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.
}

Salesforce Implementation Audit

This post provides an outline approach to consider when performing an internal audit of an existing (or emerging) Salesforce implementation. As an individual who specialises in the provision of such quality assurance services from an external perspective, I’m convinced that most projects would benefit from a periodic internal review, perhaps augmented by some occasional external perspective and insight (Salesforce services can help here). However this is approached, in the majority case the internal project team will have the requisite experience and competency to deliver such an introspective review, the challenge is often one of finding the right time, or indeed any time, to conduct it. This is why a retrospective build review should be planned every 3 or 4 sprints (or thereabouts – projects differ) with a full implementation audit scheduled every release. The principal being that whilst the build is in flight, periodic sense checks are made on key quality aspects, technical integrity, platform limits etc. with a comprehensive audit applied pre-release (ideally). The latter may need to consider a combined future deployment state where multiple parallel development streams converge into a single production org.

Note, an implementation audit is build-focused (or solution oriented) and should not assess the fit-for-purpose nature of the functionality in respect to business requirements (i.e. the problem-to-solution mapping). The only exception to this arises where an obvious mapping to a standard feature is missed resulting in a “gap” that is unnecessarily filled by a technical solution option.

Note, in order to cut down on the time required to conduct the audit access to individuals who can describe the functional intent is imperative. In the internal case the programme/project architect should be leading the audit and should be aware of the functional design context.

Note, before diving into the detail of the implementation, it can be highly valuable to re-define the high-level solution architecture (HLSA) in current state terms. The key point being that the macro-level view is often distorted by micro-level design decisions made during the project course. A periodic check is useful to ensure that this organic change is understood and that the integrity of the original architectural vision is maintained.

Indicative review areas are listed below (this is not exhaustive)

Declarative build environment
1. Identify platform limits that are reaching a high percentage of utilisation that may present risk to scalability and future phases of development.
2. Identify any future maintainability risk presented by the conventions applied in the definition of configuration elements (e.g. naming conventions, opportunities for best practice improvements.).
3. Identify functional areas where a mapping to standard features could be achieved.
4. Identify security vulnerabilities (org-access, sharing model etc.).

Technical customisations
1. Identify risks to data integrity and application responsiveness.
2. Document risks to scalability and extensibility imposed by platform execution limits.
3. Document deviations from best practice technical patterns, conventions and coding standards.
4. Identify security vulnerabilities introduced by technical componentry.
5. Document deviations from best practice development practices and process.

Integration architecture
1. Identify risk associated with deviations from best practice integration patterns and practices.
2. Identify opportunities to reduce limits consumption.
3. Identify data integrity and scalability vulnerabilities related to the current state integration architecture.

Identity management
1. Identify risk associated with implemented single sign-on processes and related services/infrastructure.
2. Document deviations from best practices related to identity management.