Skip to content

Latest commit

 

History

History
89 lines (69 loc) · 3.03 KB

LoadersAndSavers.md

File metadata and controls

89 lines (69 loc) · 3.03 KB

Loaders and Savers

Contents

What it is

Loaders and Savers is a very simple abstraction to help separate business logic from a database / services layer.

Loaders tend to work similarly in functionality to a stored procedure.

Savers allow you to save changes.

Interfaces

The Loader interface looks like:

public T load();

snippet source | anchor

And the Saver interface looks like:

public T save(T save);

snippet source | anchor

Loaders

A Loader tends to wrap data access layers to a database, file system, or Web service. By wrapping the data retrieval in a Loader interface it becomes easy to swap it out for testing and other polymorphism. This also helps to separate your business logic from the implementation of your service layer.

Savers

The Saver also tends to wrap data access layers to a: database, file system, or Web service. This is the "write" as opposed to the Loader's "read".

The Saver returns the saved object. This is needed because some savers do not mutate the object, but actually create a new instance. Often saving mutates or does not alter the saved object at all. In these instances the Saver simply returns what is passed in.

Common Usage Patterns

Most current code hides the data access methods. For example:

public JSON loadCustomer(QueryParameter p) {
    // ... lots of logic
}

Using the Loaders and Savers you can convert this to two methods, the second of which is very easy to test and extend.

public JSON loadCustomer(QueryParameter p) {
    return loadCustomer(new CustomerQuery(p), new CustomerSaver());
}
public JSON loadCustomer(Loader<Customer> customerLoader, Saver<Customer> customerSaver) {
    // ... lots of logic
}

By adding this small seam the main business logic is much easier to test as it is isolated away from the database and service layer.

Testing

The simplest way to mock a Loader or Saver is with a lambda. For example, if we wanted to test what happens when the query does not find a customer, we could do the following call:

loadCustomer(c -> null, s -> s);

ExecutableCommand

ExecutableCommands extend Loaders to allow for easy testing of the actual Loader.


Back to User Guide