Andy in the Cloud

From BBC Basic to Force.com and beyond…

Apex Enterprise Patterns – Selector Layer

10 Comments

A major theme in this series on Apex Enterprise Patterns has been ensuring a good separation of concerns, making large complex enterprise level code bases more clear, self documenting, adaptable and robust to change, be that refactoring or functional evolution over time.

In the past articles in this series we have seen Service logic that orchestrates how functional sub-domains work together to form the key business processes your application provides. Domain logic breaks down the distinct behaviour of each custom object in your application by bring the power of Object Orientated Programming into your code.

This article introduces the Selector, a layer of code that encapsulates logic responsible for querying information from your custom objects and feeding it into your Domain and Service layer code as well as Batch Apex jobs.

Selectors

You can read the rest of this article on the wiki.developerforce.com here, enjoy!

Series Summary

This completes the current series of articles on Apex Enterprise Patterns. The main goal was to express a need for Separation of Concerns to help make your Apex logic on the platform live longer and maintain its stability. In presenting three of the main patterns I feel help deliver this. If nothing else, I’d like to think you have started to think more about SOC, even if it’s just class naming. Though hopefully beyond that if you use some of the articles’ various base classes great, please feel free to contribute to them. If you don’t, or decide to skip some or use a different pattern implementation that’s also fine, thats what patterns are all about. If you do, I’d love to hear about other implementations.

Martin Fowler’s excellent patterns continue to be referenced on platforms, new and old. I’ve very much enjoyed adapting them to this platform and using them to effect better adoption of Force.com platform best practices along the way. Thanks to everyone for all the great feedback, long may your code live!

10 thoughts on “Apex Enterprise Patterns – Selector Layer

  1. Andy,

    Again, this a great article and series. Definitely lots to think about.

    I do have a question for you.

    How would you approach the situation where you have:

    * A managed packaged application (i.e. “myapp”)
    * You have a couple of custom objects as part of you app (i.e. myapp__foo__c and myapp__bar__c)
    * You have created a Selector class over these custom objects (i.e. myapp__FooSelector, myapp__BarSelector)
    * During the installation of the managed package, the client adds more fields to the Foo custom object. (i.e. myapp_foo__c.red__c, myapp_foo__c.blue__c, and myapp_foo__c.yellow__c)

    How would the Selector pattern and myapp__FooSelector Apex class be changed to include those extra fields in the subscriber’s org?

    Can this change be “conditional”? If myapp_foo__c.red__c and myapp_foo__c.blue__c were text fields, I would have no issue with always including them as part of any query. On the other hand, if myapp_foo__c.yellow__c were a rich text field of 32,000, I would want to include that field very sparingly so as to avoid exceeding the heap space limit.

    Thanks for the help.

    Cheers!

    @JohnDTheMaven

    • First I would look at using FieldSets for this (platform feature on Custom Object). If you override the getSObjectFieldSetsList method from the base class giving it the name of your packaged Fieldset. Then once subscribers add fields and then add them to the Fieldset they will automatically get queried.

      Or if you want to do your own dynamic field you can do this in the getSObjectFieldList method.

      If you want the best of both worlds, maybe a virtual base class method public virtual Boolean includeField(SObjectField fieldToInclude) which defaults to true, but can be overridden. The base class code the compiles the Field set would call back up to this. Let me know if you want something like this and i could probably add it in an hour or so.

      • Hey Andrew,

        Thanks for the reply.

        For the moment, I don’t need this feature put in.

        About a year ago, I was working on a project that called for this use case. In that project, we built a base class (BaseDAO) that would be the workhorse for a series of DAO classes (one for each object we were interested in). The base class would query the entire field list and then execute the database.query. So it was able to include new fields added directly in the subscriber’s org. The approach had its strengths and weaknesses though.

        Your Selector approach definitely has some advantages over mine and given the choice now, I would choose your Selector pattern. The question above was more for informational purposes.

        Another possible solution that I was thinking about would be to use a Strategy pattern approach. Maybe have all of the managed package Selector classes listed as virtual and then extend with a custom class during the implementation to add the additional fields. It would still allow for compile time checking but the downside would be that there would be more development inside the subscriber’s org at implementation. The approaches you listed definitely get around this issue.

        Very interesting. Lots to think about here. 😉

        I very much appreciate your time.

        Cheers,

        @JohnDTheMaven

      • Ah i see, understood. Good thoughts as you say! It really motivates me to have these conversations so its absolutely my pleasure to brainstorm this stuff with you! 🙂

  2. Hi Andrew,

    Yet another question that is more related to the selector portion of this pattern (I think!). How would you handle call outs to other databases. In my use case, I am querying a subscription database for various pricing and quantities. I have to create my query using a soql like language and then submit that using the third party API. I was about to create a selector class that would extend the sobjectselector but then realized in it’s current form that is not possible due to the tables not actually existing within the Salesforce database.

    Would this be something that would would move into the Domain or Service Layer and do the callouts directly within the logic of the overall process?

    Thank you very much for your time in answering my questions!

    • Good question. If your callout is more aligned with feeding data into your application then it feels appropriate to put logic in the selector layer. Don’t feel that you need to extend the SObjectSelector class to do this though. Maybe you could have a new base class CalloutSelector with useful stuff to help such use cases. Or simply not bother at all with a base class and go along just the design considerations of the Selector layer just the same, so it looks and feels like a selector. Its really the separation of concerns which we are talking about here. I’d say if it is a kind of remote db call out, feels like selector layer stuff. If there are other operations you could also put some of those in a service layer class as you say. Hope this helps.

  3. Hey Andy,

    Another question for you, if you don’t mind.

    Here is the use case.

    There are two SObjects: Foo__c and Bar__c. Bar__c is a child object of Foo__c (either by Lookup or Master Detail). I need to be able to select all of the Bar__c records for a specific Foo__c record. That requirement alone would suggest a method like the following inside BarSelector class:

    public list selectByFoo( final Foo__c foo );

    Which would you use for method argument? The Foo__c object or simply Foo__c’s Id?

    Bulkification suggests that the method parameter should be either a Set or a Set. I believe you have suggested that in past but I also just want to confirm that is still the case.

    And finally, the method’s output. If we set this method up for Bulkification, then would the method return a Map<Id, List> where the Id is the Id of the Foo__c record?

    Thanks in advance for your thoughts here.

    Cheers!

    @JohnDTheMaven

    • I would pass in Foo Id, the selector method does not need anything else so why give the impression it does. As regards return, tend to use list to maintain the order by. It is easy using map constructors to turn sobject lists into map, so this is left as an option for the caller. Hope this makes sense. Cheers!

Leave a comment