1

I have some additional business logic I need to put into my QuoteLineItem object, but we have come to a situation where current logic is too spread across triggers and workflow rules + field updates in QuoteLineItem+Quote, which ends up by firing multiple times each set of triggers (Quote, then QuoteLineItem, then Quote again, then some "after updates" that affect other related objects, with field updates going on in different objects...). I already have static variables for control of recursive loops and everything is bulkified, but when I tried to add this extra business logic, I reached SOQL limits.

So, I'm assuming the whole system is not well designed and needs some major refactoring. I never had a formal training with Salesforce development, and this system I'm working with was already partially implemented when I assumed it, so I have a few questions for you guys:

  • Is my conclusion valid? (I need a major refactoring in my scenario, or is this mix up of mechanisms normal for complex rules)
  • If the answer is YES, is there any documentation to help on big refactorings on a live system?
  • And what should be a good approach to this scenario (complex pricing rules, other objects depending on updates on items and quotes)? I mean in terms of using triggers VS field updates or a mix of both.
3

You should start by consolidating your triggers so that you only have one trigger per an object and use a handler class to execute the trigger logic. That way you control the order that your trigger logic is executed, unlike the uncertainty of how Salesforce executes triggers. You can also then bulkify your SOQL queries and DML statements across different business logic processes by mapping out related Ids and making queries that apply to several processes.

You need to program very defensively when building triggers because you have to co-exist with managed packages and perhaps other developers on a limited platform, and implementing a trigger framework will allow you to make your logic as lean as possible. If you use 50% of the limits, and the other code in your org uses another 50%, you'll hit the limits when they're executed together even though neither of you was worse than 50% efficient. So aim for 10% or less.

I recommend "Advanced Apex Programming" by Dan Appleman if you are looking for some good patterns for making your code more efficient and ideas for how to intelligently handle conflicts.

  • Hi Aaron, thanks for the tips. I 'm already using that pattern (one trigger per object + trigger handler class). I also have all (or at least most of it) DML and SOQL bulkified. I do use external packages which do their own bunch of SOQL queries as well, which adds more complexity to my scenario as you mentioned. But I will review my triggers once again to see if all of them have some checks before doing unnecessary queries. If I still have some specific problem after that, I'll add it here. Thanks for the book tip as well. – Mauricio Oliveira Jun 20 '17 at 17:50
  • Check for redundant queries. Are you querying the Opportunity, Contact, or Account table more than once? Could you use relationships to eliminate queries by grabbing Opportunity.Account.Name instead of a separate Account query? I just mean those as general examples that may or may not apply to you. You can loop through separate data sets and store Ids in a set or map and then use those collections to query a single time. Use the dev console with debug logs and profiling information to figure exactly how many queries you are using. Figure out where you're wasting resources. – Aaron P. Jun 20 '17 at 18:44
  • You should be able to make your code lean enough to stay well under the limits even if your business logic is complex. Also check managed packages, if one is using a disproportionate amount of resources, contact their support or consider replacing the package. Also check out headless flows and Process Builder processes, as those will contribute to limits if they're triggered by record updates. Make sure your trigger flow control is tight so you're not wasting cycles on after update cascades. – Aaron P. Jun 20 '17 at 18:46
  • Thanks for the additional tips. I have already changed a few queries to relationship queries, but there may be more cases I could apply that. I have already started analyzing each of my logic rules in trigger to see what I can improve with all those suggestions. I was trying to move one field update to trigger and got into a recursion of after updates as you said, but I rolled back and can't remember exactly why/where I got stuck. I remember trying process builder and had some limitation too. But I will first do this whole review and refactor of each trigger method to see if things get clearer – Mauricio Oliveira Jun 20 '17 at 18:57
  • Hi @Aaron, can you help me with a conceptual/design question? I had this after update trigger in Quote that was updating a field in the Opportunity (so I need to query it). Trying to remove that trigger/query, I changed this logic to roll-up summary field and WFR + Field Update in the Opportunity. But this ended up hitting my SOQL query limit, since now updates in the Opportunity will fire its triggers (mine and external packages'). So, by removing 1 query I ended up with more queries. My question is: am I in the right path, or is there something wrong with my approach? – Mauricio Oliveira Jun 21 '17 at 15:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.