I've a bunch of small services that share some common packages like Logger
, Configuration
and Net
. And I wrote each package in separated project.
The issue is that my Logger
needs package Configuration
for set up. And my Configuration
(not solely used by Logger
) wants to write output log when necessary.
Therefore, I've circular dependency flaw Logger
-->Configuration
, Configuration
-->Logger
.
How can I redesign this code?
Something similar to this came up at GopherCon this year where Edward Muller argued that having config structs increased coupling in your application. The configuration package is just an extreme version of this. He argued that instead the dependency should just take in the bits of the configuration that it actually needs rather than the whole struct (or package in this case). You can see this part of his talk here:
https://www.youtube.com/watch?v=ltqV6pDKZD8
Or a textual version here:
https://about.sourcegraph.com/go/idiomatic-go/#config-structs
The essence of his solution would be to have you main do something like:
You will probably also have a "what gets created first" problem if your logger needs some settings from the config in order to initialize itself. I avoid this by creating a logger with sensible defaults, creating the configuration object using the default logger then adjusting the logger based on the loaded configuration. This means that you temporally have a logger that isn't configured correctly but the only thing you do with it is use it for logging the loading of the configuration.
I don't know how exactly your
Configuration
package looks like, but I don't think theLogger
should have a dependency to theConfiguration
package.In the end you probably want to configure the logger somehow. IMO this configuration shouldn't be more than a struct. So one solution might be:
Usually that problem get solved by creating third module that has dependencies for other two: