Yesterday, I shared some spicy takes. A few were particularly controversial—most notably, that I correct Gif the correct way (with a soft G)—but I also got a lot of emails asking me to elaborate on a few of them.
Today, I wanted to talk about how tabs are objectively better than spaces. This won’t take long.
Tabs let you define how big you want each indent to be, and spaces do not.
When I talk about alignment it’s not about function arguments, but values, “=” signs and such. You simply cannot use tabs for that because alignment must be fixed and indentation independent:
CreateOrderRequest(
user,
productDetails => order.detail,
pricingCalculator =>DEFAULT_CALCULATOR,
order => order.internalNumber)
It seems like this basic guideline, tabs to indent and spaces to align, solves the problem for everyone. It doesn’t matter what your tab width is, it’ll look “right” regardless.
Then you lose the benefit of tabs: you can’t adjust the tab width without destroying alignment. So you end up with a confusing mix of characters for no benefit.
You might not understand how to do it properly so here’s the idea:
Tabs will let you reach the indentation level of the current block, then from here, you’ll use spaces to align stuff property. Here’s an example, where >••• are tabs (I’m exaggerating alignment for the sake of the example) :
The opposite is true, though. If you use tabs for indentation and spaces for alignment, you can adjust the tab width without destroying alignment. That’s the big benefit of the tabs-for-indentation-spaces-for-alignment mix.
You can’t do that with only tab characters, you can’t even align stuff with tabs because it has variable width.
You’re confusing using tabs for indentation and spaces for alignment with using tabs and spaces for indentation. This means each line starts with tabs. Next you optionally have spaces for alignment with previous lines. Then you have content (like code or comments). Because you never have a tab following a space the alignment is never destroyed by adjusting how wide a tabstop is.
Many styles are difficult to maintain, I’m not saying it is or isn’t. I’m saying that using only spaces for alignment will not let your alignment get messed up with various tabstops settings.
It’s hard to do this consistently (especially in a team) because people might (and statistically in a large enough project, will) use the tab key for alignment since it’s faster than pressing space, or just be confused about what whitespace is tabs and what is space. Just using space everywhere is idiot proof and requires no work to micromanage. The only way to use tabs is to not align at all.
I agree that it’s hard, but not impossible. This usually boils down to how Nazi people are when merging code. In a corporate environment, nobody gives a damn so yeah you gotta use whatever you want because there are already different indentation systems within the same file anyway :)
But hey, you gotta live by the changes you want to see happen, so I personally put a lot of effort in formatting my code regardless.
I used to think this way, at least when writing C++. But it’s objectively harder to do and convince other people to follow, especially if they can’t be bothered to change their environment to display tabs and spaces differently. It’s a losing battle so now I just do spaces when working with other people
Tabs for indent, spaces for alignment. This is the way, I can’t believe people are still fighting that ?
Anything for indent (barely matters, as long as the editor forces it to stay consistent), and fuck alignment, just put things on a new line.
struct Ident arr = [ { .id = 0, .name = "Bob", .pubkey = "", .privkey = "" }, { .id = 1, .name = "Alice", .pubkey = "", .privkey = "" } ];
Not like that, lol
Just saying, instead of this monstrosity
CreateOrderRequest(user, productDetails, pricingCalculator, order => order.internalNumber)
Just use
CreateOrderRequest( user, ...
Putting the first argument on a separate line.
When I talk about alignment it’s not about function arguments, but values, “=” signs and such. You simply cannot use tabs for that because alignment must be fixed and indentation independent:
CreateOrderRequest( user, productDetails => order.detail, pricingCalculator => DEFAULT_CALCULATOR, order => order.internalNumber)
I normally avoid that too, I find it hurts readability more than helps, plus a proper IDE will separate it by color anyway.
But yeah, the newline comment doesn’t apply to this.
To each their own indeed. But my rule of thumb is: only use tabs when there’s no other character before it (aka, start of line).
The emacs wiki agrees and has the correct take on this: https://www.emacswiki.org/emacs/SmartTabs
It seems like this basic guideline, tabs to indent and spaces to align, solves the problem for everyone. It doesn’t matter what your tab width is, it’ll look “right” regardless.
Yeah I agree I don’t find alignment very useful. It’s more work for dubious benefit, and god forbid you change one of the lines.
People seem to have a real issue with using new lines and I’ve never quite understod why.
It feels like a lot of those people are using notepad like applications instead of coding focused ones with collapsible regions etc.
seconded on not aligning things. its the whole source of the problem in the first place and doesnt even serve a purpose
Then you lose the benefit of tabs: you can’t adjust the tab width without destroying alignment. So you end up with a confusing mix of characters for no benefit.
Mixing them is the worst option.
You might not understand how to do it properly so here’s the idea:
Tabs will let you reach the indentation level of the current block, then from here, you’ll use spaces to align stuff property. Here’s an example, where
>•••
are tabs (I’m exaggerating alignment for the sake of the example) :>•••if (condition1 == true >••• || condition2 != false) >•••{ >•••>•••struct ident people[] = [ >•••>•••>•••{ >•••>•••>•••>•••.name = "bob", >•••>•••>•••>•••.pubkey = "value1", >•••>•••>•••}, >•••>•••>•••{ >•••>•••>•••>•••.name = "alice", >•••>•••>•••>•••.pubkey = "value2", >•••>•••>•••} >•••>•••]; >•••>•••secureConnection(people[0].name, people[0].pubkey, >•••>••• people[1].name, people[1].pubkey, >•••>••• CRYPTO_ALGO_DEFAULT); >•••}
As you can see, everything will stay correctly aligned as long as it’s within the same block.
The opposite is true, though. If you use tabs for indentation and spaces for alignment, you can adjust the tab width without destroying alignment. That’s the big benefit of the tabs-for-indentation-spaces-for-alignment mix.
You can’t do that with only tab characters, you can’t even align stuff with tabs because it has variable width.
You can preserve alignment in a mixed context, but it complicates things.
You’re confusing using tabs for indentation and spaces for alignment with using tabs and spaces for indentation. This means each line starts with tabs. Next you optionally have spaces for alignment with previous lines. Then you have content (like code or comments). Because you never have a tab following a space the alignment is never destroyed by adjusting how wide a tabstop is.
I am not, it’s easy to find examples where tabs first then spaces breaks down.
That example is using tabs for both indentation and alignment. The article you linked even says not using tabs for alignment is a solution.
Yes, but keep reading. That strategy is a pain to maintain especially across editors.
Many styles are difficult to maintain, I’m not saying it is or isn’t. I’m saying that using only spaces for alignment will not let your alignment get messed up with various tabstops settings.
It’s hard to do this consistently (especially in a team) because people might (and statistically in a large enough project, will) use the tab key for alignment since it’s faster than pressing space, or just be confused about what whitespace is tabs and what is space. Just using space everywhere is idiot proof and requires no work to micromanage. The only way to use tabs is to not align at all.
I agree that it’s hard, but not impossible. This usually boils down to how Nazi people are when merging code. In a corporate environment, nobody gives a damn so yeah you gotta use whatever you want because there are already different indentation systems within the same file anyway :)
But hey, you gotta live by the changes you want to see happen, so I personally put a lot of effort in formatting my code regardless.
I used to think this way, at least when writing C++. But it’s objectively harder to do and convince other people to follow, especially if they can’t be bothered to change their environment to display tabs and spaces differently. It’s a losing battle so now I just do spaces when working with other people