3 ms·
> It totally destroys encapsulation. Not at all. Only the initializer needs to know about the needs. Then in the object world you can use a combination of depe
by mixedCase 9y ago
> It totally destroys encapsulation.
Not at all. Only the initializer needs to know about the needs. Then in the object world you can use a combination of dependency injection and factories to abstract over all the details you don't want callers to know about, and you can do the same more elegantly in the functional world with partial application (AKA currying).
- baby 9y ago> Then in the object world you can use a combination of dependency injection and factories to abstract over all the details you don't want callers to know about And then you made Go a complicated and awful to read language
- mixedCase 9y agoSorry, forgot about mentioning the very language the OP was about. That was stupid. You would use the "New" constructor function pattern in this case, using a higher order function called at injection time to keep it reusable and hide everything. I also prefer keeping the struct it returns as unexported so you get full encapsulation, but golint doesn't like it. I guess this is a personal issue.
- kornish 9y ago> You would use the "New" constructor function pattern in this case, using a higher order function called at injection time to keep it reusable and hide everything. Spot on. I love the decorator pattern for dependency injection. type Server struct { logger *logrus.Logger // optional store databaste.Store // required } type ServerOption func(Server) Server func WithLogger(logger *logrus.Logger) ServerOption { return func(s Server) Server { s.logger = logger return s } } func NewServer(store database.Store, options ...ServerOption) *Server { s := Server{store: store} for _, option := range options { s = option(s) } return &s } func main() { myServer := NewServer(myStore, WithLogger(myLogger)) }
- weberc2 9y agoThis is all common place in Go, we just don't use the terms that you have associated with heavy weight frameworks. DI is simply assembling all the pieces of your application in one single place instead of breaking it up arbitrarily in dozens of different constructors. The first is easier to read and test than the second. Factories are just functions or objects that can create new instances of a thing of the number or configuration of that thing can't be known at compile time.