Clean Architecture for a Go REST API
Using Swagger 2.0 to specify a new REST API, I then generated a server in Go using go-swagger (https://goswagger.io/). This produces the following packages and components:
- restapi: configuration of routes mapping to request handlers
- restapi/operations: parameters, responses, handlers
- models: input/output payloads definitions
In order to build a Clean Architecture (https://8thlight.com/blog/uncle-bob/2012/08/13/the-clean-architecture.html) I defined the following additional packages :
- entities: domain model, define the data structures used in the application. Used by all layers (see diagram) they have the particularity in this project to embed GORM annotations (http://gorm.io/) which makes them specific to the database schema, making them coupled to the chosen database, impairing their reusability. To be reusable with any database schema, they should either not use any annotation and let the data access layer handle the data constraint ; or be converted back and forth to a database specific model (which would contain the GORM annotations). Any other way that I’m missing here ?
- service: application services that manipulate entities
- persistence: data access layer which handles the database (or other) persistence operations.
This architecture allow dependency injection which makes testing straightforward. Service and Persistence layers define interfaces referenced by the code using them. For example, the persistence package contains the definition of IssueStoreInterface, used to configure a service like IssueService.
For testing, a mock or fake IssueStore is passed to the NewIssueService method and handle the calls from the service. Similarly a mock service can be used when creating a Handler for testing.
I hope this help someone, at least it helped me clarify the design of the service I’m working on :-) !