Coding Style

Fennec has various types of source files. However, generally there are 2 major types:

  1. BASH
  2. YAML

Unless otherwise specified, you should always comply to the general direction of the technology you used or Google Style Guides.

WARNING

This is a very long post since it contains multiple languages. You are advised to open multiple tabs. The recommended reading sections are: 1, 2, your choice(s) of langauge.

  1. General Mindset
  2. Coding Styles in General
  3. Coding Styles in BASH
  4. Coding Styles in YAML


General Mindset

In any cases, with or without guide, you MUST comply to these general rules of practices:

ALWAYS Respect Readability

Codes are for human to read. The compiler does its job by converting them into a binary which the computer understands so:

  1. Write for human to read!
  2. Avoid Hungarian notation turning count_active_users() into cntuser()
  3. Leave no room for guessing.
  4. Make your code self-explainatory. You don’t need to abuse comments to explain your code. That is a sign of failure.
  5. DO NOT hide your code! As in:
# BAD
#####
if (condition) do_this;
	do_something_everytime;


# SHOULD BE
###########
if (condition)
	do_this;
do_something_everytime;


USE Common Sense

In situation where you do not know what to do: ASK!

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.

Remember, we are in the industry of managing information. If we make one wrong mistake, it is going to cost us a bomb!

If you are self-aware, knowing that you do not have common sense, again ASK or do the industry a favor: change your career path because this industry is not suitable for you.


Respect Local Coding Style

If there is a local coding style available for reference, be it a document or inside the source codes, first thing first: RESPECT the local coding style.

You would not like me walking into your house and set the living room on fire because I enjoy fireworks, do you?


Pack Everything in Function

Keep the code back-trackable, 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:

#!/bin/bash
source ./library.sh
soruce ./config/settings.sh

bprint() {
	printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' =
	echo $@
	printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' =
	return 0
}

add() {
	echo $1 + $2
	return 0
}

main() {
	add $@
}
main $@


Coding Styles In General

Indentation and Spacing

Use 8-characters indentation for 80 columns width or 1:10 ratio so that you maintain maximum of 3 indentations per lines.

Use TAB ("\t") over SPACE (" ").

Rationale

1. It acts as a natural cyclomatic complexity sensing system

If you need more than 3 tabs per line, it signals that you are going to produce a complicated nesting program. Heed that warning and break it into smaller parts with function or subroutines.

2. Clearer, readable codes

With 8-spacing, it illustrate a clearer spacing and make it easier to read. Some of us codes from 5am to 10pm (~15 hours) on a daily basis. Make sure your codes facilitates readability.

3. Tab was designed for indentation

TAB is meant for indentation. It was designed by default. Use it instead of spacing. That’s 1 byte over 8 bytes in terms of size. Your code editor should render them correctly anyway.


Spacing for Patterns

Switch

Keep the case same indentation as switch. You don’t need additional indent for something like part of the overall syntax. Example:

switch (keyword) {
case 'A':
	do_something;
	break;
case 'B':
	do_something_else;
	break;
default:
	do_default;
	break;
}


If Else If Else

If the language permits, one liner action for if:

if (condition) do_this;

Otherwise, multiple conditions:

if (condition) {
	do_this;
} 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 the specifics and respond early. Example:

#####################################################################
# 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
}
do_default;  # anything from this line is true
exit 0;


Looping

Keep in clear, short, and simple as such:

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;
}

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.


Break Long Lines

Always find out the language’s line breaking style. The preferred maximum columns are 80 characters. While reading, you would want to make your codes scroll in a single direction, rather than 2.

There are 2 types of long lines breaking:

  1. breaking the code
  2. breaking long string / data types

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"


Naming Conventions

Follow the language specific orientations. There is no strict practices to say you must use one over the others. HOWEVER, there are strict rules:

  1. There should only be 1 convention in a source code.
  2. No reason for you to write Hungarian notation in ANY convention.


For private naming convention, you can use simplified alphabets or maximum of 2 words that are short and on point. Examples:

  1. Instead of: loop_counter, you can use i.
  2. Isntead of: temporary_photo_link, you can use photo1.


CamelCase Convention

Use UPPERCASE_SNAKE_CASE for global convention.

Use CapitalizedCamelCase for public accessible API, variable, or function.

Use lowercaseStartCamelCase for private accessible API, variable, or function.

Avoid _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);
}


snake_case Convention

Use UPPERCASE_SNAKE_CASE for global convention.

Use lowercase_snake_case for public accessible API, variable, or function.

Use _starting_underscore_snake_case for private accessible API, variable, or function.

Exception
  1. The language is offering 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);
}


Variables and Functions

  1. Avoid global variables unless absolute necessary.
  2. A function should use a maximum of 5-7 variables inside it. If you need more than that, you’re doing something wrong and probably want to split it into smaller functions.
  3. Write in a way that a first year high school student can understand the function. Otherwise, break it until it reaches that level of comprehensions.
  4. For languages which offers braces {, adhere to its coding convention. Otherwise, for function, it is preferred to be:
int add(x, y)
{
	return x + y;
}

for (int i=0; i<5; i++) {
	add(i, i);
}



// Avoid this to make it clear that is a function, not a loop
int add(x, y) {
	return x + y;
}

for (int i=0; i<5; i++) {
	add(i, i);
}


Comments

  1. Avoid explaining your codes. Do that to your codes. It is a waste of time explaining bad codes anyway.
  2. Tell WHAT not HOW.
  3. Use the long comment syntax if available. Stick to one syntax convention.

Example:

/* this is clearer than using // */

/* This is also clearer
 * for multi-line comments
 */



# This is another commenting style

# This is the longer
# multi-line
# version


Silence is Gold

Keep the output (stdout) as quiet as possible. If you need to print status, use the correct output channel like stderr or log it 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


Return Values

Keep 0 integer value as SUCCESS. Any non-integer numbers indicates failure with identity defined your error table.


Filenames

Respect the standard convention. Always append .extension.



Coding Styles in BASH

This are the coding styles in BASH/Shell script.

Shebang Line

Always include Shebang Line in Line 1. Period.. You’ll break your script and let your user crying to figure out which Shell program to use if you avoid it. A Shebang line is:

#!/bin/bash

Example:

#!/bin/bash
1>&2 echo "Hello World"


Filename

The file extension is .sh or .bash.


Naming Convention

Consistency first. Otherwise, use snake_case convention. Example:

integer=5
export OS_LEVEL=5
TITLE_SHARABLE_VARIABLE="the shared data for other script to source from"

process_data() {
	...
}

# run
unset integer
process_data


Functions

Opening brace { after the function naming since it breaks the script. export comes after the function declaration. Example:

function_name() {
	echo "Hello World"
}
export -f function_name

Always keep track to unset your functions after used.


Variables

Keep operations outside variables. export comes before the variable. Example:

# variable requires operations
GLOBAL_VARIABLE="$(ls)"
export GLOBAL_VARIABLE

# variable with only value
export GLOBAL_LANGUAGE="en-US"

# DO NOT do this. $(...) is an operation
export GLOBAL_VARIABLE="$(ls)"


Indentation and Maximum Columns.

Use TAB (\t). Maximum columns are 80 characters. It’s a terminal script.


If Else and While Loop Condition Syntax

  1. Perferbly [[ ... ]] for bash while [ ... ] for POSIX compliant.
  2. 1 space after [ or [[.
  3. 1 space before ] or ]].
  4. then or do should shares the same line as if, elif, while and for respectively.
  5. No space before the semi-colon (;); 1 space after; then then or do comes later.
  6. All contents inside should have 1 TAB inside.

Example:

# BASH
if [[ 5 != 0 ]]; then
	...
elif [[ 5 != 0 || 5 != 4 ]]; then
	...
elif [[ ([[ 5 != 0 || 5 != 4 ]]) && ([[ 5 != 0 || 5 != 4 ]]) ]]; then
	...
elif [[ ([[ 5 != 0 || 5 != 4 ]]) &&
		([[ 5 != 0 || 5 != 4 ]]) &&
		([[ 5 != 0 || 5 != 4 ]]) &&
		([[ 5 != 0 || 5 != 4 ]]) ]]; then
else
	...
fi


# POSIX Compliant
if [ -z "$filename" ]; then
	...
elif [ -z "$filename" ] && { [ -e "$filename" ] || [ -r "$filename" ] }; then
	...
else
	...
fi



# BASH
while [[ ([[ 5 != 0 || 5 != 4 ]]) && ([[ 5 != 0 || 5 != 4 ]]) ]]; do
	...
done

for item in "${list[@]}"; do
	...
done


# POSIX Compliant
while { [ 5 != 0 ] || [ 5 != 4 ] } && { [ 5 != 0 ] || [ 5 != 4 ] }; do
	...
done

for file in ./directory/*; do
	...
done


Variables

  1. Avoid array if you want POSIX compliant.
  2. Forbid yourself from using local keyword. Use naming convention.
  3. Forbid the use of alias. Use function instead.



Coding Styles in YAML

This is the coding style for YAML configuration file.

Filename

The extension is .yml.


Indents and Space

  1. Use space as tab instead of \t.
  2. Use 4 spaces as standard indent.
  3. Avoid 1 space tab.

NOTE

Maintain tab alignment for consistency. That’s how YAML works.


Strings

Follow source code. Otherwise ,use double quote (").


Naming Convention

  1. Use snake_case convention.
  2. Avoid SPACE in the name. Use underscore _ instead.
  3. No space before the colon (:).
  4. One space after the colon (:).

Example:

this_is_a_very_long_string_label: "string"
integer: 5
float: 10.0
boolean: true


Comments

Keep it on its own line. You don’t need an inline comment. The label should be self-explanatory.

Example:

# Server launch date
date: "2001-12-14T21:59:43.10-05:00"

# NOT
date: "2001-12-14T21:59:43.10-05:00" # This is the server launch date


Collection

  1. Use tabulators for consistency and readability.

Example:

symfony-1.0:
    - PHP: 5.0
    - Propel: 1.2
    - python:
        - 2.7: 5.2
        - 3.3: 4.4

symfony-1.2:
    - PHP: 5.2
    - Propel: 1.3


Don’t Repeat Yourself.

  1. Make use of alias (&) to group repeated value.
  2. Use <<: to include them.
  3. Use * to call your alias group.

Example:

common: &default
    adapter: postgresql
    version: 1.0

development:
    <<: *default
    database: dev_development

test:
    <<: *default
    database: test_test

production:
    <<: *default
    database: test_production
    version: 0.5