Never use hard tabs

Update: This post has been updated to address some of the claims in the comments. Please note that most of these claims are wrong :)

As there seems to be some confusion when hard tab characters (ASCII code 9) are appropriate in source code files here is a rule:

1) Never use hard tabs

1. 1) Unless your source code is hard tab sensitive (only such format I know is Makefile)

1. Reasons not to use hard tabs

  • Due to legacy, different text editors treat hard tabs different. UNIX text editors prefer hard tab is 8 spaces, Windows text editors and IDEs (Eclipse) prefer that a hard tab is 4 spaces.
  • The hard tab length agreement between different text editors cannot be reached
  • The hard tab length agreement between people cannot be reached
  • Thus, hard tabs may break source code readability and editability if there is more than a single person editing the file. They will open the file in an editor with different tab settings, edit it and next time you open the file it is ruined and all indentations are wrong.
  • This is even worse on white space sensitive languages (Python, CoffeeScript) as this might actually cause syntax errors or programming logic errors

However, you can avoid this problem in the first place if you do indentation using soft tabs (spaces) instead.

Even if you were the single person in the world editing the text file, even you might switch the text editor in some point and accidentally shoot yourself in the leg.

2. Using soft tabs for indentation and having no hard tabs should not be a problem because

  • All text editors can convert tabs to spaces in fly, when editing the file. Please note me if there are commonly used editors, besides Windows Notepad, which doesn’t do it yet.
  • Text editors usually have different settings to tab key length and indentation settings. The latter is what you really want to adjust.

3. Pseudo-arguments for using hard tabs

  • It makes the file size smaller: you really care about those twenty bytes on your gigabyte hard disks?
  • This one I made up: spaces count toward the file size in web stuff, because visitors download the files. However if those bytes really matter you that much you should be using a minimizer in the first place.
  • I like them arguments…: rationale not involved
  • The change resistance in human nature

You might have a legacy software project having its legacy style guides. If the project big, e.g. Linux kernel, the switching cost may be very high and not affordable. However, even with this kind of codebase, you can gradually replace hard tabs away.

4. Style guides (updated)

Hard tabs are required only in Makefile syntax and preferred only in Go style guides. This is because people have learn by experience that hard tabs cause mess when working with other people.

5. Tab character is not semantically the same as indent level (updated)

There is no style guide or coding conventions saying that the tab character should the indent. This assumption is easy to make because it allows you to stick your head into a sand, ignore the surrounding world and by singing “let the users pick their own tab width” mantra. However, though a cunning idea, this perceived simplicity causes compatibility and co-operation issues which this post tries to highlight.

6. The user should choose to their own tab width (updated)

To choose your own preference is the rationale many people claim is the reason for indentation by tabs. “Let the users pick their own preference for indentation” However if you indent to work with other people the recommendation is to stick to the programming language recommendation. This way people can be more easily pick up the codebase.

There is nothing gained by having “user chooseable indentation width by adjusting tab character width”. The most used indentation width is 4 spaces anyway, so it is extra effort to maintain the freedom to have a user pickable indent width number instead.

Try to go to tell some old UNIX admin that they must adjust their editor tab width (see below).

7. Tab width is 8 spaces and don’t mess with it (updated)

People who use tabs as indent assume tab one tab = one indent and they can freely adjust the tab width, so that the indentation looks nice. However

  • By legacy, the tab character width is 8 spaces and most of the software out there makes this assumption. If you use any other value for tab width you are breaking this legacy social contract and you are making it for other peoples more difficult to work with your project.

This really limits the ability of using tabs as indent, because 8 spaces tabs often don’t make sense as indent (exception in system style C programming like with Linux kernel).

It’s ok if you work with the code in only one text editor alone where you have this one setting for tab width and that’s the only setting in the world controlling the tab width in your source code project. But when someone else must read or edit the code

  • Others must adjust tab width to make your code more readable
  • Adjusting tab widths from 8 spaces might be very difficult when working with other toolchains (e.g. you are viewing the code in terminal using cat)

Also in the languages where the recommended indentation level is only two spaces it would make it little funny to use one tab character just to have two spaces.

8. Tabs cannot be used to format code multi-line functions (updated)

Some people prefer to format long argument lists like this. A Python example which would break because of mixed tabs and spaces if tabs are used as indentation

call_a_function(argument,
                very_long_argument="something",
                even_longer_argument="something_else)

 Or in C

   if (first condition
       second condition)

9. Text editors

If you are a text editor author, make sure your text editor ships with hard tabs turned off by default, especially for whitespace sensitive languages if you vary tab policy by file type.

Note that this blog post, and the situation, could have been avoided if

  • All text editors would have sticked to soft tabs by default
  • All text editors would have sticked to a hard tab is 8 spaces by default

But in some point (when?) someone (who?) decided to make our life little more complex.

10. Tools for managing hard tab policy in your software project

 Subscribe to RSS feed Follow me on Twitter Follow me on Facebook Follow me Google+

44 thoughts on “Never use hard tabs

  1. Thank you! Now I have a nice place to point some hard headed friends to =)

  2. “The hard tab length agreement between people cannot be reached”

    This is actually a reason to use hard tabs. Most editors allow changing the length of hard tabs, and this way everybody can use the length he likes – 2, 4 or 8 spaces – without forcing all other people working on the same project to use the same setting. As long as no creative formatting is added, but every tab represents just one level of indentation, indentation never gets screwed – regardless of the visible length of tabs.

  3. Tommi: Just turn off that setting in your editor and if you never need to know about it you’ll be a happier person :)

  4. Lew: That would imply people don’t mix tabs and spaces. I don’t see how that could not happen in real life. It is so much simpler solution just to use spaces. Also all sane programming languages recommend indentation length, so you don’t want to change it, especially per person basis. That would just create an insane mess.

  5. Mikko: I agree with Lew. It’s not that hard to avoid mixing tabs and spaces – that’s what I do. You miss some benefits, like aligning arguments in multi-line function calls, but there are better ways to format anyways.

    If everything is a hard, then you can choose what width of indentation you like to see. It doesn’t matter how you view the document, because column and line numbers are the same.

  6. >if you do indentation using soft tabs (spaces) instead.

    Note that spaces are spaces, not “soft tabs”.

  7. Pingback: In the News: 2012-05-13 | Klaus' Korner

  8. Mikko: People usually don’t mix tabs and spaces at the beginning of the line. And if they would try, Python would force them to stop it.

    In our own projects, I and my coworkers indent all the code with tabs, in all used languages. Most of us prefer displaying tabs as 4 spaces, but at least one uses 8 – and this works perfectly, without any problems.

  9. Totally agree with LEW21. Any half decent editor that you would use to code with allows you to set your own tab length.

  10. Personally in my own projects I prefer tab symbols over spaces due to semantic reason: spaces are for word splitting and tabs are for line indent.
    4 spaces (not soft tabs as they’re do not have tab behavior!) become real headache when somebody decides to be ascii-artist.

  11. I agree with LEW21. In 15 years of programming various languages (COBOL, C++, Visual Basic, Delphi, SQL, Java, Ruby, etc, etc) on teams of various sizes (1 to 50), I have *never*, I repeat, *never*, encountered a problem using tabs. I just don’t understand why there has to be such lines drawn in the sand. Never do this. Never do that. You’d think that some people happen to know absolutely everything.

  12. The Go language recommends using tabs (see http://golang.org/doc/effective_go.html under formatting), and the automatic code formatter gofmt will format your code to use them as well.

    I personally don’t have a problem with either, I’ll use whatever is recommended by the language I am using. So far the only language that’s given me some indentation problems is Haskell.

  13. While we are at it, we should tell everyone what editor to use, or what religion to subscribe to.

    In most worth while editors, we can control the *visual* depth of the hard tab while keeping the actual character count down.

    The 20 bytes you consider saving leads me to believe that you have not worked on a big project. Tens of thousands of lines of code using spaces over hard tabs is A LOT of wasted space.

    Lets also consider the memory the editor requires to open the files. More characters per file = more memory to the editor.

    Yes, you get some benefits with spaces like making sure that parameters can line up across multiple lines. But this is a worthwhile loss for the consistent lining up of real indenting.

    Do you still wrap your code at line 80? Seems like a waste of that big monitor…

  14. There is a lot of confusion between the use of spaces and tabs. I see it that way :

    1) Use tabs to indent your code (and let people decide if they prefer to see tabs as 4-spaces or 8-spaces, I hate reading code in 2-spaces). It’s better in terms of semantics, memory space and user configuration. And it’s easier to (un)indent code with just TAB/backspace.

    2) Use spaces when you align your code, that way it won’t break, Here I’ll show you, paste this in a code editor:
    (__ = tab, . = space)

    class Foo(object):
    __def foobar(self):
    ____var1………..=.value1
    ____long_var2……=.value2
    ____very_long_var3.=.value3

  15. Another example of tabs/spaces, this time aligning the arguments of a long function. Again paste this in a fixed-font editor:

    void foo() {
    __callToFooBar(arg1,
    __………….longArg2,
    __………….arg3,
    __………….veryLongArg4
    __);
    }

  16. LEW21 is right: the *obvious* reason to prefer tabs is that they have a semantic meaning – 1 tab equals 1 level of indentation, and let the editor display the right amount of space as configured by the user.

  17. I always use hard tab before, until I switch to python. Now hard tab is forbidden in my computer!

  18. Pingback: Sublime Text 2 tips for Python and web developers

  19. This post is wrong in so many ways. Using spaces for indentation is like using a certain number of space characters to centre the title of a Word document — stupid as hell. If you use real tab characters, then:
    1) One character represents one level of indentation.
    2) People can configure their editors to use whichever physical width of indentation they like, people like anywhere from 1-8 space-widths and they should be able to choose for themselves.
    3) You never end up with screwed up indentation because you deleted three space characters by accident instead of four, etc. This kind of thing happens to me regularly when working on soft-spaced projects.
    4) You actually do save space, on disk as well as over the network.

  20. Wow. These comments are saddening. Tab is a horrendous character and I wish Python forbade it outright.

    I may be able to configure tabs in my editor, but in my terminal, my web browser, my email client, my IRC client, and lordy knows where else, tabs are still 8 columns and code is super ugly. I’ve seen plenty of code that’s wrapped at some reasonable width in the author’s editor, but becomes hilariously unreadable when all its indentation suddenly doubles in size in some other medium.

    I’ve also had enough problems trying to combine tabbed and untabbed code, move my cursor through tabbed code, half-indent tabbed code (not in Python, of course, but in some media it’s useful), etc etc. It’s easy to say “don’t mix tabs and spaces, duh”, too, but harder to actually make people do that, especially when they can’t easily tell that they’re doing it. Invisible wide characters are an annoyance I don’t want to have to deal with when I’m writing code.

    Tabs don’t let me use whatever size I want; they make the indentation *8 columns* and tell me that changing it to something else is my problem. Very few people would ever use 8 spaces to indent. So why use tabs, which is effectively the same? If reading code with an indent size you don’t like is really such a problem in your life then you can write a one-line git filter—and the code will actually look the same for you everywhere.

    I’ve yet to find a serious practical reason for using tabs. Semantics of plain text? Size on disk of your whitespace? Human beings who can compromise on all manner of other code style differences but cannot abide 4-column indentation? How is any of this an acceptable reason to make my plain text inconsistent to read and tricky to edit?

  21. I would say the opposite–especially for Python–always use hard tabs. Aside from the benefit of having the source code indented to your preference, copying code snippets is safer. Soft tabs should be forbidden, or indent should have been defined in the language as one of (2 spaces, 3 spaces, 4 spaces, etc.).

    I like the correspondence 1 tab = 1 level of indentation. As mentioned above, don’t use tabs for alignment.

  22. Indent recommendation for Python is 4 spaces and Python correctly picks up space based indentation. Also I prefer that the code look and feel on the same among fellow project peer members. The argument os “pick up your own tab width it just a way to have less conforming codebase and extra time of adjusting tab sizes in different applications (terminal, text editor, web based editor, and so on).

    When you use spaces for indentation the code will look correct, no matter which editor/application you use to view it.

  23. I’m not saying that’s bad to use spaces but please stop saying to never use tabs because the arguments are ‘ridiculous’. Some points in this article are easily refuted and even are true also for tabs. If you are not developing an open source project some of the points of this article don’t even make sense. Please do a decent ‘pseudo-arguments for using tabs’.

    Also, I can easily add some ‘dumb’ arguments like “using spaces with a non fixedwidth font and ask if spaces can ‘really’ do indention” and converted to a ‘strong’ argument. Using tabs or spaces depends on your development environment and your team. It’s not dependent on legacy environments or the environments of people that make the style guides.

  24. The answer is actually very simple. Spaces are 100% portable, tabs are not. End of discussion.

    There are tools out there that don’t understand tabs at all. I have used a file compare tool that turned tabs into boxes. Trying to review code changes that had a mixture of tabs and spaces basically meant viewing code with random indentation.

    I know of no tool that has any problems with spaces.

  25. I totally agree with LEW21 also. Different editors depicting tabs differently does not affect one tab = one indent. Nobody in their right mind mixes tabs and spaces.
    You can use spaces if you want, but let me use tabs. It is annoying when people try to enforce something like this as a “rule”.

  26. I disagree with this, I find all the arguments quite weak against tabs. Editors will display tabs correctly all the time, there is only one rule that you need to follow, hard tabs for indentation and spaces for alignment.

    On my experience I have found soft tabs a time waster:
    - Copying an pasting code from different source is terrible as some people will use 2, 4 or 8 spaces. Plain tabs avoids this problem.
    - removing indentation is a lot more work, you have to delete several spaces instead of just one tab.

  27. I can’t agree more that tab IS the indent character and only it SHOULD be used as an indent character. Simple rule of thumb – indent with tabs on the left side, indent with spaces on the right side and between the code in the middle. That is the one and only way any code will look great in any editor, in any environment with any user preferred settings.

  28. The whole discussion on “tabs vs spaces” should be rethought after a question most obvious in 2013:

    * In modern coding environments, wouldn’t it be better (in terms of readability and performance) to display the code in proportional fonts? *

  29. @Alex: No, it won’t.

    Using proportional font, you can never get non-identation alignments right, as you have even less control on the choose of font of developers, e.g.
    Try to align the equals sign if you are using proportional fonts that will be portable across different fonts or env:

    String aString = “foo”;
    String anotherStringWithLongerName = “bar”;

    You simply can’t do it right

    Another example is aligning line wrapping, as mentioned above. e.g.
    callingLongMethodWithLongName(someVariable,
    anotherVariable,
    yetAnotherVariable);
    (the above should align well in fixed-width font)

  30. I do agree that, it will be super great that people can follow the rule that: Use tab for indentation, and use space for alignments.

    e.g. ( >>>> as tab, ____ as space)

    >>>>void foo(String aVariable
    >>>>_________String anotherVar) {
    >>>>>>>>int anInt_____ = 0;
    >>>>>>>>int anotherInt = 0;
    >>>>>>>>callingMethodWithLongName(anInt,
    >>>>>>>>__________________________anotherInt);
    >>>>}
    (this should align well with monospace font)

    That’s really really good if all developers can follow this rule and the code should be great to read under most, if not all, tab size setting.

    However, let’s face the truth: When working in group, you can hardly control the habit of developers. Once you got a developer that, maybe unintentionally, used tabs to do those line-wrapping alignment, the source code just messed up and become hard to read. It is now even more difficult to follow as Tab and Space need to be mixed and used in different yet similar situation. Take a look in Sun’s JDK source code, even in such a big commercial project, the indentation character is still mixed irrationally. How can you expect all developers are going to be that careful in doing the indentation?

    Yes, you can say that should be part of code review to fix and avoid such kind indentation/alignment issue. But not all code review product is doing well in displaying invisible whitespace character (e.g. Crucible). Even it does, I’d rather spend my time looking at other issue, instead of keep on checking such kind of “invisible” alignment issue.

    I am not saying using Tab to do indentation is wrong. However it will only work if every developer is following that strictly but that is simply hard to enforce given the rather complicated “indentation” vs “alignment” practice.

  31. I don’t think tab indentation adversely affects projects with multiple collaborators, as seems to be your main point against hard tabs.

    A case in point. The Linux kernel style guide says the following:

    “Outside of comments, documentation and except in Kconfig, spaces are never
    used for indentation.”

    The project is over 15 million lines of code, with hundreds of contributers. They seem to do just fine.

    At the end of the day, I think consistency is paramount. You’ll never convince the entire world to use one or the other. The worst transgression is to mix the two. I prefer hard tabs, but if I’m editing a file that has been created with soft tabs, then I will respect that decision and continue to use soft tabs.

  32. All the (Java) projects that I have been on have more or less a mix between tab indentation and space indentation. Once a piece of code has been written in a given style it tends to stay that way unless it’s refactored or rewritten anyway since “fixing” the indentation style makes it hard for the VCS to indicate which lines of code actually did change.

    The choice of style is not the biggest problem in the world and it rarely causes any problems as such. Maybe because everyone has their Eclipse set to render tabs as four spaces anyway.

    That being said, I’m strongly in favour of using spaces and I have yet to meet a senior level SW engineer who disagrees with this viewpoint.

  33. Pingback: Sublime Text 3 for Python, JavaScript and web developers

  34. Thanks for this post, I was wondering for a while why most open-source projects I know are fully indented with spaces. Now I know :).

  35. Pingback: Changing Tab Indentation in Sublime Text 3 | TLDR Dev Notes

  36. The hard tabs vs soft tabs argument is moot, there are too many people out there who have no idea how to use their text editors to :set tabstop=4.

    Now, instead the world is a better place, totalitarian nirvana has been reached, hard tabs have been eradicated and we have the 4 spaces vs 3 spaces and 2 spaces indentation arguments.

    No, really…

    I like 3 space indents it’s a nice compromise between 2 and 4.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>