Skip to content

Commit

Permalink
feat: use generics for dto
Browse files Browse the repository at this point in the history
  • Loading branch information
ChristophBe committed Dec 24, 2023
1 parent 49add85 commit 9685e8b
Show file tree
Hide file tree
Showing 9 changed files with 35 additions and 33 deletions.
2 changes: 1 addition & 1 deletion handlers/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (
)

// NewCreateHandler creates a http.Handler that handles the creation of a model
func NewCreateHandler[Model any](service types.CreateService[Model], responseWriter types.ResponseWriter, errorWriter types.ErrorResponseWriter) http.HandlerFunc {
func NewCreateHandler[Model types.ModelTypeInterface, Dto types.Dto[Model]](service types.CreateService[Model, Dto], responseWriter types.ResponseWriter, errorWriter types.ErrorResponseWriter) http.HandlerFunc {
return func(writer http.ResponseWriter, request *http.Request) {
ctx := request.Context()
dto, err := service.ParseDtoFromRequest(request)
Expand Down
6 changes: 3 additions & 3 deletions handlers/create_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@ type testModel struct {
Value string
}
type parseDtoFromRequestServiceMock struct {
dto types.Dto[testModel]
dto dtoMock[testModel]
err error
}

func (p parseDtoFromRequestServiceMock) ParseDtoFromRequest(_ *http.Request) (types.Dto[testModel], error) {
func (p parseDtoFromRequestServiceMock) ParseDtoFromRequest(_ *http.Request) (dtoMock[testModel], error) {
return p.dto, p.err
}

Expand Down Expand Up @@ -45,7 +45,7 @@ func TestCrudHandlersImpl_Create(t *testing.T) {

tt := []struct {
name string
service types.CreateService[testModel]
service types.CreateService[testModel, dtoMock[testModel]]
responseWriterError error
expectedError error
resultModel testModel
Expand Down
26 changes: 13 additions & 13 deletions handlers/crud-handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,46 +16,46 @@ type CrudHandlers interface {
}

// NewCrudHandlers creates a instance of CrudHandlers.
func NewCrudHandlers[M types.ModelTypeInterface](service types.Service[M], responseWriter types.ResponseWriter, errorWriter types.ErrorResponseWriter) CrudHandlers {
return crudHandlersImpl[M]{
func NewCrudHandlers[M types.ModelTypeInterface, D types.Dto[M]](service types.Service[M, D], responseWriter types.ResponseWriter, errorWriter types.ErrorResponseWriter) CrudHandlers {
return crudHandlersImpl[M, D]{
service: service,
responseWriter: responseWriter,
errorWriter: errorWriter,
}
}

type crudHandlersImpl[M types.ModelTypeInterface] struct {
service types.Service[M]
type crudHandlersImpl[M types.ModelTypeInterface, D types.Dto[M]] struct {
service types.Service[M, D]
responseWriter types.ResponseWriter
errorWriter types.ErrorResponseWriter
}

// Create is a http.Handler that handles the creation of a model
func (c crudHandlersImpl[M]) Create(writer http.ResponseWriter, request *http.Request) {
NewCreateHandler[M](c.service, c.responseWriter, c.errorWriter).ServeHTTP(writer, request)
func (c crudHandlersImpl[M, D]) Create(writer http.ResponseWriter, request *http.Request) {
NewCreateHandler[M, D](c.service, c.responseWriter, c.errorWriter).ServeHTTP(writer, request)
}

// GetAll is a http.Handler for fetch a list of model.
func (c crudHandlersImpl[M]) GetAll(writer http.ResponseWriter, request *http.Request) {
func (c crudHandlersImpl[M, D]) GetAll(writer http.ResponseWriter, request *http.Request) {
NewGetAllHandler[M](c.service, c.responseWriter, c.errorWriter).ServeHTTP(writer, request)
}

// GetOne returns a http handler for handling requests one specific model.
func (c crudHandlersImpl[M]) GetOne(w http.ResponseWriter, r *http.Request) {
func (c crudHandlersImpl[M, D]) GetOne(w http.ResponseWriter, r *http.Request) {
NewGetOneHandler[M](c.service, c.responseWriter, c.errorWriter)(w, r)
}

// Update is a http.Handler that handles partial updates for existing models.
func (c crudHandlersImpl[M]) Update(writer http.ResponseWriter, request *http.Request) {
NewUpdateHandler[M](c.service, c.responseWriter, c.errorWriter).ServeHTTP(writer, request)
func (c crudHandlersImpl[M, D]) Update(writer http.ResponseWriter, request *http.Request) {
NewUpdateHandler[M, D](c.service, c.responseWriter, c.errorWriter).ServeHTTP(writer, request)
}

// Replace is a http.Handler that handles replacing an exing model.
func (c crudHandlersImpl[M]) Replace(writer http.ResponseWriter, request *http.Request) {
NewReplaceHandler[M](c.service, c.responseWriter, c.errorWriter).ServeHTTP(writer, request)
func (c crudHandlersImpl[M, D]) Replace(writer http.ResponseWriter, request *http.Request) {
NewReplaceHandler[M, D](c.service, c.responseWriter, c.errorWriter).ServeHTTP(writer, request)
}

// Delete is a http handler for handling the deletion of specific model.
func (c crudHandlersImpl[M]) Delete(writer http.ResponseWriter, request *http.Request) {
func (c crudHandlersImpl[M, D]) Delete(writer http.ResponseWriter, request *http.Request) {
NewDeleteHandler[M](c.service, c.responseWriter, c.errorWriter).ServeHTTP(writer, request)
}
2 changes: 1 addition & 1 deletion handlers/replace.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (
)

// NewReplaceHandler creates a http.Handler that handles replacing an exing model.
func NewReplaceHandler[M types.ModelTypeInterface](service types.ReplaceService[M], responseWriter types.ResponseWriter, errorWriter types.ErrorResponseWriter) http.HandlerFunc {
func NewReplaceHandler[M types.ModelTypeInterface, D types.Dto[M]](service types.ReplaceService[M, D], responseWriter types.ResponseWriter, errorWriter types.ErrorResponseWriter) http.HandlerFunc {
return func(writer http.ResponseWriter, request *http.Request) {
ctx := request.Context()

Expand Down
2 changes: 1 addition & 1 deletion handlers/replace_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ func TestCrudHandlersImpl_Replace(t *testing.T) {

tt := []struct {
name string
service types.ReplaceService[testModel]
service types.ReplaceService[testModel, dtoMock[testModel]]
responseWriterError error
expectedError error
resultModel testModel
Expand Down
2 changes: 1 addition & 1 deletion handlers/update.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (
)

// NewUpdateHandler creates a http.Handler that handles partial updates for existing models.
func NewUpdateHandler[M types.ModelTypeInterface](service types.UpdateService[M], responseWriter types.ResponseWriter, errorWriter types.ErrorResponseWriter) http.HandlerFunc {
func NewUpdateHandler[M types.ModelTypeInterface, D types.Dto[M]](service types.UpdateService[M, D], responseWriter types.ResponseWriter, errorWriter types.ErrorResponseWriter) http.HandlerFunc {
return func(writer http.ResponseWriter, request *http.Request) {
ctx := request.Context()
dto, err := service.ParseDtoFromRequest(request)
Expand Down
2 changes: 1 addition & 1 deletion handlers/update_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ func TestCrudHandlersImpl_Update(t *testing.T) {

tt := []struct {
name string
service types.UpdateService[testModel]
service types.UpdateService[testModel, dtoMock[testModel]]
responseWriterError error
expectedError error
resultModel testModel
Expand Down
6 changes: 4 additions & 2 deletions types/dto.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package types

import "context"
import (
"context"
)

// Validatable is an interface that makes sure the typ can be validated.
type Validatable interface {
Expand All @@ -12,7 +14,7 @@ type Validatable interface {

// Dto is the type that contains the structure of the data that your api expect to receive.
// It contains a method to validate itself and to convert it to its corresponding model object.
type Dto[Model any] interface {
type Dto[Model ModelTypeInterface] interface {
Validatable

// AssignToModel assigns the value of the dto to a Model.
Expand Down
20 changes: 10 additions & 10 deletions types/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@ type DeleteModelService[M ModelTypeInterface] interface {
}

// ParseDtoFromRequestService defines the ParseDtoFromRequest function that is used in multiple handlers.
type ParseDtoFromRequestService[M ModelTypeInterface] interface {
type ParseDtoFromRequestService[M ModelTypeInterface, D Dto[M]] interface {
// ParseDtoFromRequest creates a dto instance based on a request
ParseDtoFromRequest(request *http.Request) (Dto[M], error)
ParseDtoFromRequest(request *http.Request) (D, error)
}

// FunctionHandlerService defines a service to handle a request by a Function
Expand All @@ -50,28 +50,28 @@ type DeleteService[M ModelTypeInterface] interface {
}

// CreateService defines functions that are need for the create model handler
type CreateService[M ModelTypeInterface] interface {
type CreateService[M ModelTypeInterface, D Dto[M]] interface {
CreateModelService[M]
ParseDtoFromRequestService[M]
ParseDtoFromRequestService[M, D]
}

// UpdateService defines functions that are need for the update model handler
type UpdateService[M ModelTypeInterface] interface {
type UpdateService[M ModelTypeInterface, D Dto[M]] interface {
UpdateModelService[M]
GetOneService[M]
ParseDtoFromRequestService[M]
ParseDtoFromRequestService[M, D]
}

// ReplaceService defines functions that are need for the replace model handler
type ReplaceService[M ModelTypeInterface] interface {
type ReplaceService[M ModelTypeInterface, D Dto[M]] interface {
UpdateModelService[M]
GetOneService[M]
ParseDtoFromRequestService[M]
ParseDtoFromRequestService[M, D]
}

// Service holds functions to retrieve Model instances or create Dto objects.
type Service[M ModelTypeInterface] interface {
ParseDtoFromRequestService[M]
type Service[M ModelTypeInterface, D Dto[M]] interface {
ParseDtoFromRequestService[M, D]
CreateModelService[M]
UpdateModelService[M]
GetOneService[M]
Expand Down

0 comments on commit 9685e8b

Please sign in to comment.