diff --git a/HACKING.md b/HACKING.md index 092e17c6..462c3f9c 100644 --- a/HACKING.md +++ b/HACKING.md @@ -1,19 +1,23 @@ # AdGuard Home Developer Guidelines -As of **March 2021**, this document is partially a work-in-progress, but -should still be followed. Some of the rules aren't enforced as thoroughly or -remain broken in old code, but this is still the place to find out about what we -**want** our code to look like. +As of **March 2021**, following this document is obligatory for all new code. +Some of the rules aren't enforced as thoroughly or remain broken in old code, +but this is still the place to find out about what we **want** our code to look +like and how to improve it. The rules are mostly sorted in the alphabetical order. + + ## Contents * [Git](#git) * [Go](#go) - * [Code And Naming](#code-and-naming) + * [Code](#code) * [Commenting](#commenting) * [Formatting](#formatting) + * [Naming](#naming) + * [Testing](#testing) * [Recommended Reading](#recommended-reading) * [Markdown](#markdown) * [Shell Scripting](#shell-scripting) @@ -23,6 +27,8 @@ The rules are mostly sorted in the alphabetical order. + + ## Git * Call your branches either `NNNN-fix-foo` (where `NNNN` is the ID of the @@ -47,6 +53,8 @@ on GitHub and most other Markdown renderers. --> The only exceptions are direct mentions of identifiers from the source code and filenames like `HACKING.md`. + + ## Go > Not Golang, not GO, not GOLANG, not GoLang. It is Go in natural language, @@ -54,7 +62,13 @@ on GitHub and most other Markdown renderers. --> — [@rakyll](https://twitter.com/rakyll/status/1229850223184269312) - ### Code And Naming + ### Code + + * Always `recover` from panics in new goroutines. Preferably in the very + first statement. If all you want there is a log message, use + `agherr.LogPanic`. + + * Avoid `errors.New`, use `aghnet.Error` instead. * Avoid `goto`. @@ -70,6 +84,14 @@ on GitHub and most other Markdown renderers. --> } ``` + Except when the check is done to then use the first character: + + ```go + if len(s) > 0 { + c := s[0] + } + ``` + * Constructors should validate their arguments and return meaningful errors. As a corollary, avoid lazy initialization. @@ -99,10 +121,11 @@ on GitHub and most other Markdown renderers. --> ) ``` - * Don't use naked `return`s. + * Don't use `fmt.Sprintf` where a more structured approach to string + conversion could be used. For example, `net.JoinHostPort` or + `url.(*URL).String`. - * Don't use underscores in file and package names, unless they're build tags - or for tests. This is to prevent accidental build errors with weird tags. + * Don't use naked `return`s. * Don't write non-test code with more than four (**4**) levels of indentation. Just like [Linus said], plus an additional level for an occasional error @@ -114,25 +137,7 @@ on GitHub and most other Markdown renderers. --> * Eschew external dependencies, including transitive, unless absolutely necessary. - * Name benchmarks and tests using the same convention as examples. For - example: - - ```go - func TestFunction(t *testing.T) { /* … */ } - func TestFunction_suffix(t *testing.T) { /* … */ } - func TestType_Method(t *testing.T) { /* … */ } - func TestType_Method_suffix(t *testing.T) { /* … */ } - ``` - - * Name parameters in interface definitions: - - ```go - type Frobulator interface { - Frobulate(f Foo, b Bar) (r Result, err error) - } - ``` - - * Name the deferred errors (e.g. when closing something) `derr`. + * Minimize scope of variables as much as possible. * No shadowing, since it can often lead to subtle bugs, especially with errors. @@ -140,20 +145,12 @@ on GitHub and most other Markdown renderers. --> * Prefer constants to variables where possible. Reduce global variables. Use [constant errors] instead of `errors.New`. + * Prefer to use named functions for goroutines. + * Program code lines should not be longer than one hundred (**100**) columns. For comments, see the text section below. - * Unused arguments in anonymous functions must be called `_`: - - ```go - v.onSuccess = func(_ int, msg string) { - // … - } - ``` - - * Use linters. - - * Use named returns to improve readability of function signatures. + * Use linters. `make go-lint`. * Write logs and error messages in lowercase only to make it easier to `grep` logs and error messages without using the `-i` flag. @@ -211,6 +208,49 @@ on GitHub and most other Markdown renderers. --> }} ``` + ### Naming + + * Don't use underscores in file and package names, unless they're build tags + or for tests. This is to prevent accidental build errors with weird tags. + + * Name benchmarks and tests using the same convention as examples. For + example: + + ```go + func TestFunction(t *testing.T) { /* … */ } + func TestFunction_suffix(t *testing.T) { /* … */ } + func TestType_Method(t *testing.T) { /* … */ } + func TestType_Method_suffix(t *testing.T) { /* … */ } + ``` + + * Name parameters in interface definitions: + + ```go + type Frobulator interface { + Frobulate(f Foo, b Bar) (r Result, err error) + } + ``` + + * Name the deferred errors (e.g. when closing something) `derr`. + + * Unused arguments in anonymous functions must be called `_`: + + ```go + v.onSuccess = func(_ int, msg string) { + // … + } + ``` + + * Use named returns to improve readability of function signatures. + + ### Testing + + * Use `assert.NoError` and `require.NoError` instead of `assert.Nil` and + `require.Nil` on errors. + + * Use functions like `require.Foo` instead of `assert.Foo` when the test + cannot continue if the condition is false. + ### Recommended Reading * . @@ -223,6 +263,8 @@ on GitHub and most other Markdown renderers. --> [Linus said]: https://www.kernel.org/doc/html/v4.17/process/coding-style.html#indentation [Text, Including Comments]: #text-including-comments + + ## Markdown * **TODO(a.garipov):** Define more Markdown conventions. @@ -234,6 +276,8 @@ on GitHub and most other Markdown renderers. --> * Use either link references or link destinations only. Put all link reference definitions at the end of the second-level block. + + ## Shell Scripting * Avoid bashisms and GNUisms, prefer POSIX features only. @@ -336,6 +380,7 @@ on GitHub and most other Markdown renderers. --> escaping is required or there are single quotes inside the string (e.g. for GitHub Actions). - * Use `>` for multiline strings, unless you need to keep the line breaks. + * Use `>` for multiline strings, unless you need to keep the line breaks. Use + `|` for multiline strings when you do. [NO-rway Law]: https://news.ycombinator.com/item?id=17359376