1

We have a existing salesforce implementation, we have most of the logic in triggers and trigger handlers. We are still using classic and no mobile or other UI. But still we are planning to implement apex common library for SOC

1. Is there any other better pattern to refactor domain classes that are huge (1000 lines of code )?
We have huge amount of logic in trigger handlers, once we refactored this in selector, domain, service and uow. We still have large amount of code in domain classes. We wrote some helper classes with public methods. .

eg. we have 30 field validations and 20 field defaults and the field defaults. Related object updates etc.

2. Apply Defaults - OnBeforeUpdate event
We have default fields onbeforeupdate event too, for this I extended the domain base class with this method, I know this is not upgrade safe. Is there a better option ? or should I just use onBeforeUpdate method ?

public virtual void onApplyDefaults(Map existingRecords) { }

3. Use custom Setting to Turn trigger on and off as needed
We have custom setting to to turn on and off triggers. for now it seems we need to write extra line of code in the trigger. is there any other better option for this ?

public trigger testtrigger(allevents){
if(customsetting){
 domainclass.getTriggerEvent(YourDomain.class).disableAll();
 return;
}
call domainclass here
}
4
  • Well, I belive if you dont want the complexity of FFlib but want similar functionalites, you can use kevin o Hara's trigger framework Commented Dec 13, 2018 at 18:49
  • we used to use similar triggerhandler but the code base size in increasing each day and each triggerhandler has more than 1000 lines of code, so we want to implement fflib for better soc
    – ab0369
    Commented Dec 13, 2018 at 18:51
  • 5
    Well, Ideally you should not write business logic in Handler. Handler should only call the Service methods. Commented Dec 13, 2018 at 18:56
  • This is how we made the decision between service vs domain github.com/financialforcedev/fflib-apex-common/issues/109
    – ab0369
    Commented Dec 13, 2018 at 19:27

1 Answer 1

7

If you plan on using fflib, then best practice is to adopt its conventions as documented in GitHub, Trailhead, and Andrew Fawcett's book Force.com Enterprise Architecture Second Edition (which is well worth reading on the philosophy and fine points of domain vs service vs selector and also has a superb section on unit testing with ApexMocks)

Domain classes should include the onXXX trigger handlers plus other methods that naturally apply to the (sobject) domain. Often these take the form of isXXX() that are domain utility methods usable by service (and sometime, selectors)

Service classes should be the place where work gets done - because service class methods are callable from multiple places - apex rest, invocable methods, VF controllers, apex web services, batchable, schedulable, queueable, future, and yes, domain. Most of the time, service methods should simply take in a set of IDs and then do work, either in their own unit of work or within a unit of work passed into the service method.

My domain trigger handlers tend to be of the form

onXXX() {
  YYYsService.doSomething(getQualifyingIdsForSomething());
  YYYsService.doSomethingElse(getQualifyingIdsForSomethingElse());
}

where the getQualifyingIdsForSomething() method iterates over Records and/or existingRecords to find the sobjects of interest. Iteration can be made easy using GitHub library Selector. If the service is passed an empty set of Ids, it just returns and does nothing.

There are huge advantages to using the fflib pattern and corresponding apexmocks library so you can unit test without having to do DML for many, many use cases. The domain class by its nature can be passed mocked sobjects and simply verifying the service(s) are called with the expected Ids. Separate unit tests on the services verify they do what is expected.

I wrote a recent SFSE answer with an example for selectors. See also this series of blog posts for more examples

As for disabling trigger execution as you outlined above - I would use custom metadata over custom settings to inject the master switch.

8
  • Thank you for your response. I was really hoping you to answer my question and god had heard my prayers. I read your blogs, I started reading Andrew's book and I even read your conversations with Andrew.
    – ab0369
    Commented Dec 14, 2018 at 3:21
  • 1Q is domain classes are getting bulkier with isXXX method and methods to creatingSetofIds to pass to service. The reason is we have 30 defaults by making variuos checks and 10 complex validations rules. Can we call helper classes from domain ?
    – ab0369
    Commented Dec 14, 2018 at 3:26
  • 1
    Is not a rule to call domain from service but not the other way around ? andyinthecloud.com/2013/04/24/…
    – ab0369
    Commented Dec 14, 2018 at 3:45
  • 1
    @ab0369 Glad I could help. At your convenience, you might want to vote up the response. You can of course delegate to other objects. John Daniel has some interesting techniques to break up the domain class into application-specific methods using dependency injection. See his Dreamforce 18 talks.
    – cropredy
    Commented Dec 14, 2018 at 5:00
  • 1
    @ab0369. Domain can of course call service as domain is a transaction entry point, just like VF controller or Apex Rest.
    – cropredy
    Commented Dec 14, 2018 at 5:03

Not the answer you're looking for? Browse other questions tagged .