Why do you think we can / can't replace SOQL Builders with User Mode SOQL?
I will answer your first question because I have more experience with Selectors which gives me a better view of why we need them.
First of all WITH USER_MODE
applies an FLS + Sharing rules to the SOQL:
The object permissions, field-level security, and sharing rules of the current user are enforced.
Of course, it's a good practice to do it, but we do not live in a perfect world, a lot of projects have bad design.
What if I would like to respect FLS, but get records without sharing
to meet business requirements? WITH USER_MODE
is not always a solution.
Secondly WITH USER_MODE
covers a tiny fraction (FLS, sharing rules*) of what Selectors can do.
There are a lot of benefits that the Selector layer can provide:
- Additional level of abstraction - The selector layer is an additional level of abstraction that gives you the possibility to control the execution of SQOL. It's a quite generic statement, but that level is a source of other benefits.
- Mocking - Selector classes give a possibility to mock return values in unit tests.
- Mock external objects (__x) - External objects cannot be inserted in unit tests. You need to mock all SOQLs, of course, there is
if (Test. isRunningTest())
, but not an elegant and clean solution.
- Mock custom metadata - Custom metadata cannot be inserted in unit tests unless the developer uses the Metadata API. Mocking can be a solution.
- Control field-level security - The best practice is to execute SOQLs
WITH USER_MODE
to enforce field-level security and object permissions of the running user. The selector layer can apply WITH USER_MODE
by default to all of the queries, so the developer does not need to care about it. Developers can also add WITH SYSTEM_MODE
to all SOQLs from a specific selector. I believe selectors make FLS control easier.
- Control sharings rules - The selector allows to execution of different SQOLs within the same class in different sharing modes (
with sharing
/without sharing
).
- Avoid duplicates - Generic SQOLs like
getById
, and getByRecordType
can be stored in the selector class. It makes developers' lives easier when you have predefined/tested methods.
- Default configuration - The selector class can provide default SOQL configuration like default fields, FLS settings, and sharing rules. I was on a project were sharing rules were screwed up and each SOQL needed a default condition
OwnerId = :UserInfo.getUserId()
, it was quite simple to achieve with Selectors by adding a default condition to all of the SOQL.
- Cache - The selector can have additional logic to save SOQL results. That approach can be beneficial in places where we need to save SOQL limits.
SOQL Lib
Resources:
user mode
. Chris and Daniel mentioned a "user mode with perm set" concept to plug this gap, though I've got some reservations around use of an admin modifiable perm set to cover fields/objects the user doesn't have access to. We have a lot of different queries of a lot of different objects for a lot of different use cases and adding perm sets for each would not make sense. Having a single extra perm set also doesn't make sense... it's a quandary