17 min. read

What is discussed here

  • What is formatting
  • Formatting Text
  • Formatting code
  • Conventions
  • Ordering
  • Formatting tools

Code formatting

What is code formatting?

  • Aligning of identations and spaces.
  • Ordering code.
  • Naming.
  • Commenting.

In this post I describe how to think about code formatting and how to do it correctly.
Spoiler - There is more than 1 correct answer!

Code as text

Code is a text that tells the computer what to do - what instructions to perform.
In high level code it’s abstracted in special keywords with expressions, clauses and blocks.

Before we discuss elements of code I want to discuss the concept of Code as Text.
To simplify writing code - a special language is used.
The most popular languages are based on the English/Latin language.
Keywords for example: if, for , while, with, etc…

Formatting Text

To understand how to format code we should consider how to format regular text.
Formatting creates a better reading experience.
If we kept everything untidy it would look very chaotic.

Let’s take this silly email:

There are error identations, different symbols, grammer mistakes and non aligned text.

Elements of alignment and formatting

The idea

When we write something we want to be clear as possible.

Elements

  • Direction of language -
    Right to left, up-down or left to right.
    The direction will set up the flow the reader will follow.

  • Headlines -
    Summarizes ideas or make it more interesting to read.

  • Paragraphs -
    Splitting ideas and information into different text blocks.

  • Spaces and Identation -
    White space splits better between ideas and paragraphs.
    Identation gives us a clear hierarchy of information.
    No spaces:

    Spaces:

  • Symbols -
    All text are basically familiar glyphs that we know how to read.
    There are symbols that we add information but are not actually read phonetically.
    Read this sentence:
    THE CAT HAS GONE!
    If you didn’t scream it or imagined a higher intense voice, you probably didn’t read it.

    • Uppercases and the exclamation mark are used to make emphasis on the text.
    • More common symbols: ? , @ , $ , % , etc…
  • Styling -
    Styling texts adds better emphasis on ideas.

  • Splitters -
    Splitting text with actual splitters and not just white spaces or identation gives us a more clear guidance that a section has been ended or the idea has shifted.
    For example:

    The line beneath the headline gives us clear information that the pervious section has ended.

  • Font -
    Fonts may deliver a different idea based on their graphical design.

  • Repeating styling / Conventions -
    When we use a certain style we expect to see this style more often - if a convention breaks and we do not deliever in the same manner the reader would be very confused.
    In general - No consistency.
    Few examples on how to stay consistent:

    • Lists.
    • Same colors
    • Headlines.
  • Templating -
    Prior to beginning writing, deciding on a template can help us deliever more consistent text.
    A good example for it would be a presentation, When working with Powerpoint it lets you select a template for the presentation.

    The main idea in a template is to stay consistent.

Elements of reading

The idea

Alignment elements clears noise around the idea and allow us to split an idea into smaller points.
Reading elements help us introduce variaty and guide the reader to the right information.
However, there are certain elements that - when misused - create a worse reading experience.

Elements

  • Major eye catchers -
    When reading our eyes tend to jump to locations that we may precieve as more important.

    • Images
    • Tables
    • Quotes
      Too many images create an information overload.
  • Eye jumping -
    When you seek information your eyes tend to jump from paragraph to paragraph.
    Either reading the first sentence to get a clear idea or trying to glance at headlines or images.

  • Table of contents -
    TOC allows us to summarize and present a smaller view of our whole text.
    In general - a smaller summary of the text.

  • Splitters -
    If the text has been splitted correctly we can jump to the correct information that we seek.

  • Known vocabulary -
    When seeking something specific we analyze the text to see if a certain word is presented.
    For example:
    If I want to find which movies a director has made I’ll look in the correct section in the table of contents.

  • Ctrl + F friendliness -
    Headers and the right vocabulary helps the reader to find information quicker.
    If the text supports finding keywords more easily and in the right location it would be even quicker to find it using Ctrl+F.

Formatting code

Treat code as text

The same ideas that we use to write texts, books, papers, etc…
Can be - and should be - used to write code.

Elements of alignment in a masked code

In this exmaple I maksed the actual code.

Important code - implementation details.
Details such as variable initialization, functions calls, etc...
Common code such as for loops, loggins, etc...

So what elements are there in this code?

Identation

Identation is spaces or tabs in a line.
Identation keeps the hierarchy very clear.
It’s one of the most improtatnt tools for formatting the code.

No identations:

1
2
3
4
5
6
7
8
9
var hasAbovePiece = !isUpSide;
if (hasAbovePiece && y - 1 >= 0)
{
var abovePiece = puzzle[x, y - 1];
if (abovePiece.Down != JigsawType.NotSet)
{
piece.Up = negateType(abovePiece.Down);
}
}

Identations:

1
2
3
4
5
6
7
8
9
var hasAbovePiece = !isUpSide;
if (hasAbovePiece && y - 1 >= 0)
{
var abovePiece = puzzle[x, y - 1];
if (abovePiece.Down != JigsawType.NotSet)
{
piece.Up = negateType(abovePiece.Down);
}
}

Spaces

Spaces seperate between implementation details.

No spaces:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Menu:
def Execute(self):
wantsToPlay = True
hasPlayed = False
while wantsToPlay:
userInput = input('Please Enter to Begin, C to exit: ')
if userInput == 'c' or userInput == 'C':
break
categories = self.__questionsGenerator.Load()
game = Game(self.__activePlayers, categories, self.__pointsToWin)
game.Run()
hasPlayed = True
if hasPlayed:
print('Thanks for playing!')
else:
print('Hope you\'ll play next time!')

Spaces:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Menu:

def Execute(self):
wantsToPlay = True
hasPlayed = False
while wantsToPlay:

userInput = input('Please Enter to Begin, C to exit: ')
if userInput == 'c' or userInput == 'C':
break

categories = self.__questionsGenerator.Load()

game = Game(self.__activePlayers, categories, self.__pointsToWin)
game.Run()

hasPlayed = True

if hasPlayed:
print('Thanks for playing!')
else:
print('Hope you\'ll play next time!')

Spaces help to create less strain on the eyes and the brain by seperating details.
This section for example:

1
2
3
4
5
6
7
8
9
10
userInput = input('Please Enter to Begin, C to exit: ')
if userInput == 'c' or userInput == 'C':
break

categories = self.__questionsGenerator.Load()

game = Game(self.__activePlayers, categories, self.__pointsToWin)
game.Run()

hasPlayed = True

The 3 ideas are:

  • Input.
  • Categories load.
  • Game running.

Common blocks

Each marked block consists of a ceratin information - we do not blend between them.
This is highly recommended by the principle Single responsibility.
Each “Block” contains a single general idea.

One of the most common blocks is - a Function!
Functions seperate implementation details by creating actions.

1
2
3
4
5
6
7
8
9
public void Main(string[] args)
{
var (ip, requestInfo) = ParseArguments();

var request = GenerateRequest(requestInfo);

var client = CreateHTTPClient(ip);
client.Send(request);
}

By using loops and if statements we create another block that is identified easily.

Pro tip: Make statements more visible.

That’s why I prefer to put spaces before and after statements and seperate brackets { } into new lines:

1
2
3
4
5
6
7
8
9
10
var race = character.Race; 

if(race == Races.Elven)
{
character.MaxManaPoints += 20;
}
else
{
character.MaxHitPoints += 20;
}

Brackets - { }

Brackets are symbols that seperate code into elements called Blocks.
A block of code not only seperate the code into ideas but in some languages defines the scope of variables.
So something inside a block isn’t “leaked” outside of the block.

C++ code for example:

1
2
3
4
5
6
{
auto myVariable = 3;
}
{
std::cout << "My variable is: " << myVariable << "\n";
}

This would produce a compilation error because we defined a variable out of scope.

New lines or not?

An endless argument is To put new lines or not?

Same lines:

1
2
3
4
5
6
7
var race = character.Race; 

if(race == Races.Elven) {
character.MaxManaPoints += 20;
} else {
character.MaxHitPoints += 20;
}

New lines:

1
2
3
4
5
6
7
8
9
10
var race = character.Race; 

if(race == Races.Elven)
{
character.MaxManaPoints += 20;
}
else
{
character.MaxHitPoints += 20;
}

The answer:
It doesn’t matter - what matters is to stay consistent.
If you use new lines - keep using new lines.
If you put them on the same line - Keep doing that.

RAII - Resource Acquisition Is Initialization

In C++ it’s even used as a technique called RAII.
By using the ctor and dtor as scope handlers we can manage resources more easily.
A common practice is using a mutex guard alongside the brackets.

1
2
3
4
5
6
7
8
9
10
11
12
13
void MyFunction(std::string playerName)
{
auto hasFound = false;
{
std::lock_guard<std::mutex> myGuard { mMutex };
hasFound = mPlayers.Find(playerName);
}

if(hasFound)
{
// Do code here
}
}

Locking should be minimzed as possible so if we only lock the mPlayers variable we should minimize the scope by introducing a block using the brackets.

Headers in code

Headers present ideas.
In code we have few definitions that act like headers:

Classes/Structs

1
2
3
4
5
6
7
/*
A monster is a Creature that has hostility.
*/
class Monster final : public Creature
{
// Code goes here.
}

The class defines a Monster which inherits the Creature class.
The final seals the class for overriding virtual methods.

Functions

1
2
3
4
public void PerformHit(float damage, IEnumerable<IDamageBuffs> buffs)
{
// Code goes here.
}

A function states:

  • What info is returned (In this case void).
  • What action is performed.
  • What parameters goes in the function.

By emphasizing the headers with spaces, clear identation and proper documentation we guide the programmer more easily in our code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
/// <summary>
/// A monster is a living entity in the game that is hostile to nearby players.
/// </summary>
public abstract class Monster : LivingEntity
{
protected bool mIsHostile = false;
protected LivingEntity mEntityToAttack = null;

public override void TakeHit(float damage, IEnumerable<IHitBuffs> accumelatedHits)
{
// Calculate hit...
}

/// <summary>
/// A monster is a living entity in the game that is hostile to nearby players.
/// </summary>
public virtual void DetectHostileEntity(IEnumerable<LivingEntity> nearbyEntities)
{
// Small tip: .Net 6.0 introduces a "***By" methods :)
var minDistanceEntity = nearbyEntities.MinBy(entity=> Distance(entity,this));
if(minDistanceEntity != null)
{
mEntityToAttack = minDistanceEntity;
mIsHostile = true;
}
}

/// .... More methods
}

Ordering elements in classes

When the code is ordered and a consistent order exists the reader can expect the same element in the same location for every class.
What do we order in a class?
In C# there are many elements that may exist in a class:

  • Field members
  • Ctors
  • Public methods
  • Protected methods
  • Private methods
  • Delegates and Events
  • Properties
  • Const and static members
  • Const and static methods
  • Inner enums/classes/structs.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
using System;

namespace Game
{
public class Hero : LivingEntity
{
public const int AdditionalHitpoints = 200;

private bool mHasUltiAction = false;
private Skill mMainSkill = null;

public Hero() { }

public event Action<float> OnHit;

public override void PerformMainSkill()
{
var isOnCooldown = HasCooldown(mMainSkill);
// .... Code
}

private bool HasCooldown(Skill skill)
{
// ... Code
}
}
}

Different languages has different styles and each language has its own culture of arrangment.
C# Has many elements therefore it’s a good example on how we order elements inside a class.

Prefer to put on top more common methods and as we go “deeper” in a file we get more implementation details.
Prefer to group everything so it would be easier to navigate throught the class.
Prefer to hide details and make the public interface as clear as possible.

Regions and splitters

C# allows the usage of region text processor:

These kind of regions are helpful to hide elements and focus on what’s important right now.

A more common and trivial approach is to use seperators such as comment lines:

I’m not advocating for any approach as the usage of splitters is very subjective.
As I stated already the preference is not important as long as - you’re consistent!.

Consistency is key.

Breaking consistency

When should we break consistency?
When we want to emphasise on an idea or make it more readable.

Lambdas

I still struggle today with the idea of lambdas especially when different languages and IDEs prefer different styles.
What I prefer is - READABILITY.
It means that I may alter the style to make it more readable but less consistent overall.

First example

This is a regular lambda, the common practice is to put { in the same line:

1
2
3
4
5
6
7
8
public void Main()
{
Func<int,bool> performCheck = (int num) => {
var result = false;
// Some checking code.
return result;
};
}

Second example

This example uses many nested elements.
Here I prefered to spread the lambda over new lines to focus on the banning user code.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public void Main()
{
for(int i = 0; i< 10 ;i++)
{
if(someCondition)
{
var bakaTitles = myList.Select(s=> s.Title).Where(title=>title.Contains("Baka"));
PerformOn(bakaTitles,
(title) =>
{
var user = FindUser();
if(user.Titles.Contains(title))
{
BanUser(user);
}
}
);

// Some code...
}
}
}

Formatting tools - automation

Integrated development environments such as ‘Visual Studio’ and tools like ‘Resharper’ automates the process of formatting.
So if you don’t use an IDE and want to auto format your code it’s recommend to use one.

Of course there are CLI tools as well, some examples:

  • clang-format for C++.
  • black for Python.
  • dotnet format for C#.

Consistency and Readablity are important characteristics for code as it decreases the time a programmer spends reading it.
The more you automate this process the better your code will look.

Thanks for reading!


Is this helpful? You can show your appreciation here: Buy me a coffee