Skip to Content

MVCS Best Practice - Repository Layer

Table of Contents

Introduction

Services contain your application business logic, orchestrating calls between your providers and repositories. They represent the “service” layer in the traditional definition of MVCS.

Biz logic should be contained in your service layer

  • This helps all other layers simple, dumb and reusable.

Try to make your service interface re-usable

  • Design your service interface in a generic that it can be reused by multiple different callers, such as different resources.
  • This will help you keep your code dry and make your code more maintainable.

Complicated validation should happen in service layer

  • Some of the validation logic requires complex rules, they should be done at service layer instead of resource layer.
  • Some of the validation logic requires cross-checking against database, they should be done at service layer instead of resource layer.

Service layer should be opinionated on what type of behavior constitute of error

  • For example, if the repository queries a database table by id and can not find the target row, then whether this is considered as an error should be decided at service layer. Below is an illustrative example of a basic GetWalletByID service function.
example.go
func (s *service) GetWalletByID(ctx context.Context, req GetWalletByIDRequest) (*GetWalletByIDResponse, error) { wallet, err := s.repo.GetWalletByID(ctx, model.WalletPublicStates, req.WalletIDQueryParams) if err != nil { return nil, err } if wallet == nil { return nil, cerror.New(common.WalletNotFoundError) } return &GetWalletByIDResponse{ Wallet: *wallet, }, nil }
Last updated on