Add primitive domains and criteria feature
This commit is contained in:
@@ -0,0 +1,107 @@
|
||||
# fflib-apex-extensions
|
||||
|
||||
## Criteria based filter for Domains and Selectors
|
||||
|
||||
A common criteria based filter for domains and SOQL condition generator for Selectors.
|
||||
|
||||
|
||||
It is very often that we have the same filters in domain and elector classes. The Criteria feature provides a solution that extracts the filter conditions into a single reusable criteria class. These filter conditions are dynamic and can be evaluated in run-time, or be converted to a SOQL statement condition.
|
||||
```
|
||||
+ - - - - - - - - +
|
||||
+ - - - | Filter Criteria | - - - +
|
||||
| + - - - - - - - - + |
|
||||
| |
|
||||
| |
|
||||
+ - - - - - - - + + - - - - - - - +
|
||||
| Domain | | Selector |
|
||||
+ - - - - - - - + + - - - - - - - +
|
||||
```
|
||||
Here is an example on how its used:
|
||||
|
||||
The criteria class is the place where all the filter conditions are stored for a single SObjectType.
|
||||
|
||||
```apex
|
||||
public with sharing class AccountCriteria extends fflib_Criteria
|
||||
{
|
||||
public AccountCriteria ShippingCountryEquals(String countryName)
|
||||
{
|
||||
equalTo(Schema.Account.ShippingCountry, countryName);
|
||||
return this;
|
||||
}
|
||||
|
||||
public AccountCriteria NumberOfEmployeesGreaterThan(Integer numberOfEmployees)
|
||||
{
|
||||
greaterThan(Schema.Account.NumberOfEmployees, numberOfEmployees);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
How it can be applied in a Domain class:
|
||||
|
||||
```apex
|
||||
public with sharing class Accounts
|
||||
extends SObjects
|
||||
implements IAccounts
|
||||
{
|
||||
private static final Integer LARGE_ACCOUNT_EMPLOYEE_NUMBERS = 500;
|
||||
|
||||
public Accounts getByCountry(String countryName)
|
||||
{
|
||||
return new Accounts(
|
||||
getRecords(
|
||||
new AccountCriteria().ShippingCountryEquals(countryName)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public Accounts getByNumberOfEmployeesGreaterThan(Integer numberOfEmployees)
|
||||
{
|
||||
return new Accounts(
|
||||
getRecords(
|
||||
new AccountCriteria().NumberOfEmployeesGreaterThan(numberOfEmployees)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public Accounts getByLargeAccountsInCountry(String countryName)
|
||||
{
|
||||
return new Accounts(
|
||||
getRecords(
|
||||
new AccountCriteria()
|
||||
.ShippingCountryEquals(countryName)
|
||||
.NumberOfEmployeesGreaterThan(numberOfEmployees)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
```
|
||||
In this example we see three filters; one for country, another for checking minimal number of employees and a third that combines the first two.
|
||||
It is important not to have a filter with too many conditions.
|
||||
One filter criteria condition per method is ideal to have maximum flexibility and a high chance on code-reuse.
|
||||
|
||||
|
||||
How the same filters can be used in the Selector class:
|
||||
|
||||
```apex
|
||||
public with sharing class AccountsSelector
|
||||
extends fflib_SObjectSelector
|
||||
implements IAccountsSelector
|
||||
{
|
||||
...
|
||||
public List<Account> selectByCountryWithMinimalNumberOfEmployees(String country, Integer minimalNumberOfEmployees)
|
||||
{
|
||||
return (List<Account>) Database.query(
|
||||
newQueryFactory()
|
||||
.setCondition(
|
||||
new AccountCriteria()
|
||||
.ShippingCountryEquals(country)
|
||||
.NumberOfEmployeesGreaterThan(minimalNumberOfEmployees)
|
||||
);
|
||||
}
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
With this feature developers can avoid a lot of code duplications.
|
||||
Hope you like it!
|
||||
@@ -0,0 +1,22 @@
|
||||
# fflib-apex-extensions
|
||||
|
||||
## Primitive Domains
|
||||
|
||||
A huge benefit of using primitive domains, is that you write less code.
|
||||
Instead of:
|
||||
```apex
|
||||
List<String> myStrings = getSomeStrings();
|
||||
```
|
||||
You can write:
|
||||
```apex
|
||||
Strings myStrings = getSomeString();
|
||||
```
|
||||
|
||||
It is a small thing, but it makes things looks much nicer.
|
||||
|
||||
|
||||
One other benefit is that you can encapsulate more logic as Lists. You can see these lists as a Domain.
|
||||
Take a look at the SObjects primitive domain, it is the new source for extending domain classes.
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user