Skip to content

Improve Repository method operation customization

Alejo Carballude requested to merge feature/repository_options into master

Related tasks

Context

Repository methods currently provide little ways to customize their operation, making it impossible to implement some queries.

The methods that do provide behavior customization do so by way of function parameters. There are a number of issues with customizing operation using function parameters:

  1. Adding a new parameters requires updating all previously existing calls to the method.
  2. Method calls become increasingly verbose as all parameters need to be specified in each function call due to the lack of default values in Go.
  3. It is not possible to have more than one variadic parameter, which can make calls require complex array notation even for very simple calls.
  4. Every parameter added increases the complexity of the method implementation: more checks and calls are necessary to perform the actual business logic, even in the case where no configuration is applied at all.

One possible alternative approach to this is to receive parameters in a struct. This has a number of benefits:

  1. It is possible to only define the specific parameters that are relevant to a specific method call
  2. It is possible to define default values internally, and it is possible to extend the number of parameters without having to change existing code.

The big downside to the struct approach is that it still does not address the issue of having to check for each parameter regardless of use.

Another alternative approach is to use an Options (sometimes referred to Functional Options). In this setup, a variable number of options are passed to method calls to configure its operation. Options are functions that modify the behavior of the internal object performing the method's operation. Each option is only executed when passed, which removes the issue of needing to check for all possible options when performing a plain method call. Option implementation is also separate from the method logic, leading to proper separation of concerns.

Change

This MR introduces Repository method options for the Repository SQL implementation in the repository package.

Currently only the Repository.Find method is making use of options, but they can be extended to virtually any method in the Repository interface as the need arises.

Note that there are some issues introduced in this MR that are a consequence of the package structure. Right now, both the Repository interface and its SQL implementation live in the same package. Options were introduced for the SQL implementation, so they also live in the repository package. These options are implementation specific, but their names are not suffixed (e.g. with SQL). This will be an issue if another Repository implementation is defined. Moving the SQL implementation to its own package was left as future work.

Other information

Additional documentation

Edited by Alejo Carballude

Merge request reports