Tabs vs. Spaces

Let’s take a look at the glorious tabs vs. spaces war. This discussion is famous amongst all skill levels of developers and it seems that noone can really convince the other side. People have different opinions on why one side is better than the other and cannot unanimously agree on one style. I think one of the main reasons for this problem is that the discussion is always about 100% tabs vs. 100% spaces instead of looking at an alternative approach: Using both.

Both? Are you out of your mind?

At first it might sound weird, but we’re not just going to randomly insert a different indentation character whenever we want to. There is going to be a ruleset and that ruleset will be well defined. That means by going hybrid, there are no discussions needed for when tabs or spaces should be used, as every situation will be clearly covered by those rules.

Which rules, exactly?

  1. Tabs for semantic indentation
  2. Spaces for presentational alignment

Semantic indentation

Relating to meaning in language or logic.

Semantic indentation is required when the whitespace has a meaning in the given context. Note that meaning doesn’t necessarily imply that it is needed for the compiler to process the code as in the case of Python e.g., meaning can simply refer to an indented block of code, let’s say a for loop, where the body of the loop is semantically different from the surrounding code and therefore is indented.

for {
	// This is semantic indentation: Use tabs.
}

Semantic indentation should be performed as the very first step, using tabs.

Spaces would need to be repeated multiple times to represent a single meaning. This is inefficient for disk space and therefore code parsing, let alone the fact that doing so doesn’t give us any benefits in the first place. Or when was the last time that you used 4 square brackets to represent an array in JSON?

[[[["Behold the new JSON standard!"]]]]

Why use more when you can do it with less?

We also get the added benefit of letting every team member be able to adjust the tab width and therefore personalize how much pixel space he or she would prefer to be used for a single tab. This can heavily improve readability for a person that is used to very different widths on his or her monitor. Normally, if you used tabs 100% of the time, this argument would be held up against using tabs because it can break the alignment of your code. That is exactly why we are going to define separate rules for alignment.

Presentational alignment

The proper positioning or state of adjustment of parts in relation to each other.

Presentational alignment refers to positioning different parts better in relation to each other and does not convey any meaning. It will make the code look better but the whitespace doesn’t convey that the code is different from the surrounding code, thus being only used to align parts with each other for presentational purposes.

type User struct {
	// Note how we're using tabs to indent the struct
	// and spaces to align the name of the data type.
	ID   string
	Name string
	Age  int
}

Alignment should be used after semantic indentation and should be done using spaces. The reason is that alignment requires precise positioning on a monospace font and the tab character can’t do that because it has dynamic width.

Your team members will thank you because they can finally change the indentation width to something they like and it won’t break the alignment of the code.

Conclusion

Rather than going full tabs or full spaces, consider using a hybrid approach where each character does what it’s best at and therefore combining the best of both worlds. I have been using this system for as long as I can remember and I never had a problem with it. For me, this is the de facto standard nowadays and the more people start switching to this system, the better. Amen.