These are the essential styles serving as the main pillar for all other language-specific styles.
Before you start coding, observe the existing source codes and seek out for existing code styles inside the repository. Remember, at the end of the day, it is the owner (or maintainers) who will be reviewing your codes, respect them. If there isn't any, make a discussion with them to clear things out.
It’s better to ask now compared to correcting 1000+ lines of codes you created. It’s okay to be smart but don’t act smart. Use common sense to solve a question or a problem.
Keep the code back-tractable, like from main
to other core functions
, then internal functions, etc. This way, it’s easier to figure out what is your code doing. Example in BASH:
#!/bin/bash
################################
# User Variables #
################################
VERSION="0.0.1"
################################
# App Variables #
################################
action=""
message=""
################################
# Functions #
################################
print_version() {
echo $VERSION
}
run() {
if [[ "$message" == "" ]]; then
echo "I see no message. Did you say something?"
return 0
fi
echo "$message"
}
################################
# CLI Parameters and Help #
################################
print_help() {
echo "\
PROGRAM NAME
One liner description
-------------------------------------------------------------------------------
To use: $0 [ACTION] [ARGUMENTS]
ACTIONS
1. -h, --help print help. Longest help is up
to this length for terminal
friendly printout.
2. -r, --run run the program. In this case,
says the message.
COMPULSORY VALUES:
1. -r \"[message you want]\"
COMPULSORY ARGUMENTS:
1. -
OPTIONAL ARGUMENTS:
1. -
3. -v, --version print app version.
"
}
run_action() {
case "$action" in
"h")
print_help
;;
"r")
run
;;
"v")
print_version
;;
*)
echo "[ ERROR ] - invalid command."
return 1
;;
esac
}
process_parameters() {
while [[ $# != 0 ]]; do
case "$1" in
-h|--help)
action="h"
;;
-r|--run)
if [[ "$2" != "" && "${2:0:1}" != "-" ]]; then
message="${@:2}"
shift 1
fi
action="r"
;;
-v|--version)
action="v"
;;
*)
;;
esac
shift 1
done
}
main() {
process_parameters $@
run_action
if [[ $? != 0 ]]; then
exit 1
fi
}
main $@
Making modular executable functions allow:
"\t"
) over SPACE (" "
). 80
columns width or 1:10
ratio so that you maintain maximum of 3 indentations
per lines.function
or subroutines
.switch (keyword) {
case 'A':
do_something;
break;
case 'B':
do_something_else;
break;
default:
do_default;
break;
}
Keep the case
same indentation as switch
. You don’t need additional indent for something like part of the overall syntax.
If it is one-line action:
if (condition) do_this;
If it is multi-line actions or multi-conditions:
if (condition) {
do_this;
do_something_more;
} else if (condition) {
do_that;
} else {
do_something_else;
}
If the else
is a default routine in a function, then do not write it. Always check for specifics and respond and exit/return early instead of nesting and wasting indentation:
#####################################################################
# You are checking false condition. Exit/return early when possible # #####################################################################
if (false condition) {
do_false_handling;
} else {
do_default;
}
exit 0;
#######################################
# A Better way (and save indentation) #
#######################################
if (false condition) {
do_false_handling;
exit 1
}
# anything from this line is true
do_default;
exit 0;
Another example, instead of:
if err != nil {
// error handling
} else {
// normal code
}
write:
if err != nil {
// error handling
return // or continue, etc.
}
// normal code
for (i=0; i<5; i++) {
do_something_repeatedly;
}
for item in list {
do_something_repeatedly;
}
while (i != true) {
do_something_boring_repeatedly;
}
while true {
do_to_infinity_and_beyond;
}
Keep in clear, short, and simple. Watch where to put SPACE before, inside and outside the conditions depending on languages.
Avoid do ... while
if available. It simply means you couldn’t be bothered with readability checking for looping and waste indentations and brain juice.
Avoid unconventional keyword provided by the language to keep the learning curve flat, like until
. Use the conditions smartly.
80 characters
for wide range of editors compatibility including vim.There are 2 types of long lines breaking:
Example in bash:
# BAD - Long Code
./program --super-long-arguments value1 --super-long-arguments2 value2 --super-long-arguments3 value3
# GOOD
./program --super-long-arguments value1 \
--super-long-arguments value2 \
--super-long-arguments value3
# BAD - Long String
./program --super-long-arguments "extremely long values that I have no idea what I'm typing here"
# GOOD
./program --super-long-arguments "\
extremely long values that I have no idea what I'm typing here"
# BAD - Break mid-statement
currentEstimate = calc(currentEstimate + x *
currentEstimate) / 2.0f;
# GOOD - Break at higher level
currentEstimate =
calc(currentEstimate + x * currentEstimate) /
2.0f;
UPPERCASE_SNAKE_CASE
for global convention.CapitalizedCamelCase
for public accessible API, variable, or function.lowercaseStartCamelCase
for private accessible API, variable, or function._startingUnderscoreCamelCase
as it creates confusion.Example:
var (
// SELECTED_LANGUAGE only works in en-US
SELECTED_LANGUAGE = "en-US"
)
func internalAddAlgo(x int, y int) {
...
}
// Add is a function to add x and y mathematically.
func Add(x int, y int) {
internalAddAlgo(x, y);
}
UPPERCASE_SNAKE_CASE
for global convention.lowercase_snake_case
for public accessible API, variable, or function._starting_underscore_snake_case
for private accessible API, variable, or function.public
/ private
keywords. In that case, use those keywords instead and stick to lowercase_snake_case
for private functions.Example:
extern *char SELECTED_LANGUAGE = "en-US" // tell the world only works in en-US
int __internal_add_number(int x, int y)
{
...
}
// Add is a function to sum x and y mathematically.
int add(int x, int y)
{
return __internal_add_number(x, y);
}
{
, adhere to its coding convention. Otherwise, it is preferred to be:int add(x, y) {
return x + y;
}
To measure whether you need a comment always think this:
Good codes has a lot of comments; bad codes needs comments. - Dave Thomas and Andrew Hunt
Example:
/* this is clearer, simple to remember than using // in languages like C */
/*
* This is also clearer
* for multi-line comments
*/
# This is another commenting style
# This is the longer
# multi-line
# version
stdout
) as quiet as possible.stderr
or log status messages into a file.Example in BASH:
Add() {
echo "$((1 + 2))"
return 0
}
1>&2 echo -n "This is a status message. Doing 5 + 3 = "
Add 5 3
0
integer value as SUCCESS
..extension
.base
, common
, utils
, misc
, etc.To measure a good name, you should not need to explain the name itself. Good name should be not wasting spaces for extraneous, describes the application of the variable or constant, not the content (e.g. the result, not the function implementation), and quickly and easily inferred (idiomatic).
Example in Go:
// instead of this:
var usersMap map[string]*User
var companiesMap map[string]*Company
var productsMap map[string]*Products
// use this:
var users map[string]*User
var companies map[string]*Company
var products map[string]*Products
Concurrency is similar to team delegation. If the job is simple, don't delegate; do it. If you want to delegate, make sure you tell the end-goal to your teammate. Don't let him/her run wildly and ended up destroying things. Also, delegate, not micro-managing it (shared memory). Everyone hates micro-manager so avoid being one.
This is to prevent timing side-channel attack for sensitive codes, especially password hashes comparison. It allows the attacker to use a timing table to match the passwords back to the original characters via confident guessing.
Keep things simple and boring, complying to the cryptography community best practices.
This is to avoid letting the next developer to wondering in the magic land or forcing them to read up documentations from scratch just to figure this magic out.
There are only few truly magical numbers in the current industry. Those has a name too. Therefore, yours should have too.
This is to balance between costly refactoring vs. necessary duplication during each stages of the codes.
There are time where you just need to prove things are working (first prototype), testing the development process (expand the code base for the first time), and truly a duplication issues in future development (building on existing working code base). Do duplication refactoring when the cost is worth the optimization.
Program should only expose minimum necessary public interface. User does not need to know too much of stuff. Also, maintainers and developers hate magical codes where global state facilitates. We should always write the code in clarity and controllable.
Example:
goto
, only use it inside a function, and jump inside that function ONLY.goto
jump according to the direction of the readability (if the flow is down, then jump down, not up).goto
jump after all the memory declaration are done.goto
jump is the very source of evil and the first step to spaghetti codes.goto
jumping - https://stackoverflow.com/questions/4051883/batch-script-how-to-check-for-admin-rights instead of practicing exit early.goto
jump for time-sensitive functions, like cryptography compare API.That's all about coding styles in general. You may feel free to explore the language specific coding styles. Their mentioning overrides this generalized version.