Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

There's only two ways to write code where the lines of text stay legible regardless of tab size configuration:

1. Use all spaces

2. Use tabs for indentation and spaces for alignment

Unfortunately, only individual developers seem competent on their own to do #2, so everyone who cares about readability inevitably practices #1 by default.

You can never use only tabs.



A special case of (2) that is easy to do is to use tabs* for indentation and not do column alignment at all. To be clear, by "column alignment" I think we are both referring to patterns like this:

    myVars = {
        first:     123,
        second:    234,
        afterward: 345,
        also:      456,
    }   //~~~~~~~~ <- alignment

    // or:
    def my_long_function(arg1, arg2,
                         more_args,
                         and_some_more)
    //~~~~~~~~~~~~~~~~~~ <- alignment
This is, e.g., what Go uses for struct fields, and what some Python style guides use for hanging function definitions. Regardless of tabs/spaces preference, both of these are independently bad because they churn diffs unnecessarily: if you change `afterward` to `afterward2` then you need to change all the nearby lines, and likewise if you change `my_long_function` to `my_longer_function`. Some formatters, like Black, Prettier, and (mostly) Rustfmt, avoid this pattern entirely, and they are better for it.

* You can do this and still use spaces if you prefer, too.


Or just configure your code formatter to do this and forget about ever getting it wrong again.


That doesn'f fix the ugly diff spam though


of course it does, why wouldn't it?


What? How would it? Do you understand what is meant by that?

The problem being referred to here is that a change on one line causes changes to unrelated lines. It makes it harder to pinpoint which line was changed intentionally in a diff and which ones were just caused by tab issues.


Err, yes, been coding for a while :D

If you format before every commit, then the only changes you get are the changes you made.


Doesn't help if you squash changes before merging, which is typical for large codebases


Again, this makes absolutely no sense to me. I've never experienced any of the problems you're facing and I can't imagine how they'd even cause problems.


It's not clear why you're still defending this position. Feels like you made a not well considered, off the cuff remark about something. Rather than realize you were wrong and take the L, you're still doubling down? Is it that important to you?


That’s what ignored revisions are for.


That doesn't help the problem here. Part of the revision is still relevant (say, adding a new, longer field name to a struct) and the rest is just extra spam. But you wouldn't want to ignore the entire revision.


It really sounds like you've not tried formatters before.


> Use tabs for indentation and spaces for alignment

I'm not surprised that this isn't something that projects have been able to adopt successfully very often because I've never found it very intuitive that those are separate things. In what way is "indentation" not also a form of "alignment"?


The other problem with it is that it assumes that people have visible whitespace on, and that their tools even have that option to show whitespace, otherwise it’s like navigating the Fuchsia Gym.

I don’t mind if people use tabs but mixing the two is not great.


The worst mixing I've seen: aligning on 4 spaces, but using tabs as a placeholder for 8 spaces. So first stop is 4 spaces, then tab, then tab and 4 spaces. Chaotic evil version of tabs vs spaces battle.


Why would you care about the whitespace? Formatting is a job for computers, not humans.

I'm practically unable to `git add` unformatted Go or Rust code, and very happy with the setup:

.config/git/attributes:

    *.go filter=gofmt
    *.cgo filter=gofmt
    *.rs filter=rustfmt

.config/git/config:

    [filter "gofmt"]
    clean = "gofmt"

    [filter "rustfmt"]
    clean = "rustfmt --edition=2021"


I’m not sure what relevance this has to files that use a mix of tabs and spaces because I’m not aware of any formatting tool that can reproduce that convention.

Knowing whether a space in a space-formatted document is for alignment or indentation is AI complete.


The relevance is that I the human don't bother and the tools do it right. Go code uses both tabs and spaces...


Aligning a character on one line with an arbitrary character on another line is purely a choice of style, not a requirement.

It is perfectly doable to do only tabs, but many end up mixing in spaces.

The curse of space-only files is in people that manage commit indentation errors, breaking auto-detection in some editors, which propagate to even more indentation errors... All it takes is an inattentive reviewer, or review-less merge.


Readability of the code is not mere style, and can directly translate into errors being more visible. Compare:

    a_variable = (
       'lorum ipsum dolor sit amet ' +
       'my poor memory has left me quite upset ' +
       'for i cannot remember what word comes next '
       'in this long descriptive text' +
       'surely this is bound for the incinerator ' +
       'but remember any haiku can end, refrigerator.'
    )
But now if I choose to align certain characters:

    a_variable = (
       'lorum ipsum dolor sit amet'
       + ' my poor memory has left me quite upset'
       * ' for i cannot remember what word comes next'
       ' in this long descriptive text'
       + 'surely this is bound for the incinerator '
       + ' but remember any haiku can end, refrigerator.'
    )
… the errors in the first version are now plainly obvious. (Both the missed space, as well as the missed +.)

(This is an example. Yes, there are languages for which you don't need the +. There are some for which you do, however. There are also some that resist having the + moved about: for example, in Javascript, the parens become required, or you'll trigger the horrid auto-semicolon "feature".)


Hmm? You have not changed alignment, as all your lines of code start on the same integer indentation boundary. You just moved the operator to the beginning of the line, and changed the bug between the two examples.

Either you misunderstood what we mean by alignment (single whitespace separating operators and operands are not alignment), or maybe you tried to indent the first string literal further to align the string literal start boundaries. I sincerely hope it wasn't the latter...

Putting the operator on the second line, at the same indentation level, is a perfectly fine, indentation- and alignment-agnostic stylistic choice, and has its uses.


> You have not changed alignment

I have changed the alignment of both ' ' and '+' characters between the two examples, from not being aligned to being aligned.

> as all your lines of code start on the same integer indentation boundary

Indentation is not the only thing "style" guides enforce.

> and changed the bug between the two examples.

The bug should be the same in both examples, though I do see I transposed a '+' into an '*'. That wasn't intentional; the two are supposed to form the same AST, but with purposeful alignment in the second making bugs in both far more visible.

(You seem to be using "alignment of characters" to mean "alignment with indentation", which is more limiting than I would take "Aligning a character on one line with an arbitrary character on another line" to be.)


>purely a choice of style

Sure, but could i not say the same of using any indentation at all?


Would you consider a file without any indentation as readable and practical as a file without single-space alignments?

Not to mention that in languages like Python, indentation is syntax.


With a variable width font you can't use spaces for alignment...


If you program in a variable-width font, you're on your own!


Monospace is weird legacy technology and a path dependency that people are holding on to for not so great reasons.

If monospace was actually a good idea and not a technical limitation of computers from the 80s, books, newspapers, and your comment on this website would be displayed in monospace.


I dunno man, sometimes things are good in different contexts. Monospace makes stuff really easy to align when programming, and while I do like the idea of elastic tabstops and have tried it out before, in practice they don't work so well.


Frankly, I've never desired for things to be aligned in source code. Are you, like, embedding tables of numbers in your code, or just explicitly aligning the equals signs in short = 42 and much_longer = 7?


That is, people using alignment only care that it works on their machine.


> Use tabs for indentation and spaces for alignment

The pains is, most website or editor never handled that well enough. You end up have mixed tab/space at unexpected position and never knew about it.

Just banning the tab is probably not the most 'correct' option to fix it. But it is the most feasible one to get the job done. Because fixing all the tool, editors and websites is nearly impossible for an average man.


Simple solution: Auto formatters

- If you have project wide automatic code formatting: Tabs

- Otherwise: Spaces

Nowadays, most of my projects use option 1.


3. Use tabs for indentation


> Unfortunately, only individual developers seem competent on their own to do #2,

What do you mean?

> You can never use only tabs.

You can.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: