问题
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?
回答1:
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:
logSetting1 := configuration.GetLogSetting1()
logSetting2 := configuration.GetLogSetting2()
logger.SetSettings(logSetting1, logSetting2)
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.
回答2:
Usually that problem get solved by creating third module that has dependencies for other two:
回答3:
I don't know how exactly your Configuration
package looks like, but I don't think the Logger
should have a dependency to the Configuration
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:
- put the logger dependent configuration into on struct inside the logger package
- let the configuration package generate the logger config struct
- initialize the logger either in the configuration package or in some upper level package
来源:https://stackoverflow.com/questions/48221414/re-design-circular-dependency-flaw