Musings on Black

Black is a code formatter for Python. Well, that might be an understatement. It appeared a couple of years ago, and immediately won a huge acceptance. Maybe that was a gofmt envy, I am not sure.
Fact is, Black is now almost a standard, with teams using it all over the world, and even the asda is using it.

Personally, I do not like it. Actually, the times I had to read code formatted with Black I always a bad feeling, like reading “enterprise code”.
And maybe that’s the point – Black’s appeal is on an extreme consistency in order to help team working together – but that’s nothing to see with the beauty that you can feel reading good python code.

To go a bit in detail why I do not want to work with code formatted with Black, for me, it boils down to three points:

  • Code beauty
  • Difference between code and data
  • “Textual” style vs. “Enterprise” code style

Code beauty

The first one, is actually not only my point — even GvR said something very similar: Black is good for large projects, but I find it uglifies all code compared to manually formatting using careful consideration of PEP 8.

Most of the times, black formats ok. The problem are the exceptions. And with type hinting (which very often forces to split long lines) those exceptions are more common – way more common.
The result is often “according to the algorithm”. Formally compliant? yes. Beautiful? Absolutely not.
And in the end, beautiful code is one of my most important metrics in my work, and as stupid as it might be, a very precious tool that I have in evaluating code. Because I read beautiful code with more pleasure, so it’s easier to understand and maintain.

Difference between code and data

The second point, is something that I have not seen any other complaining about, so it might be just me.
My point is that function declaration very often degrades to a shape that is actually looking like a list. Take for example this snippet:

def function_wiht_long_signature(
    self,
    itinerary: Itinerary,
    object_checker_results: ObjectCheckerResults,
    external_assessment: Optional[ExternalAssessment],
) -> None:

(note also the comma after the last parameter!)

This does not look like a function; to me, this looks more like a list:

context_for_function = [
    self,
    itinerary,
    object_checker_results,
    external_assessment,
]

What I want to say, is that for me, data should develop vertically, while function definitions should develop horizontally. Mixing the two makes code more difficult to understand, because you are actually mixing two different facets. Of course, you can get used to that; still this makes skimming through code harder, as well it makes harder to quickly grasp abstractions and flows.
Well, at least for me.

“Textual” style vs. “Enterprise” code style

Finally, we go to the third part: “text style”.

Python was heavily influenced by the ABC language, which was essentially a research project, about creating a language easy to learn and use. As such, it had a very strong focus on readability – hence the formatting, and things like the usage of the colon (see Karin Dewar, Indentation and the Colon for more details). In other words, one of the main drivers was for code to look much like written text. Again, the reason why you have the colon at the end of a function definition: because it kinda mimics the rules for writing English text.

Now, Black completely ignore those ideas, and for the virtue of consistency, it simply treat the code like if it were Java (or C, or whatever) — without any regard for the “written piece of text” part.

So, why Black?

So, we are at the end. And with this, we get to the very core of the point.
Why black?

For a smaller team, focused on execution speed, with an healthy codebase and light formatting tools (like the excellent from PyCharm), I think zero. Actually, less than zero, given the points above.

For a large team, however the situation is different. Large teams, with people of different skills and mindsets; large team where people of different opinion cannot really talk together and reach an agreement on a process – and unfortunately, this is something bound to happen over a certain size – can actually benefit from Black. Because in that case, you can just say “black” and everybody have to agree. Heck, who would disagree against a tool with so many users?

That said, I was working in such teams, and in the end code formatting was the least of the problems.
Yes, a tool can and will help; but that’s not touching the core of the issue.


python

753 Words

2021-04-19 00:39 +0200