Considerations when using SObject in the Service layer interface

In the following example, the Service method appears to add the Race records as the input, requiring the caller to query the object and also decide which fields have to be queried. This is a loose contract definition between the Service method and the caller:

RaceService.awardChampionShipPoints(List<Race__c> races) 

A better contract to the caller is to just ask for what is needed, in the case of the following example, the IDs:

RaceService.awardChampionShipPoints(Set<Id>raceIds) 

Even though IDs that relate to records from different object types could be passed (you might consider performing some parameter validation to reject such lists), this is a more expressive contract, focusing on what the service really needs. The caller now knows that only the ID is going to be used.

In the first example, when using the Race__c SObject type as a parameter type, it is not clear which fields callers need to populate, which can make the code fragile, as it is not something that can be expressed in the interface definition. Additionally, the fields required within the service code could change and require caller logic to be refactored. This could also be an example of failing in the encapsulation concern of the business logic within the Service layer.

It can be said that this design approach incurs additional overhead, especially if the caller has already queried the Race record for presentation purposes and the service must then re-query the information. However, in such cases, maintaining encapsulation and reuse concerns can be more compelling reasons. Careful monitoring of this consideration makes the service interface clearer, better encapsulated, and, ultimately, more robust.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.218.234.83