Am working on a project in an org where I have to work with Dave Scott's Tidy, Streamlined, Bulkified Trigger Pattern also known as the Trigger Factory pattern which can be found in the Salesforce Cookbook. There are nuances to it that can make it difficult to work with for some use cases.
For example, one can't perform queries from within the Object Handler Class. That makes it difficult to use when one needs to query related records as they must be done in another helper class. Making those callouts appears to be something of a challenge as well. The "bulk before" and "bulk after" methods are iterators. As such, they're controlled by the for loop iterators in the Execute method of the Trigger Factory base class as per the code example below:
private static void execute(ITrigger handler)
{
// Before Trigger
if (Trigger.isBefore)
{
// Call the bulk before to handle any caching of data and enable bulkification
handler.bulkBefore();
// "before" code section omitted
}
else
{
// Call the bulk after to handle any caching of data and enable bulkification
handler.bulkAfter();
// Iterate through the records deleted passing them to the handler.
if (Trigger.isDelete)
{
for (SObject so : Trigger.old)
{
handler.afterDelete(so);
}
}
// Iterate through the records inserted passing them to the handler.
else if (Trigger.isInsert)
{
for (SObject so : Trigger.new)
{
handler.afterInsert(so);
}
}
// Iterate through the records updated passing them to the handler.
else if (Trigger.isUpdate)
{
for (SObject so : Trigger.old)
{
handler.afterUpdate(so, Trigger.newMap.get(so.Id));
}
}
}
// Perform any post processing
handler.andFinally();
}
What the above means is that when you get to the point of writing code for the actual trigger handler, in an After Trigger, it begins to look something like this:
// note: public variables defined earlier
public void afterInsert(SObject so)
{
User u = (User)So;
if(u.ProfileId == ProfileId && u.isActive == true){
CommUsrId2CtcId3.put(u.Id,u.contactId);
// can't make a callout here from a list
// not certain if I can make a callout here at all on a per record basis
// appears I need to wait until the finally method to do DML or callouts
// can't set flag on custom field in user object for tracking
// can't set a boolean flag to prevent re-entry to this part here since
// it would be in an iterative loop & repeat up to 200 times
}
}
public void afterUpdate(SObject oldSo, SObject newSo)
{
}
public void andFinally()
{
if(Trigger.IsAfter && Trigger.IsInsert){
ApexSharing_UserHandler(CommUsrId2CtcId3, true);
// could do DML to custom object which causes @future trigger to fire
// could do DML on User object to set flag on custom field for tracking
// could set a boolean flag to prevent re-entry
// appears I can use a for loop here, but not certain of that
}
}
I'm trying to refactor code to work with this pattern and am feeling hamstrung by it, but the client insists that it be used. I can respect that, but need to be able to call other handlers to do the work and need to figure out where and how to call them in an efficient manner. Have I drawn the correct conclusions in my commented code about what I can and cannot do using this pattern? Are there other limitations I need to be aware of?
andFinally
. You collect related -to- the-trigger-set objects in thebulkBefore
orbulkAfter
handlers and then in the before/after insert/update handlers, you build up maps of interesting things to do when you hit theandFinally
. It is just a different way of thinkingandFinally
method?