Skip to content
This repository has been archived by the owner on Oct 13, 2021. It is now read-only.

Returning interfaces? #28

Open
longfellowone opened this issue Dec 18, 2018 · 3 comments
Open

Returning interfaces? #28

longfellowone opened this issue Dec 18, 2018 · 3 comments

Comments

@longfellowone
Copy link

longfellowone commented Dec 18, 2018

Hi, Very new to GO/Programming here, very interested in implementing DDD. Having a look over your code and just have a question.

Why did you choose to return/export interfaces rather than structs/concrete types? Was it to keep from having to retype the same interface in each service?

Haven't quite figured everything out yet, maybe there is something else I'm missing?

For example the CargoRepository interface is declared in in cargo.go rather then where it is consumed?

type CargoRepository interface {
	Store(cargo *Cargo) error
	Find(id TrackingID) (*Cargo, error)
	FindAll() []*Cargo
}

Why not do something like this in your service.go?

type cargoRepository interface {
	Store(cargo *shipping.Cargo) error
	Find(id shipping.TrackingID) (*shipping.Cargo, error)
	FindAll() []*shipping.Cargo
}

type Service struct {
	cargos         cargoRepository
}

func (s *Service) Track() {
//...
}

func NewService(cargos cargoRepository) *Service {
	return &Service{
		cargos:         cargos,
	}
}

Reference:
https://github.com/golang/go/wiki/CodeReviewComments#interfaces
https://mycodesmells.com/post/accept-interfaces-return-struct-in-go
https://stackoverflow.com/questions/37181597/go-should-i-use-an-interface-to-allow-for-mocking

@alexbredy
Copy link

alexbredy commented Jan 31, 2019

  1. CargoRepository could be used in multiple services, and the Repo is part of the domain (not the application layer), tied to the Cargo in this case.

  2. The CargoRepository needs to be an interface and be exported (capital C) from the package as it is implemented in the infrastructure layer (check inmem/inmem.go and mongo/mongo.go)

@longfellowone
Copy link
Author

longfellowone commented Feb 1, 2019

1. CargoRepository could be used in multiple services, and the Repo is part of the domain (not the application layer), tied to the Cargo in this case.

2. The CargoRepository needs to be an interface and be exported (capital C) from the package as it is implemented in the infrastructure layer (check inmem/inmem.go and mongo/mongo.go)

Hey Alex

Since posting this Ive had a chance to play around with the DDD style a bit. Here is a solution I came up with that I think meets your requirements.

// cargo.go - package shipping
type CargoRepository interface {
	Store(cargo *shipping.Cargo) error
	Find(id shipping.TrackingID) (*shipping.Cargo, error)
	FindAll() []*shipping.Cargo
}


// service.go - package somethingelse
type Service interface {
	Track()
}

type cargoRepository interface {
	shipping.CargoRepository
}

type service struct {
	cargos cargoRepository
}

func (s *service) Track() {
	//...
}

func NewService(cargos cargoRepository) *service {
	return &service{
		cargos: cargos,
	}
}

// server.go takes the somethingelse.Service interface
func New(svc somethingelse.Service) *Server {
	//...
}

Here is an example of where Ive used this approach

https://github.com/longfellowone/field-services/blob/master/supply/purchasing/service.go#L14

This also allows you to add additional methods that are not part of the domain like in this example

https://github.com/longfellowone/field-services/blob/master/supply/ordering/service.go#L19

@juliandroid
Copy link

juliandroid commented Aug 30, 2019

Personally I'm not a big fan of exporting data structures when they are intended to be used as (through) interfaces only. In that case you can follow this recommendation:

https://golang.org/doc/effective_go.html#generality

Also defining interfaces where they are used (as recommended in the FAQ) is not possible if in the method's prototype also refers to another interface (arguments or return type) which you have to define too, but if you do that in the same place it won't be compatible (won't implement the interface).

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants