Hacker News new | ask | show | jobs
by tomp 1586 days ago
worst things about Black:

- doesn't respect vertical space - sure, making the code fit on screen might be valuable (though the default width should be at least 120 characters, I mean we're in 2022 after all), but Black does it by blowing up the vertical space used by the code

- spurious changes in commits - if you happen to indent a block, Black will cause lines to break

- Black fails at its most basic premise - "avoiding manual code formatting" - because a trailing comma causes a list/function call to be split over lines regardless of width

6 comments

> oesn't respect vertical space - sure, making the code fit on screen might be valuable (though the default width should be at least 120 characters, I mean we're in 2022 after all), but Black does it by blowing up the vertical space used by the code

This is fine with me--I think it makes sense to optimize for readability, and I can read a long vertical list of arguments a lot more readily than a long comma-delineated list.

> spurious changes in commits - if you happen to indent a block, Black will cause lines to break

Is this a generic argument against wrapping lines, or am I misunderstanding something?

> Black fails at its most basic premise - "avoiding manual code formatting" - because a trailing comma causes a list/function call to be split over lines regardless of width

I'm not following this either. If black automatically reformats your code over multiple lines, that doesn't suggest manual formatting. Maybe you're arguing that all code which produces a given AST should be formatted in the same way--this would be cool and I would agree, but black gets us 95% of the way there so to argue that it "fails" is to imply that "0%" and "<100%" are equivalent.

> the default width should be at least 120 characters, I mean we're in 2022 after all

Even in 2022, some people don't have wide external monitors, sometimes like to view two files (or a diff) side-by-side, or need to use GitHub/BitBucket/etc. code viewer pages. Also, it's still difficult for humans to read long lines.

Agreed. It's really nice to be able to have two files side-by-side (or a file plus a shell) without having tiny font. I still do the overwhelming majority of my work on a laptop--maybe I'd feel differently with one or more 27" 4K monitors, but even then I don't think a code formatter should make these kinds of assumptions.
True, but we also have word wrap to deal with this automatically!
> This is fine with me--I think it makes sense to optimize for readability

You cannot read things you can't see. If half a function is scrolled off the bottom of the screen because every function arg is on its own line .... its pretty annoying.

I also noticed we are in 2022, and my screen is so big I can have three or four files of 80'ish chars wide side to side. Specially with Django, where you usually need models.py, views.py, forms.py and a template open at the same time. With 120'ish lines, I lose one vertical split.
I have to bump up my font size a bit and find 120 characters too wide on a 27" monitor where I need to look at multiple things side by side. It's also harder to read even when viewing a single file.

IMO, < 80 is ideal where possible with an absolute maximum of 99. I think Black's choice of 88 (plus maybe a little more in special cases) is quite good.

It's odd that nobody followed Go's formatter in letting developers break lines themselves and mostly fixing indentation and spacing. I thought they made good choices.
Honestly the only grievance I have with Go's formatter is that it doesn't automatically break lines. I'd be a big fan of "if two programs parse to the same AST, they should format the same" and if that's too aggressive perhaps allow for `// go:nofmt` annotations or something. In whatever case, `gofmt` gets at least 95% right.
Nah, I can totally understand why they decided to stay away from this can of worms. First, what max line width do you choose? Second, where do you break a line if it's too long? I think gofmt gets the balance exactly right: makes source code easier to read by providing a unified formatting style, but doesn't get in your way more than necessary.
> First, what max line width do you choose?

The whole point of an opinionated formatter is to have opinions about these sorts of things.

> Second, where do you break a line if it's too long?

It depends on the context. Yeah, writing the algorithm to make these decisions is a little complex, but it's also well-understood.

> doesn't get in your way more than necessary

What is "necessary"? It seems like you're trying to say "it makes decisions on the things I think it should make decisions on" which is fine, but it's not like choosing between `struct {` and `struct{` is objectively more critical than line wrapping.

I believe one reason they chose it is so that automatic reformats like renaming a variable don't cause reformats to more lines than necessary.

Keeping lines reasonably short is nice but doesn't need to be done strictly. It can wait until someone edits the code.

> what max line width do you choose?

80

> where do you break a line if it's too long

Wherever a keyword or name ends, but does not exceed 80.

Gofmt has made opinionated decisions about everything, why stop at line breaks?

When I'm writing Python at Google, and get yet another error because my Python or Markdown line exceeds 80 characters, and read the fights on the mailing lists about changing the limit, I think Go was created because it was easier to create a whole new language than get the line length increased for Python.
Why do you get errors rather than auto-formatting (in the editor or in CI) and moving on with your day? I would have thought Google would have this sorted already?
IME 80 is terribly short in almost any language.
I like 80 because I can have three vertical windows open on my monitor and see everything without side scrolling.
I'm in this camp. Why do we still waste brain cells on this problem? Just copy it
> - Black fails at its most basic premise - "avoiding manual code formatting" - because a trailing comma causes a list/function call to be split over lines regardless of width

Yeah, this one drives me nuts too.

It's one of my favorite things about black, and I've started to use that formatting of function calls with long arguments for other languages too.

But I also despise long lines with a passion, I hate having to go to the right, and would much much rather scroll up and down with a consistent width, so that I can put multiple views next to each other.

I don’t mind the formatting, I mind that the formatting is done depending on wether the list ends with a comma or not.

    [
       Item1,
       Item2
    ]
Is combined to one line, while

    [
       Item1,
       Item2,
    ]
Stays as multi line. Now I am once again in charge of formatting my code, by virtue of the comma. Does this stay multi line or is it short enough enough to combine? That should be for black to decide not me!
If I'm understanding your problem correctly, it seems that you can avoid it by using the --skip-magic-trailing-comma option [0].

[0] https://black.readthedocs.io/en/stable/the_black_code_style/...

Yes, but wasn’t the whole point not having to run the linter with options.

The trailing comma thing seems inconsistent with handing over the formatting to black. Now I’m in charge of deciding if a list should be cleaned up into one line or not.

My monitor is in portrait mode. Even when I used one in landscape, I typically had two windows side by side. So extra-wide lines of code are less readable.
> - Black fails at its most basic premise - "avoiding manual code formatting" - because a trailing comma causes a list/function call to be split over lines regardless of width

Ah that's why `manage.py shell` now split json pasted on several lines, very annoying