3.0 KiB
Backend style guide
Grafanas backend has been developed for a long time with a mix of code styles.
This style guide is a guide for how we want to write Go code in the future. Generally, we want to follow the style guides used in Go Code Review Comments and Peter Bourgon's Go: Best Practices for Production Environments
Global state
Global state makes testing and debugging software harder and its something we want to avoid when possible.
Unfortunately, there is quite a lot of global state in Grafana. The way we want to migrate away from this
is to use the inject
package to wire up all dependencies either in pkg/cmd/grafana-server/main.go
or
self registering using registry.RegisterService
ex https://github.com/grafana/grafana/blob/master/pkg/services/cleanup/cleanup.go#L25
the bus
bus.Dispatch
is used in many places and something we want to avoid in the future since it refers to a global instance.
The preferred solution, in this case, is to inject the bus
into services or take the bus instance as a parameter into functions.
settings package
In the setting
packages there are many global variables which Grafana sets at startup. This is also something we want to move
away from and move as much configuration as possible to the setting.Cfg
struct and pass it around, just like the bus.
Linting and formatting
We enforce strict gofmt
formating and use some linters on our codebase. You can find the current list of linters at https://github.com/grafana/grafana/blob/master/scripts/backend-lint.sh
We use revive as a go linter, and do enforce our custom config for it.
Testing
We use GoConvey for BDD/scenario based testing. Which we think is useful for testing certain chain or interactions. Ex https://github.com/grafana/grafana/blob/master/pkg/services/auth/auth_token_test.go
For smaller tests its preferred to use standard library testing.
Mocks/Stubs
As a general rule of thumb we try to override/replace functions/methods when mocks/stubs are needed. One common task is the need of overriding time (time.Now()
). See usage of getTime
variable in code and in test as an example.
When you need to stub/mock an interface you can implement a struct that allows you to override methods on a test-by-test basis. See stub and example usage.