11 thoughts on “Apex Design Patterns – Leveraging the flexibility of custom metadata types”

  1. Hi Jonatas,
    Thanks for a very useful and interesting solution to the flexibility requirements.
    I have one question here though, most solutions in real life have conflicting constraints (well that is true about life itself, but that is for another day :-)), so how do we compare this solution in terms of performance requirements vs the earlier case.
    In my pursuit of such solutions, I have often had to balance flexibility with how often that is really needed and keep on the lookout for alternatives by weighing them from business value. Of course, there is no perfect solution here. I would however, greatly appreciate your thoughts on a real life case where this level of flexibility was weighed over performance.
    Thanks so much for your time.

    • Hi Chandra,

      Thanks for taking the time to go through the post and contribute with a comment, I really appreciate it. In terms of performance, I haven’t had a chance to compare both solutions through the use of the Apex benchmark methods (e.g. Limits.getgetCpuTime(), Limits.getQueries(), etc.). However, it’s clear that the second approach that uses custom metadata types is using more resources since it leverages the creation of a custom metadata type itself (Salesforce also has a limit related to that), the SOQL queries related to the retrieval of those records, and all the abstractions that need to be processed in order to execute the code logic.

      For your second point, I totally agree that this should not be the first approach to be taken in every case. I really believe that we should keep our solutions and implementations as simple as possible most of the time. However, if you have been working on a project that has demonstrated to have last-minute business changes on a certain frequency, I would definitely recommend the second approach instead.

      A simple heuristic that I like to use for myself is something that I like to call the “1, 2, N” approach. The idea is that we would do the straightforward solution for the first time, for the second time, and if a new case appears then it’s already a good signal that an abstraction is needed.

      I hope that those thoughts could help clarify the points that you have mentioned. Thanks again for your contribution!

  2. Is it possible to do the same using more declarative methods like Flow Designer? That way an Advanced Admin could do the lot. Also, how do we set up the testing of everything you’ve shown?

    • Hi Frederick,

      Thanks for your comment! I believe you can do something similar for declarative solutions by leveraging custom settings. You can find an example of this approach here.

      For your second point, I’ll be providing the full code for this framework soon, including test classes, stay tuned!

  3. Hi Jonatas,

    like the first reply to this article: Interesting approach to be as flexible as possible. Unfortunately there is no solution described related to the capabilities of apex tests for this highly flexible scenario. How does a test class with this solution looks like?

    Best regards,

    • Hi Christian,

      Thanks for your comment. I’ll be providing the complete source code for this framework soon, including its test classes. Stay tuned for more updates!

  4. First of all , I really appreciate for this valuable information this is a great framework for trigger, but I think following things needs to be updated : –
    public interface CriterionEvaluator {

    public Boolean evaluateCriterion(String fieldName, String fieldValue, SObject record);
    I think this should be a virtual class instead of interface
    public virtual with sharing class CriterionEvaluator
    public virtual boolean evaluateCriterion(String fieldName, String fieldValue, SObject record)
    return true;
    as we want to extend this class.
    and for criteriaSet.Trigger_Entry_Criteria__r it should be criteriaSet.ChildRelationShipName__r

    Please suggest and advise.

    • Hi Nachiket,

      Thanks for taking the time to read the post and for your contribution. You’re right, I just updated the code to use the keyword “implements” instead of “extends” as we want to make sure our criteria classes implement the defined interface. It could be an abstract class as you mentioned, but usually, we use abstract classes when we have methods to be inherited by the child classes.

      In terms of the child relationship name, this is completely arbitrary so I decided to use Trigger_Entry_Criteria_Set__mdt.Trigger_Entry_Criteria__r in this example, but feel free to update it as you prefer.

      Thanks again for your contribution and let me know if you have additional questions or feedback!

  5. I have one more question , how we can evaluate complex filter logic e.g (1 AND 2) OR (3 AND 4) I mean advanced filter logic ?

    • That’s a great question, Nachiket!

      Stay tuned for more updates related to this framework, I’ll be releasing a new enhanced version soon!

  6. Hi Jonatas,

    now I come to a point where I want to implement your really appreciated code to a real life scenario. Did you already publish a new enhanced version to support for instance an order of execution on different criterias and add AND or OR condition or for the test classes? 🙂


Leave a Comment