Jens Alfke wrote a post of coding tips that includes this advice:
Don’t use tab characters in source files!
The world will never come to an agreement on whether a tab character indents 8 spaces or 4, especially on the Mac, where lots of Unix tools (and Unix source code) are hard-coded for 8. So since different people will have their tab-width preferences set differently, just don’t use tab characters in your source code if you want everyone to be able to read it.
In Xcode, go to the Indentation pref pane and uncheck “Tab key inserts tab, not spaces”. In Textmate, check “Soft Tabs” in the tabs pop-up at the bottom of the editor window. You won’t notice a difference in editing text, but your source code will now look properly indented to everyone.
No, no it won’t. Because now you are forcing your indentation preference on everyone else.
Let’s make one thing clear: tabs have no intrinsic size.. For example, he says “if…you view code that uses 4-char tabs for indentation…”. This is patently wrong: There is no such thing as a 4-char tab. Tabs have no width of their own; they simply say “move to the next tab stop”, and it’s up to the viewer application to determine where the next tab stop is.
Here’s my comment on his post, replying to one of his own comments (which, in turn, was a reply to somebody else’s comment about tabs):
Peter Hosey:
Jens Alfke:
And I find the “wrong” indentation level in files much less annoying than the “wrong” tab width, because the latter makes the indentation completely impossible to follow without reformatting.
But a tab is always the right width, because it’s the viewer who sets it, not the author. Indenting with spaces will look wrong when you move the code to someone who uses more or fewer spaces than you do; tabs don’t have that problem.
The problem comes when you use tabs to create columns. That’s wrong, because then the columns don’t line up when the tab width changes. That, I think, is where your objection originates. You should always use spaces to create columns.
Indentation, however, is the proper use of a tab, and tabs are the proper way to indent.
I’ll take his reply point-by-point:
Jens Alfke:
Peter: It’s not that simple. If the tab width is set to 8, as in all Unix-derived code (and all the Cocoa sources I’ve seen), then the editor uses a mixture of tabs and four spaces to get the 4-character indents.
What?
First off, no source code contains a tab width set to anything*. As I said, tabs have no intrinsic width; it’s your editor/viewer that assigns width to a tab. So, if a tab is 8 characters, it’s because you said so in the viewer application’s prefs.
And if you have set your tab width to 8, then what 4-character indents are you talking about? Are you trying to force such indents despite your setting the tab width to 8?
(There is one exception: If you use a method that has one parameter with a longer name than the first line of the message-statement, Xcode will sacrifice some of the indent in order to colon-align that parameter, resulting in spaces where there would otherwise be a tab. This is a symptom of its colon-alignment logic, which is described below. This only matters in 1%, at most, of Cocoa code, and 0% of other code; as such, this special case should not dictate indentation policy for all other code.)
So that code is going to look completely messed-up to someone with different tab settings.
Maybe so. But if you use nothing but tabs, then it will look perfectly correct to somebody with different tab settings. Let’s say you prefer 4-character indents, and they prefer 2-character indents. Your tab width should be set to 4, and his to 2.
If you indent your code with four spaces, then he will see two of his two-character indents (2×2). But if you use a single tab, then it will still look like four spaces (one indent) to you, and it will look like two spaces (one indent) to him, exactly as he expects.
But if you have tabs set to 8 and you view code that uses 4-char tabs for indentation, the indentation level is 8 characters, which is pretty ridiculous looking and makes most normal code fall off the right edge of the window. So a tab is absolutely _not_ the right width for me.
Here’s what I think you meant:
…if you view code written by somebody who set his tab width to 4 characters, despite preferring 8-character indents, so that he uses two tabs instead of one, then it will look ridiculous.
Which is exactly right, but more the fault of the programmer who does not set his editor’s Preferences to match his preferences than the fault of the tab character. The tab character is innocent in this; it was misused, and that’s what caused the problem.
(Moreover, nearly all code I’ve seen uses extra spaces for indentation. Xcode does this for you in Obj-C code, to make the colons line up. That stuff looks really awful if you change the indentation width.)
Actually, Xcode uses tabs to line up the colons. That’s wrong, and it’s why it looks awful. Xcode should use tabs until it matches the indentation of the start of the statement, and then continue with spaces. For example, if the first line of the statement is indented with two tabs, then every other line of the same statement should also be indented with two tabs, followed by spaces to align the colons. Xcode uses tabs; that’s what causes the messed-up alignment when you change the tab width.
Wrapping it up in a little bow
Here’s an executive summary of the issue. Hopefully this will make things fully clear.
- Programmers indent their code to indicate scope.
- For every additional level of scope, there is one indent. This rule is invariant.
- Different programmers have different preference for the width of an indent. Some prefer four characters; some prefer eight characters; some prefer two characters; and some (crazy people) prefer one character.
- Some programmers use one tab character (U+0009 HORIZONTAL TAB) per indent. This option is usually referred to as “real tabs”. The programmer defines his preferred indent width in the preferences, and the editor uses that width to define the width of one tab.
- However, this width is not saved in the file. This is useful, because it means that when you portage the file to another editor where the indent width is different, it will take on the new indent width (e.g. eight characters instead of four) with no modification to the file.
- Other programmers use one or more space characters (U+0020 SPACE) per indent. This option is sometimes referred to as “soft tabs”. The programmer defines his preferred indent width in the preferences, and the editor indents by inserting that many spaces.
- This width is saved in the file. Another editor will show the same width, which may not be the width that the other programmer prefers and expects. This is great if you want to force your preferences upon everybody else, but if you would prefer to avoid a formatting war, then everybody should use tabs and set the width that their editor will use for a tab according to their own preferences. Nobody need ever know that other people’s indents are different widths.
- Thus, tabs are superior because one tab = one indent, regardless of width; it has the right width for you (according to the width you defined in your preferences) and the right width for everybody else (according to the widths they defined in their preferences).
UPDATE 2008-11-29: See also the sequel to this post: Tabs vs. spaces redux.
* I’m aware that UNIX editors like vim and emacs support special meta-text that you can embed that will set the tab width, among other things. I consider this a cheap hack intended for people who do not understand the difference between tab and space indents, or for people who have to deal with those people. ↶