In this post I add specify example of GO coding guidelines.
Many of these guidelines are language agnostic, so this can be used as a base for any other language.
Use full words
Names are important for clear text.
Always use full words.
For camel case make sure to use event for abbreviation:
myInstance
ssnFullText
clientIpAddress
No Comments
Our code should be clear and readable.
This means we should have comments only in case we do something unusual.
Do not comment on the obvious.
Look around for standards
Always look around for standards before making a change.
Someone had invested some thought about this code, and decided on a standard,
so we want to continue using the same standard and not create a new standard to confuse future development.
Each class in its own package
Each class should be its own package.
Do not include more than a single class in a package.
Clear TODOs
Do not leave TODOs in the code
Switch case default
Do not assume the default in a switch case is something that should not be handled.
In case we should not get to the default, raise an error.
Each Parameter in its own line
Each function parameter should be in its own line, even when it is the only parameter
Boolean condition
Boolean variable is a gift for usage in a condition.
Never compare boolean to true or false,
Unused code
All unused code must be removed. This includes: variables, functions, consts, comments, commented code and anything…
One letter self
Always use one letter for the “self”.
Explicit struct
Always create explicit structs.
Each struct should have a name and a definition.
Avoid using struct on the fly.
Bad Example:
Limit indentation
We are human, and we cannot understand complicated code with more than 3 indentations.
Use functions, and build a better clear design.
Empty array
When you need an empty array, always use nil
Max 15 codes line per function
Keep the functions short and clean
In case you have a function with more than 15 code lines,
split it wisely while keeping a clear code and reduce coupling.
Remove unnecessary code
Avoid adding code that is already handled by the GO language, for example:
* loop over nil array is ok, no need to add codition and check if the array is nil
Two words for public items
To bypass the IDE bug, any public struct field and public method must have at least 2 words.
Struct is always a pointer in function
Whenever sending a struct to a function and receiving a struct from a function,
use a pointer to the struct to avoid memory duplication.
Notice that time.Time is also a struct.
Function for nothing
In case you have a function that does only a simple statement, rethink whether it is really required.
You might still want to keep it to avoid code duplication,
but otherwise remove the function and just call the statement directly..
Reduce Coupling in function parameters
Design the functions to receive as few parameters as possible.
This reduces the coupling between the calling code and the function.
Reduce coupling in object fields
The idea of an object is that we have fields that are shared among all methods.
Hence, do not send the fields as parameters.
Keep you private stuff private
Use public only if you must expose.
Upper case function & variable & structure should be avoided otherwise.
Don’t return errors
When you have errors, raise them, do not return an error in the function return code.
The only case when you need to handle errors is when you have a new top level code, such as a new go routine.
No hard coded configuration
Avoid using hard coded configuration.
Use environment variables, or better - use some kind of mechanism that can be updated on the fly.
JSON tags
Usage of JSON tags is required only when communicating with an external entity, or when saving to redis.
Don’t add JSON tags just because you can.
Use OOD
In a component that receives some common input parameters that are used across its functions,
avoid sending the parameters over and over again.
Instead, create an object, set the input in the object’s fields, and avoid resending the parameters.
Constants usage
Constants should be used if and only if a value is used more than once
Tests
Any code should have a project test.
Make sure to check the code also manually in the local KIND cluster.
Memory usage
When using a persistent in-memory state, we must make sure the state memory is limited.
We must make sure the pod will not crash due to memory usage.
Passwords to frontend
Never return passwords from the backend to the GUI, this is a security issue
Logging to the relevant logger
Always use a common logger library for logging.
Make sure to include the ability to dynamically update the log level for a running pod.
Avoid complex types
We are simple humans, and we understand simple types.
If you have a complex type, create structures to simplify it.
Array of structs
Array of struct should always use point to the struct
Do not confuse this with a pointer to array.
Provide error details
When we have an error, we can find the exact location using the error stack trace.
However, we cannot know the values that cause the error.
Provide more details in such cases.
Don’t hide errors
When we have errors we should not hide them.
The default should be to raise the error.
If this is something we expect to have errors and we are 100% sure we cannot overcome this by retries or similar,
at least log with WARN.
Don’t bypass bugs
If we have bugs, we want to raise errors, and not to avoid them.
Do not create code that ignores bugs.
Avoid code duplication
Duplicate code makes the understanding of the code harder,
and leaves room for bugs in case someone updates only one copy of the code.
Safe Locking
Always prefer clean locking that guarantees cleanup of locking in case of error.
So we should have a function starting with the following:
a.mutex.Lock()
defer a.mutex.Lock()