| Permalink

Repository Pattern in Go: Drivers and Portable Code

When writting software in terms of Domain-Driven Design (DDD), specifically in the context of Go, there’s a common interpretation of the Repository pattern which drives the implementation to something similar to the following code:

1
2
3
4
type UserRepository interface {
	SaveUser(context.Context, *User) error
	GetUserByID(context.Context, string) (*User, error)
}

Now while this works, and it’s a good practice to use interfaces in general, this is a bit misleading as it makes it really difficult for UserRepository to be portable in terms of infrastructure (think database layer).

All specific implementations of the repository will usually end up with some duplicate code (think things you need to do regardless of the internal storage engine being used), which is not ideal for obvious reasons.

For this particular reason, I generally like to define repositories as concrete types, and introduce a layer of abstraction (drivers) that deals with the specific details of each storage engine (pgsql, mysql, even docstore, etc):

1
2
3
4
5
6
7
8
type UserDriver interface {
    SaveUser(context.Context, *User) error
	GetUserByID(context.Context, string) (*User, error)
}

type UserRepository struct {
    driver UserDriver
}

This allows the repository to be totally agnostic in terms of the storage engine, making it really portable. For convenience, the repository can expose the same API as the driver or even extend it with some more features:

1
2
3
func (r *UserRepository) SaveUser(context.Context, *User) error {}
func (r *UserRepository) GetUserByID(context.Context, string) (*User, error) {}
func (r *UserRepository) GetUserByEmail(context.Context, string) (*User, error) {}

So, if your repository contains code which makes use of packages like sql/driver, that’s the code you should move to a driver implementation.

Followed Articles

Status update, February 2021

Hi! Once again my focus has been Wayland-related projects this month. A steady stream of improvements made it into wlroots: Xyene…

via emersion February 22, 2021
Generated by openring