Scalability and APEX go hand-in-hand when developing anything on the Salesforce platform. The key points to maintain a scalable code base include simple architecture, efficient naming, and intelligent commenting. This page is dedicated to showing admins how to achieve all these key points while building out an org. 

architecture foundation

Everything about a trigger is built around the initial foundation of your trigger. When building out a trigger for an object, maintaining a centralized code base is important. By "centralized code base", I mean creating only 1 trigger per object and building out methods to carryout specific trigger functions. Creating a new trigger per action will cause unnecessary complexity and inefficiency in the system.

In your master trigger class there are several features that are required to increase efficiency, allow for quick modification, and provide bulkification. The first involves querying records from a Custom Metadata Type object that hold information about all the action methods that exist on the trigger. (Read more about what these records store here). The next feature is a collection of all the action classes with a brief commented description on what the action does. This collection and commenting will allow non-developers to quickly dive into the trigger and figure out what actions are being taken. The following action performed on the trigger is a for loop to loop through all the values. The methods called inside of this loop perform validations to confirm a records is eligible for an update or direct updates (if the action is a before trigger). These methods are pre-pended with check or checkrun (if the action is a before trigger). After the 1st loop is complete a section to run all query methods in the after methods is run. After that section you have the 2nd for loop to loop through all the before run methods. Finally call the DML Object SortAndUpsert method. 

Here is a temple of the structure.

classes & methods

The second critical piece to successfully building out the one-trigger-per-object method is to properly build out descriptive and efficient classes and methods. Developers should create one class per trigger action. However, there are some instances when one class should contain multiple trigger actions. All actions that relate to validation rules, chatters, and/or emails should be collected into one method. I have determined the methods that should be grouped together are validation ruleschattersemails, and formulas (replacing formula fields with APEX). This strategy enables non-developers easier visibility into what those types of methods and future code modification be more streamlined since all related work is collected together.  

Naming convention is hugely important as it is the initial entry for anyone reading the codebase and will allow for more streamlined searching and documentation. All classes should be properly labeled with the name of the object which they are associated with and a brief description of what the class does.

Here are some examples of trigger class names : 

// Stamps Health Score on the opportunity
Opportunity_HealthScore healthScore_Mthds = new Opportunity_HealthScore();
// Convert Insight Contacts into Salesforce Contacts
Account_ConvertInsightContact convertInsightContacts_Mthds = new Account_ConvertInsightContact();
// Chatter messaging for opportunity (holds all chatter related methods)
Opportunity_Chatter chatter_Mthds = new Opportunity_Chatter();


Methods : 

The methods within the class all have unique purposes. I have created four different types of methods, a Check, QueryRun, and CheckRun. Together these method types validate, query and modify Salesforce data. Check methods are used to validate a record is approved for update or insert. Query methods query any necessary data for the data modification action, which occurs in the Run method. These methods are where DML queries occur, however the Run method can also have a DML query if the method is an after trigger type. CheckRun methods are solely used for before triggers and hold all data modifications in one method.

Here are some templates on trigger classes & methods.

naming conventions overview

Triggers : 

Object Name + "MasterTrigger  "

AccountMasterTrigger, OpportunityMasterTrigger

Classes : 

Object Name + short description

Opportunity_T1000Renewals, Opportunity_RenewalContRoles, Opportunity_PopulatedQualifiedBy

Test Classes :

Class Name + "_TC"  >>  (the "_TC" allows for quick filtering/searching in the APEX class view)

Opportunity_T1000Renewals_TC, Opportunity_RenewalContRoles_TC

Methods : 

Method type + class name + method description (if applicable)

CheckRun_Chatter_ForecastRenewalCategory, Check_ParentAccountSegment, Query_ParentAccountSegment, Run_ParentAccountSegment



Commenting in triggers and trigger classes, as with other APEX components, is incredibly important. Documentation and code read-ability are two major reasons why strong commenting is critical to the development process. Commenting in the trigger consists mainly of making sure to include a brief description of what the class does and small comments around methods when necessary. 

Commenting in the classes and methods are also very important. Single line comments before for loops or if/else statements are very helpful tricks. A description for each class is highly recommended. The following format provides quality, quick information : 

/*  ===============================
    Created By: 
    Created Date: 
public void Check_() {}

additional components

The last part of the trigger architecture is the use of Custom Metadata Types. These metadata records are incredibly power for several reasons. First, querying them does not count towards the query limit for triggers. Second, they are deployable via change sets (a huge advantage over Custom Settings). And third, they offer much more flexibility when building out the object and associated fields. 

At the top of the trigger template above, there is a section to query all the trigger settings associated to the trigger. The query gets the current status of the trigger action and the overall trigger and allows non-admins to quickly turn off and on any specific trigger they would like.