Spaces vs. tabs

Yesterday on Twitter, I came across this tweet/question from Paul Ford

Which sparked this response from me:

And then mostly forgot about it because I thought it was a fairly obvious thing. Spaces are the clear choice. Tabs are only good for one thing, keeping track of what you owe at the bar.

…but Twitter started alerting me to a number of likes, and so I decided to check out the larger conversation around the poll and was *shocked* to find out some people were actually voting for/defending tabs over spaces. So clearly it’s not as cut-and-dry obvious as I had thought it was and I guess I should explain/defend my stance a bit more.

Tabs are a form of abstraction

My core argument boils down to the fact that tabs are just a form of abstraction (for spaces)…and I believe abstraction is only good when it clearly simplifies something.

Most developers seem to love abstractions (way too much in my book)…so I guess I shouldn’t be surprised about some people making the case for tabs, but let’s step back and think about it from the larger picture for a minute.

Here’s some hard truths from my personal experience:

1. The arguments that you can configure your editor to handle tabs properly is pure crap. Yes, you can and should configure *your* dev. environment for what best fits you, but you don’t know what editor will be used to edit/manage your code going forward. So don’t force/assume editor configurations. Code should be able to stand on it’s own outside of a given  editor. You’re writing code to solve a problem, not to give your dev. environment something to do. Assume your code will be viewed in any number of pure text editors including a basic NOTES program (and should still look right and make sense).

2. Abstraction makes it harder for beginners to understand what’s really going on. Beginners may not notice tabs (they are often hidden characters; especially depending on the dev. environment someone is using). Everyone should be writing code that makes it easy for others to stand on your shoulders; otherwise your code (and ultimately all your effort) is going to have a really short shelf life. It’s shouldn’t be about showing off how smart or clever you are, but about how easy you make solving the problem for everyone that comes after you.

3. Tab key is non-standard key in many mobile keyboards (and hence a pain). Those of you that are advocating for the use of a tab key have clearly never had to make a hot fix to a production bit of code via your mobile phone. It’s not an ideal situation, but it can (and does) happen…and when it does, you don’t want to waste brain cycles, minutes, and many curse words on dealing with tabs via your mobile interface. (and remember, like it or not, mobile is the way of the future)

4. If you work in a lot of different languages, and also do a decent amount of data parsing and formatting, you’ll see people use Tabs in all sorts of funky and unique ways. You’ll spend a decent amount of time tracking down bugs that are directly related to an accidental or mis-placed tab…but you’ll almost never have the same troubles when dealing with spaces (improper spacing generally jumps out quicker and easier to devs. than tabs). I promise you, this alone will have you cursing the idea of anyone using tabs for anything that they don’t HAVE to.

And while I’m on the soap box, I guess I should call out one more tidbit from the conversation that I can’t just let pass

If you’re a reg. reader/follower of mine, you’ll already know that my personal approach to all code is 1. make it work, 2. make it good, and then 3. make it fast…so you would think I’m all in on this tweet…but I actually think “make it work” on it’s own can be very dangerous. Here’s why:

1. “Make it work” is great for bootstrapping; prototyping; and mvps - especially when working on your own and trying to do something fast…but it’s also selfish and potential maint./scaling nightmare. There’s a big difference between figuring it out, and releasing it. “Make it work” as you’re figuring it out…but “do the right thing” when you release it. Consider the afterlife of your code (and the sanity of those devs. who will follow and/or stand on your shoulders). It’s often the boring and painstaking ‘work’ part of being a professional developer (and so it’s often skipped or at the very least skimped on)…but often the little things in life that make the biggest differences. Take the time to do it right, and your code (and reputation) has an insanely higher chance of a long, and healthy, life.

2. Again, a development goal in all software should be to remove or limit abstraction as much as possible (espeicially abstractions that are just for the sake of abstractions; don’t be clever, be clear.) Want to learn this the hard way? Build something with even a simple layer or two of abstraction, do NOT document it, and then let it sit for just six weeks without thinking about or touching it. Now try to jump in and improve or tweak it. How long does it take you? How hard was it to figure out? Now imagine if you weren’t the orig. dev and didn’t have that initial knowledge (a more real situation) and you can get a feel for how big a problem abstraction actually is. Yes it’s powerful, and sometimes even required, but it also comes with great responsibility – use it sparingly and wisely.

3. Even if you are just thinking of your future self, it should always be your goal to make code as readible, reliable, and repeatable as possible. If nothing else, you’ll save yourself a ton of “remember” time…and again you’ll make it crazy easy for others to stand on your shoulders and move on to the next problem/challenge (rather than refactoring and/or fixing your code).

BTW - this also means using blocks when/where possible (even when not required)…but that’s a larger rant I’ll save for another day.

This post has received 0 love.



This is the personal blog of Kevin Marshall (a.k.a Falicon) where he often digs into side projects he's working on for and other random thoughts he's got on his mind.

Kevin also talks in more depth about many of the these things around twice a month via his drip campaign and has a day job as CTO of Veritonic. You can also check out some of his open source code on GitHub or connect with him on Twitter @falicon or via email at kevin at

If you have comments, thoughts, or want to respond to something you see here I would encourage you to respond via a post on your own blog (and then let me know about the link via one of the routes mentioned above).