Tabs Not Spaces
Coding styles have long been a heated topic of debate among programmers. The debate over using tabs vs spaces for indentation has probably been one of the more heated examples. Unfortunately it seems the wrong side has been winning. But it will never be over!
This one starts with the need to balance two competing goals:
- Make it easy to see groupings such as blocks or lists at a glance.
- Keep lines short minimizing eye movement and the need to scroll.
It is impossible to simultaneously optimize for both of these goals. Big fat indentations make it easy to see at a glance exactly which code is grouped with which but they also make lines wider increasing the amount of eye movement and scrolling which is necessary. The result will always be a compromise and the best compromise will always vary from person to person and equipment to equipment. It might vary due to the size and resolution of a display. What works best might vary due to font or text and background color. It might vary due to the eyesight of the reader. And most of all it will vary because of personal preference. We just are not all the same person.
When using spaces to indent the author chooses a specific number of spaces and for every level of indentation they start the line with that many space characters. This leaves the reader with no way to adjust the physical width of the indentations on their screen.
When using tabs the author typically uses exactly one tab character for each level of indentation. Depending on the software the reader is using there is usually an option where the reader can tell the software exactly how wide to display each tab character. In this way the reader gets to set the indentation width to exactly what works best for them while using their hardware.
Why would anyone ever prefer spaces?
A lack of discipline.
It can be easy to accidentally switch between the two and mixing has worse results than either tabs or spaces by themselves because it may still look right to the author but totally wrong to a reader who has a different tab width preference.
Your code editor should help you with this. Many code editors have an option to highlight the background of tabs and/or spaces a different color so that you may see which you typed and correct it. Or a more console based editor might have characters that it can display. Emacs for example has its whitespace-mode which will display a tab as ' » ' and a space as '·'. If your editor has no such feature it may be time to consider changing editors.
Lining up items within a comment.
This is not a good reason. The tabs vs spaces question is really meant to be about indentation. Indent your comment up to the point that it lines up with the code it describes. If you must line things up within the comment itself then use spaces inside the comment, after the line's starting indentation.
php
» /*
» $foo - holds number word pairs
» ··key·|·value
» ····1·|·'one'
» ····2·|·'two'
» */
» $foo = array();
Even so, be careful relying on things lining up within comments. Take the above example: if the reader is using a non-monospaced font it might not be possible at all to ensure that everything always lines up perfectly.
Lining up arguments in a multi-line function definition or items in a pre-defined array or other collection.
It is common to want to place the first item directly after the opening parenthesis or bracket then start the following line directly below that first item. With tabs one cannot align the second item with the first unless the number of characters in the definition before the first item happens to be a multiple of the tab width and even then it would only work for that specific tab width.
php
» $fruitlist = ["peach",
» » » » » » » » "pear",
» » » » » » » » "apple"
» » » » » » » » ];
» // or
» $fruitlist = ["peach",
» » » » » » » » "pear",
» » » » » » » » "apple"
» » » » » » » ];
Notice that in this example peach, pear and apple probably line up. The closing bracket however can never quite line up with the opening one. Depending on how many tabs are used it is either a little short or a little long.
php
» function Process(first,
» » » » » » » » » second,
» » » » » » » » » » third
» » » » » » » » » ){
Here the opening and closing parentheses probably line up just fine. Getting the items within the parentheses to line up however is not possible.
This may seem like a problem for tabs. It is the closest thing to a good reason to use spaces. But it certainly can be worked around without switching to spaces and locking everyone into the same indentation width.
There is a mistake in the thought process that leads to these examples. Lining these up at all depends on the tab width. Here I am representing a tab with " »" so that's a 2-space wide tab. If these were real tabs and the reader had their tab widths set to 4 spaces wide for example all those lines would begin twice as far to the right. Nothing would line up with the first line at all.
This mistake came from mixing the concept of indentation with layout. Much like how modern HTML and CSS strive to keep meaning and layout separate we should strive for the same thing in code. Tabs should only be used for indentation. Towards that end we can rewrite our examples as so:
php
» //Just right!
» $fruitlist = [
» » "peach",
» » "pear",
» » "apple"
» ];
» function Process(
» » first,
» » second,
» » third
» ){
Here it is plain to see that the array items are contained within their array because they are indented in from it. Likewise it is plain to see that the parameters belong to the function as they are indented from it. These things are all lined up with one another. There is not a lot of wasted horizontal eye movement or scrolling because they are only one extra level deep.
There are a couple of compromises. Starting the first item or parameter on a new line means a little more vertical scrolling. Vertical scrolling is not as bad as horizontal though so it is very much worth it. Also, the opening and closing brackets or parens are not on the same columns as one another.
Some people like to add yet another newline to put the opening parenthesis or bracket on the next line. This allows the opening and closing to line up.
I do not think this is worth it because that makes for even more extra scrolling. Also having the items and parameters indented already makes it pretty easy to see that they belong inside their containers. And if the bracket or parenthesis started on the next line it would either have to be lined up with the function or array declaration, making it less obvious that it is 'contained within' that definition as opposed to being a 'separate thought' or there would have to be two levels of indentation. One level just for the parenthesis or bracket and another for the content. That brings back more eye movement or scrolling.
php
» //Brackets line up but take an extra line
» $fruitlist =
» [
» » "peach",
» » "pear",
» » "apple"
» ];
» //Way too much whitespace!
» function Process
» » (
» » » first,
» » » second,
» » » third
» » )
» {
Tabs for indentation, spaces for alignment?
Another option some people prefer is "tabs for indentation, spaces for alignment." This lets the first parameter or item go back up on the definition line. Each following line starts with the same tabs as the definition line, then uses spaces to line up under the first item.
php
» $fruitlist = ["peach",
» ··············"pear",
» ··············"apple"];
This has a couple of problems. First, it isn't widely supported by editors; often it has to be enforced by a formatter after the fact. Without that, it's easy to end up with exactly the invisible mixing described above. Second, while the alignment does survive a change in tab width, the alignment itself is fixed-width. A long definition pushes every following line far to the right, and the reader can't shrink that the way they can shrink a tab. It gives back some of the flexibility tabs were supposed to provide.
People vary
I picked up a preference back in college of using three spaces for indentation. I chose this because the professor said he didn't care what we used, only that it was consistent. But my English teacher wanted 3 spaces to indent a paragraph. So naturally I tried that for code and it felt quite readable that way. Today 2 or 4 spaces are more common for space-indented code. I have run into some however who use as many as eight! For me eight was far too many. It made the code harder to read as I would get lost with all the extra horizontal eye movement and scrolling. But why take that ability away from someone who genuinely prefers eight or more?
Changing tab width
Personally, I work at the office on a desktop with a nice wide display. Occasionally I work on personal stuff at home on my own desktop with a similarly wide display. But most of the time I do my own projects on my phone which docks to my Lapdock. The Lapdock has a decent display but it is definitely more cramped than either desktop. It makes sense to use different tab width preferences between these devices. Occasionally I might even fire up an editor on my phone itself without the dock if I just need to make a quick edit. It really makes sense to drop the tab width on such a small display as lines need to be narrow to prevent a lot of extra horizontal scrolling.
I started out coding in an 80-character wide MS-DOS display. In my college days I used old laptops where 800x600 or 1024x768 was as good as it gets. We used a DOS based C++ editor in college years after the market switched to GUIs because it was still just fine for learning basic concepts and this way it saved students money. After college I did a lot of coding on a Sharp Zaurus Collie (now-obsolete handheld, kind of like a Linux phone without the phone) and even on my old Series 60 phone. I am not likely to use any of this old hardware today. But there is a whole community out there into retro-computing. Why make things hard for them?
Another thing that changed for me over the years is my eyesight. I had 20/20 vision and could easily discern even a 2-space indentation on that tiny Zaurus screen. The whitespace someone else might have needed to be able to easily read the code was using up scarce screen real estate. We all think we will stay young forever until we are not. Today I have to wear reading glasses. But I am lucky. What about people who have real vision problems? The more we can allow them to customize their displays the better.
Of course this advice is meant for the people who are actually setting the style for a project. When submitting code to an existing open source or work project the most important thing is consistency and one should always follow the project style guide.
When making a style guide one might want to define a maximum column width. Towards that end it would be good to define just how many characters a tab should count as when counting columns regardless of how wide it might display given an individual's tab width preference.
Who knows what hardware and software we will all be using in the future. The flexibility of tabs is a good thing. So remember, tabs are good for you and friends don't let friends indent with spaces.