MY Programming Style Guide

General Philosophy: Why dafuq do you need a style guide?

Firstly, make sure you have read the book Clean Code. This is super important. In essence, we want to optimize for readability and maintainability. Now, I know the projects that I work on don’t necessarily need to be maintained, so why should I care? Well, I want to become the best programmer and engineer I can be, and that includes finding consistency in everything that I do.

Ultimately, this will enhance my productivity.

At first, it might be hard to get used to, but over an extended period, I sincerely believe that I will benefit a lot from the consistency.

Also read up on Clean Architecture.

Let’s dive into the language-specific coding conventions.

I really like the Google Style Guide.

Clean Code Principles

Clarity is king. Professionals use their powers for good and write code that others can understand.

General rules

  1. Keep it simple stupid. Simpler is always better. Reduce complexity as much as possible.
  2. Boy Scout Rule. Leave the campground cleaner than you found it.
  3. Always find the root cause. Always look for the root cause of a problem.

Understandability tips

  1. Be consistent. If you do something a certain way, do all similar things in the same way.
  2. Use explanatory variables.
  3. Encapsulate boundary conditions. Boundary conditions are hard to keep track of. Put the processing for them in one place.
  4. Prefer dedicated value objects to primitive type.
  5. Avoid logical dependency. Don’t write methods which works correctly depending on something else in the same class.
  6. Avoid negative conditionals.

Names: “Intuitive”

The following are simple rules I use for creating good names, whether it is for functions, variables, arguments, classes, or packages. Names are everywhere in our code, so we better do it well and consistently.

Naming Conventions

I mainly code in Python and C++, and these naming conventions work for both. We use snake_case.

Update

I’ve changed my mind. Just be consistent with Google C++ naming conventions. See Google Style Guide.

source: notes/naming-convention.csv

Source: Taken from styleguide

Do not mix up functions and classes. One is an action, the other is an object.

Classes and Objects: ALWAYS start with a noun. Ex: Customer, Account, AddressParser.

Methods: Methods ALWAYS start with a verb. Ex: post_payment(), delete_page() or save()

Use Intention-Revealing Names

When choosing a name, choose one that clearly reveals intent. Choosing good names takes time but saves more than it takes.

As a general benchmark, if a name requires a comment, then the name does not reveal its intent.

BAD:
	int s;//time elapsed in seconds
GOOD:
	int time_elapsed_in_seconds;
	int file_age_in_days;

Use Descriptive Names

Don’t be afraid to make a name long if it’s necessary. A long descriptive name is better than a short enigmatic name. A long descriptive name is better than a long descriptive comment. Don’t be afraid to spend time choosing a name. You should try several different names and read the code with each in place.

Use Pronounceable Names

“If you can’t pronounce it, you can’t discuss it without sounding like an idiot”. Use pronounceable names so you can remember them more easily.

BAD:
  int tmspins;

1GOOD:
  int timestamp_in_seconds;

One Word Per Concept (TODO)

I should really be using one word per concept. It’s confusing to have fetch , retrieve and get as equivalent methods of different classes.

Use get

Use push

Consistent Names (especially for functions) TODO

includeSetupAndTeardownPages

includeSetupAndTeardownPages

includeSetupAndTeardownPages

includeTeardownPags

Other Recommendations

Avoid Disinformation

Don’t leave false clues that obscure the meaning of code. For example, don’t refer to a grouping of accounts as an account_list unless it’s actually a List.

Make Meaningful Distinctions

Look at the code below. How are we supposed to know which of these functions to call?

1BAD:
2  getActiveAccount();
3  getActiveAccounts();
4  getActiveAccountInfo();

Use Searchable Names

If a variable or constant is used at various places in a body of code, it is imperative to give it a search-friendly name. Single-letter variable names i, j, k, are fine if they are used as a loop counter and if their scope are very small and no other names can conflict with it.

Tip

The length of a name should correspond to the size of its scope.

Avoid Fun Names

I know, my videos are intended to be funny and all, but if names are too clever, people reading the code won’t get it. I will also probably forget about the joke!

Say what you mean. Mean what you say.

Functions: “Modular Programming”

Here are the recommendations for functions.

Small: Functions should be around a maximum of 20 lines. If the function is too long, break it down into smaller functions.

Do one thing: Functions should do one thing. They should do it well. They should do it only.

  • *(not sure about this) Prefer fewer arguments: The ideal number of arguments for a function is zero. More than 3 arguments require very special justification, and then shouldn’t be used anyways.

When a function seems to need more than 2 or 3 arguments, it is likely some of those arguments ought to be wrapped into a class of their own. Consider the following 2 examples:

Circle make_circle(double x, double y, double radius);
Circle make_circle(Point center, double radius);

The Stepdown Rule

We want code to read like a top-down narrative. “We want every function to be followed by those at the next level of abstraction so that we can read the program,d descending one level of abstraction at a time as we read down the list of functions. This is the Stepdown Rule.

Comments: “Less is More”

Comments are at best, a necessary evil. Comments are failures to express ourselves in code.

Always try to explain yourself in code

BAD:
//Check to see if the employee is eligible for full benefits
  if ((employee.flags & HOURLY_FLAG) && (employee.age > 65))
GOOD:
	if (employee.isEligileForFullBenefits())
 
  1. Don’t be redundant.
  2. Don’t add obvious noise.
  3. Don’t use closing brace comments.
  4. Don’t comment out code. Just remove it.
  5. Use as explanation of intent.
  6. Use as clarification of code.
  7. Use as a warning of consequences

Source code structure

  1. Separate concepts vertically.
  2. Related code should appear vertically dense.
  3. Declare variables close to their usage.
  4. Dependent functions should be close.
  5. Similar functions should be close.
  6. Place functions in the downward direction.
  7. Keep lines short.
  8. Don’t use horizontal alignment.
  9. Use white space to associate related things and disassociate weakly related.
  10. Don’t break indentation.

Design rules

  1. Keep configurable data at high levels.
  2. Prefer polymorphism to if/else or switch/case.
  3. Separate multi-threading code.
  4. Prevent over-configurability.
  5. Use dependency injection.
  6. Follow Law of Demeter. A class should know only its direct dependencies.

Objects and data structures

  1. Hide internal structure.
  2. Prefer data structures.
  3. Avoid hybrids structures (half object and half data).
  4. Should be small.
  5. Do one thing.
  6. Small number of instance variables.
  7. Base class should know nothing about their derivatives.
  8. Better to have many functions than to pass some code into a function to select a behavior.
  9. Prefer non-static methods to static methods.

Tests

  1. One assert per test.
  2. Readable.
  3. Fast.
  4. Independent.
  5. Repeatable.

Code smells

  1. Rigidity. The software is difficult to change. A small change causes a cascade of subsequent changes.
  2. Fragility. The software breaks in many places due to a single change.
  3. Immobility. You cannot reuse parts of the code in other projects because of involved risks and high effort.
  4. Needless Complexity.
  5. Needless Repetition.
  6. Opacity. The code is hard to understand.

Python Specific

Docstring format

"""A one line summary of the module or program, terminated by a period.

Leave one blank line.  The rest of this docstring should contain an
overall description of the module or program.  Optionally, it may also
contain a brief description of exported classes and functions and/or usage
examples.

Typical usage example:

  foo = ClassFoo()
  bar = foo.FunctionBar()
"""

C++ Specific

If Statements

Structure

There must be a space around the if and else keywords, and there must be a space separating the condition list and the opening curlly-bracket. Curly brackets must be on the same line as the condition list.

if (a == b) {
 
} else if (b == c) {
 
} else {
 
}
 

Always use curly brackets, even if the code within the if statement is one line.

Header Files

In general, every .cc file should have an associated .h file. There are some common exceptions, such as unit tests and small .cc files containing just a main() function.

The #define Guard

See Macro All header files should have #define guards to prevent multiple inclusion. The format of the symbol name should be <PROJECT>_<PATH>_<FILE>_H_.

To guarantee uniqueness, they should be based on the full path in a project’s source tree. For example, the file foo/src/bar/baz.h in project foo should have the following guard:

#ifndef FOO_BAR_BAZ_H_
#define FOO_BAR_BAZ_H_
 
... 
	
#endif  // FOO_BAR_BAZ_H_