Continuing my previous thoughts on the proper usage of before and after triggers, I'll share with you a problem that may arise if you choose to architect your trigger in an unorganized way.
For those of you that want the TL;DR version, skip the next 3 or 4 paragraphs of background info.
We have tree-like relationships between some of our data for an internal project management Force.com app that look like this (I haven't used UMLs in awhile, so don't read it thinking it's UML):
(Now, I realize that the pro SFers who are reading this may see that I am missing some killer functionality that Salesforce offers, but please don't share your suggestions to improve this data model, because I am leaving out the details for the sake of simplifying the explanation.)
When a time entry is inserted or updated, it tells its task to update itself because it has fields that summarize how much time has been entered on it. When a task updates, it will sum its child time entries and update some of its field values. Because the project also keeps track of the time entered on its tasks, the task forces its project to update itself.
When a time entry, task, or project moved, I was seeing a "Too many SOQL queries: 101" error because of all the recalculation that had to take place. This was a common error that I knew how to solve, but solving it, I discovered, required re-structuring and organizing the triggers on time entry and task.
Like most other developers, I slowly added features to this app as they were requested, placing each new feature in its own trigger. After seeing that I had 7 triggers on task, 4 triggers on time entry, and 4 triggers on project, I decided that it was time to get these under control by using a Master Trigger pattern, arriving at a variation of the pattern described by this blogger.
After moving the trigger logic into methods of a static helper class called by a single master trigger, I discovered that I was updating the parent task twice! Once in a before trigger and once in an after trigger! It took some more refactoring, but I was able to remove the update call from the before trigger and fix the problem.
Learn from my mistakes! Separate the duties of the before and after trigger! The before trigger is used to make the record fix itself, the after trigger for fixing others records.
Having learned my lesson, I have since always used the master trigger pattern to organize my code, and always consult Mr. Before and Uncle After when deciding where to put logic in a trigger.
No comments:
Post a Comment