Why I don't use the Go formatter
Perdón! Este contenido solo está disponible en inglés.
The best way to get the right answer on the internet is not to ask a question; it’s to post the wrong answer.
- Cunningham’s Law
Okay, I’ve probably got your attention now and you’ll be itching to skim through this opinion piece and tear me to shreds in a comment section somewhere on the web, hear me out first, okay? I promise I’ll build up to a point.
Go: a Google project
I’ve long been of the opinion that Go’s status as a project led and owned by Google has been a two-edged sword as far as the health of the project and it’s ecosystem is concerned.
Sure, on the plus side: Google is pretty big, while there are merits to be found in the Go programming language we’d be kidding ourselves if we didn’t acknowledge that a gigantic part of the popularity and momentum gained by the language in the years since it’s been public are due to Google throwing it’s weight behind it.
As with most things, Go is defined by the circumstances of its inception.
In my experience in software, learning the design principles, objectives and usage context of a tool is essential when deciding how, when and if using it makes sense, this context very often has a strong correlation with both the strong and the weak points of the technology in question, and Go is no different.
So what are the objectives of Go? Go was created to be the programming language used internally at Google for a decent chunk of the forseeable future. Here are some quotes by the man himself:
The key point here is our programmers are Googlers, they’re not researchers. They’re typically, fairly young, fresh out of school, probably learned Java, maybe learned C or C++, probably learned Python. They’re not capable of understanding a brilliant language but we want to use them to build good software. So, the language that we give them has to be easy for them to understand and easy to adopt.
It must be familiar, roughly C-like. Programmers working at Google are early in their careers and are most familiar with procedural languages, particularly from the C family. The need to get programmers productive quickly in a new language means that the language cannot be too radical.
– Rob Pike
So there we have it: Go is designed to be a language with a low barrier of entry to a certain demographic, so that they can produce code across Google-scale teams.
Downwards rounding with the Go formatter
In that context, it’s easy to understand how
gofmt came to being: Google is probably the king of scaling, their products and teams are enormous, their APIs are consumed internally and externally by who-knows-how-many clients, they really are big.
It’s easy to forget this when programming Go, but the overwhelming majority of programmers out there are not working at Google or one of the few companies that share it’s scaling problems, therefore, while Go remains a decent general purpose programming language some of it’s tools and “best practices” are designed to tackle problems the rest of the world doesn’t have, I believe this to be the case with the Go formatter.
Here’s the thing: gofmt optimises for uniformity of code, which becomes more and more important the bigger a team is, and the more the team members rotate. There is unquestionably some merit to this uniformity as it can serve to lower the cognitive load of reading Go code in certain circumstances, such as the ones present at Google.
However, as team sizes go downward, this benefit becomes less valuable. There is also another side of this argument: there is a tradeoff for gofmt, just as there is with most things.
Since Go code is meant to be formatted automatically by gofmt, some style must be chosen. That style may differ from what you’ve used in C or Java, but Go is a new language and gofmt’s style is as good as any other.
- The Golang FAQ section
Is the gofmt style really “as good as any other”? Do we really think we can program a code formatter that outputs the best formatting all (or even most) of the time? That is an incredibly bold assertion, there are far too many subjective opinions at play here on what “best” is, and far too many different use cases for a single style to be universally (or even mostly) superior in an acceptable percentage of code. Styleguides, for the most part, are presented as rules of thumb to be interpreted by the developer.
The fact is that when enforcing a coding style programatically, the style is not the best, it can’t be. What gofmt does is effectively round downwards to an acceptable “not completely crap” style arbitrarily chosen by its creators in the hopes of helping avoid completely crap formatting, which is a difficult thing to do at Google’s team scale, but not really at most other organizations.
No, I don’t use
gofmt when I have a choice. I’m used to working at small teams, with developers I trust to make effective code formatting choices and with enough code review that any quirks can be discussed and agreed upon. It’s not a gigantic waste of time, and I find that the code is more legible this way most of the time.
The larger point, however, is that this shouldn’t be such a big deal as the responses I usually get while discussing it.
The formatter is an optional language feature, which implies tradeoffs which might sometimes make it a poor choice. Why so defensive? I’m not murdering any kittens.
It’s okay to enjoy some of Go’s features and dislike others, it’s okay to think that the Go team messes up some decisions and still delivers a decent programming language with many enjoyable merits, criticism is a tool of progress and improvement, and failing to criticise Go’s weak points in a constructive manner is a sure pathway to stagnancy.
There is an excellent writeup by Gary Willoughby (@nomaddeveloper) that touches on some of the same points I’m making, it’s called Why Go’s design is a disservice to intelligent programmers.