73 comments

[ 4.5 ms ] story [ 139 ms ] thread
I usually drink the DHH koolaide when it comes to Rails decisions, but I'm surprised by this decision exactly because of his arguments against being forced to write specific styles. I enjoyed default RuboCop when I was first learning Ruby to gain idiomatic knowledge, and strongly disliked after I took off my training wheels. I don't even like using `standard-rb`, which is a much more tolerant configuration of Rubocop. There are often reasons to disregard certain style rules, and I don't want to ask for permission in `# magic disable comments`.

I strongly agree with all of his descriptions of formatting and linting. I also strongly agree with him putting his personal style into Rubocop for the Rails codebase itself, and for project maintainers to be in control of what, if any, style they wish to enforce. But to omakase his style-guide into the consuming projects is surprising and against the very arguments against conforming to style-guides he presents in the first half of the post.

I am in the camp of using as little rubocop as possible, but still using it. I like it to address the drastic stuff like misalignments, mixed tabs and spaces, obvious sloppiness.[1] Still, it should allow most of the freedom. My preferences are posted in what I call a "narrative" Rails template[2]. It's a relaxed "standardrb", which I have since relaxed even further, but haven't updated the repo yet.

[1]: https://github.com/AuthorizeNet/sdk-ruby/commit/1972b153a893... [2]: https://github.com/maxim/narrative/blob/main/example_app/.ru...

I've read this twice and I'm still getting something like: "Programmers lack style, hence linters, but linters are draconian in nature, so we are going to slap a linter in the next release"

It is Friday and I'm tired, so maybe I need another re-read.

I think DHH explains the reason pretty well in the article

> That’s why we’re shipping a default linter, cleverly called RuboCop, in the next version of Rails. Not such that I, or anyone, can mandate what style your codebase ought to be written in, but such that you can find and enforce your own.

So every new Rails project has preset of linting style, which defaults to whatever the Rails team chose, but the point is that people are free to adjust the config file to whatever they prefer. So the same style is applied through the codebase.

No, that's all peachy, but you're just going to tell me the post doesn't start with one idea, smoothly moves on, and just past the code example, wraps it up by completely dismantling the premise?
> but linters are draconian in nature

His point is actually that linters lacking configuration are draconian.

> Some languages, like Go, have a built-in linter, which applies a universal style that’s been set by the language designers. That’s the most totalitarian approach.

I'd doubt it's the "built-in" aspect; it sounds quite a bit like it's the "universal style" that the author doesn't like.

(comment deleted)
(this is probably unfairly cynical but), reading heavily between the lines, this reads to me like DHH noticed lots of Rails folks and rubyists already like and use "standardrb" for this https://github.com/standardrb/standard -- https://www.youtube.com/watch?v=QVilOzkLdlI -- but for some (unspecified?) reason(s), wasn't willing to bless the popular community-created universal standard as default convention, so instead wrote up his own, and is declaring his the default convention for Rails.
I don’t get the impression that standardrb is that popular.

It’s also hyper strict, which is ok for a new project, but won’t play nicely with any legacy app.

Though I’m surprised DHH didn’t write his own RuboCop from scratch.

I think you forgot "I don't like 'if !foo' but I don't know what a guard clause is."

This is from DHH, the Rails guy.

> gofmt bothers me

> we're shipping rubocop with the next rails

> choose one

I'm a pretty big DHH fanboy, but this article felt pretty odd in its tone and composure.

I read it as “different teams have different styles, so they might benefit from having a tool to enforce their own styles” - hence the Rubocop
Yeah, but nothing he said supports the idea of having rules applied automatically unless they configure rubocop. Everything he said supports an opt-in methodology (and maybe it will be, by requiring a flag when starting a new project), but putting every programmer and team in a place where they have to configure rubocop on their rails projects is counter to the tone and points he makes in the article.
When you can look at some code in a repo and immediately know who wrote it, that is usually a problem. I've worked in code bases where the devs could not agree on style and they each did their own thing. It quickly became an unmaintainable mess. Having a homogeneous code style is a good step towards long term maintainability. It has been many years since I've worked on a rails repo that didn't have rubocop. Glad to hear rails will ship with rubocop.
I can't quite imagine what you mean by this, asking for clarification sorry if I come off wrong. Why is it a problem that you know who wrote the code by looking at it? Do you mean that their style is distracting?
Ruby has "reduce" and "inject" aliased. Most developers pick one or the other. A codebase that mixes them adds cognitive load. It's not hard, but it adds a speed bump to understanding.
Does it really, though? How much time do you actually lose to having to sometimes read "reduce" and sometimes read "inject"?

I've heard these arguments a hundred times, and not once did I feel like the underlying sentiment was more than "I like/dislike X, therefor I want to limit how much other people can use X".

I worked on a small team for years and the other person who was there that whole time was an inject guy. I'm a reduce guy. It's fine, we never tried to change each other, but I never got over the mental hump of "what does inject do? Oh right".

This is for the smallest possible style difference. I agree that a lot of folks get hung up on their personal preferences and want to fight about. Linters reduce those fights, and encourage everybody to just deal with it.

I mean if someone has a particular style that others disagree on, the repo ends up with inconsistently styled code. There are benefits to consistently styled code especially when there are a lot of hands in the repo. I think teams should strive to have a mostly homogeneous code style for consistency sake. It makes reading code easier and ultimately maintaining code easier. Having a linter enforce style rules is really helpful so code reviews don't need to be consumed with tedious style discussions.

I like rubocop because it can be configured to be as flexible or strict as the team wants. Let the team establish what the level of consistency they want is.

Hey, a true code stylist will stand out even after the autoformatter does its work. ;)

It's good to have Rubocop included by default, but I wonder how many teams are using the "omakase" Rails at this point? I don't think I've done a plain `rails new` at work in a decade.

been coding in rails since about 2009 and only just hearing about "omakase" Rails now
I pretty much only ever see DHH saying it.
( * ^ *) ノシ , dejur. No doubt it a nice and rare luxury to start a new rails project. I wonder if the rubocop defaults will be included in rails upgrades or just new rails projects. Like when people upgrade to rails 7.2, maybe rubocop will come along for the ride.
If you're just writing code for yourself, well and good, do whatever pleases you.

The problem is that, as George Costanza said, we are living in a society. If you work on code that other people need to read and maintain, then there are a few individual concessions we should consider in order to benefit the larger group. In addition to linting, I'd also put types in this bucket. I don't think it's a coincidence that DHH doesn't like the way those feel, either.

They may cut into your personal enjoyment, but if it benefits the productivity of the larger group then that's a sacrifice you should probably consider. This is the entire reason that standards exist.

« Some languages, like Go, have a built-in linter, which applies a universal style that’s been set by the language designers. That’s the most totalitarian approach. A decree on what a program should look like that’s barely two feet removed from a compile error. I don’t like that one bit.

It reminds me of Newspeak, the new INGSOC language from Orwell’s 1984. »

I do not like something hence it’s totalitarian and newspeak.

Excellent material for some courses on discourse analysis!

Formatters are an interesting topic in that sense. Anecdotally, I sense that they're usually introduced to stem debates about style. I think that's probably not a good enough reason for them to exist. There's a sensibility that says "debates about style are bad and wrong." Where is that coming from? Why is that opinion so pervasive?
AFAIK, it's because they can easily become toxic and immensely time-consuming.

Personally, I haven't seen that failure mode, although I also haven't been in a situation where it'd come up.

Maybe because they’re unproductive, bring no value and generally a team drain because every special snowflake feels like their specific vision is the readable one?
The benefit of gofmt has nothing to do with "style" per se. Because it's standardized, tools can rely on its output. This means that you can easily write tools that handle go source code and interoperate well with each other
Go's parser can be used on code with any formatting.
True, but there are times when doing some analyzes or refactoring that what one wants to operate on is go source directly, so the output of gofmt is easier and standardized and doesn't require handling the ast at all.
Can you give an example of such a tool that analyzes/refactors just the text output of gofmt?

It seems like that approach that would be fraught with errors considering how lenient gofmt can be at times but maybe it would be okay for simple stuff. e.g all of these ways of invoking methods:

   fmt.
           Println("Hello ",
                   "World",
           )

  fmt.Println("Hello ",
          "World")

  fmt.Println("Hello ", "World")
Do you have a source for this? It's always been my understanding that the creation of gofmt was almost entirely so that programmers would stop arguing about style.
Sorry I didn't mean to imply that wasn't a driving factor of it's creation. I should've said that it's a useful side effect
This post is so wonderfully confused it's throwing my brain into an infinite loop. Misunderstanding newspeak, then a howler of a non sequitur, all about elegant composition, all the while turning a simple announcement into a super clunky argument. It's perfect doublespeak, the kind of language that throws critical thinking into infinite loops.
He didn't even bother to proofread this so what do you expect.
Should have used a linter
What for, he’d probably configure it to his unique and expressive style.
DHH imposes this kind of cognitive dissonance on the Ruby community at a pretty regular interval.

it's generally worth it, but it's still a kind of brain tax.

newspeak is for dramatic (and dare I say, rather fun) effect. I think his point is straightforward and not confused: one style and one liner for the entire programming language prohibits personal expression of style. A linter to enforce your own personal / team styles is a good idea. I don't see the confusion. You might disagree with one or both, but to me it seems logically consistent with the premise of the article which is that personal style is important in programming.
Is that his point? Or is his point that shipping rails with his own personal linting preferences is a good idea? (For what it's worth, I think it's a perfectly fine idea).
he's a genius at that. his blog posts are always like, "it's dumb that we do this or even debate about this. but my way is better. here is me debating my way in a sanctimonious blog post where i said i'm above debating this issue yet here i am debating this, and i think that my taste is the best even though i'm advocating for a big tent and i'm a really good writer and you should read me, i spent oh so much time editing this beauty of a blog post."

and then the follow up blog post: "I DON'T KNOW WHY EVERYBODY IS MAD ABOUT THIS! I AM RIGHT!!!"

Arguments of style are our desire for this work to be easier turning us against one another. We write our statements for both human and machine colleagues (who will never see eye-to-eye.) I regret that formatters can prevent us from laying things out most clearly at times.

Formatters feel varying levels of painful on a per-language basis. The balance probably lies in empathy: It wasn't best to write it that way if it was not beneficial to either the machine or your collaborators.

On the other hand, if it brings someone joy to write in their distinct style, would we deny that joy?

Side tangent: I love Ruby, but strongly dislike and discourage `unless` in the code base. It still trips me up having written Ruby 5 years at this stage. Maybe its just me but I still pause every time for myself when looking at `unless` with a multi conditional. Example:

def do_the_thing

  return do_not_do_it unless first_conditional || second_conditional

  okay_actually_do_it
end

Glad that Rubocop is shipping with Rails though!

Same. I encourage the use of unless iff it reads like english and I’ve found that to be a pretty good rule of thumb for the majority of my team
I've known a handful of people who can handle conditionals inside an unless, and dozens who can't. I'm in the latter camp. Banning conditionals in an unless is a very reasonable rule to follow
Maybe a decade of doing ruby has rotted my brain, but I love `unless`, and use it often.

Yes, every `unless` could be rewritten with an `if` instead, certainly. But I like the implication of weight these keywords carry in English language. `unless` implies it's a minor condition, that the majority of runs should fall on the opposite side of the conditional, where as `if` does not -- both weights of the condition feel potentially equivilant-ish.

`unless` is great, but best used sparingly. Only use it if the conditional is single, and simple. Never use it with `&&` or `||`, or `!`.

`unless admin?` is fine

`unless !admin?` is annoying `unless user.admin? && account.support?` leads to madness

Nearly all the first comments express that the justification to include Rubocop with a default rule set in Rails 8 contradicts DHH's criticism of languages such as Go which have a built-in linter, therefore dictating style rules to programmers. DHH criticizes Go's approach as totalitarian while shipping Rubocop with Basecamp's rule set.

Rubocop is a linter (etc) whose rule set can be easily customized and to include it in Rails wouldn't be possible without _some_ default set of rules. DHH addresses this apparent contradiction directly, too: "Not such that I, or anyone, can mandate what style your codebase ought to be written in, but such that you can find and enforce your own." I'm reading: A linter/formatter will be included in Rails 8 with a smart default rule set, and it can be easily customized. I don't see any contradiction.

I'm highly aligned with this decision as it could help alleviate a recurring pain point at our tiny company: managing code formatters and linters in our IDE (Solargraph, Rubocop, Ruby LSP, etc). Further, I'd expect excellent documentation on how we can customize the rules to best suit our purposes, too.

Most counterarguments go something like "It's bad when everyone writes in their own style, that's why one style should be enforced." But this gets you right into the other extreme: code consistency is valued above comprehensibility. Now your code is harder to read because you format it mechanically, instead of using your own human consideration.

The right answer in my view is kind of what I think DHH is trying to get at: have enough rules to avoid straight up sloppiness and clear no-nos. Don't have any rules that might change based on human consideration.

> Now your code is harder to read because you format it mechanically, instead of using your own human consideration.

How so?

Because humans can break a rule in favor of readability, symmetry, clarity. Linter can't.
> Because humans can break a rule in favor of readability, symmetry, clarity.

Care to show examples? I haven’t encountered a single one where that would the case.

With Ruby, you have many different, expressive ways of saying the same thing. Examples that come to mind off the top of my head: deciding to vertically align keyword arguments sometimes. Wrapping code differently to meet a line length limit. Breaking the rule of "never making a variable one letter long" in tiny, clear code snippets to make everything read better. Choosing to use double vs single quotes (single quotes signal that the string has no interpolation). Putting a space at the start/end of array and hash literals in some cases. Using .call() or .() or [] to call a lambda. There are many other little things like that. Each one seems insignificant, but together they replace all human consideration. And since Ruby is very concise and efficient (small amount of code gets a lot done), expressing your "hows", "whats", and "whys"[1] in the most readable way should be where you spend some of your time.

[1]: https://max.engineer/maintainable-code

One reason I don't like Ruby is because of the numerous ways to do things - stylistic consistency makes code easier to read and gofmt gives you a universal baseline for that consistency. So I guess this is a good thing but yeah it's weird argument. I guess the key is that this is provided as optional take-or-leave situation vs the tyranny of gofmt.

Maybe in the future we can just check-in the AST and a LLM will show us the code in whatever style it knows we like best.

> I guess the key is that this is provided as optional take-or-leave situation

It's a bit more than take-or-leave. Rubocop is configurable so individual projects could have their own style, no enforced style, or the default style.

It is, but how much time do you want to commit to setting it up "just right"? I don't like it because the defaults are so authoritarian -- if it can be proscribed it is -- one of the few times that Python beats Ruby hands-down, pycodestyle/pep8 is a linting Amsterdam to RuboCop's North Korea.
Sorry, there’s only one true formatter in Python and that’s Black.
That Go proverb comes to mind: "gofmt's style is nobody's favorite, but gofmt is everybody's favorite."

And I don't like gofmt's output, personally, but I immediately saw the benefit to community-wide adoption specifically because of my experiences with Ruby and RoR and every project having it's own specific little (typically also totalitarian, very teapot dictator in my experience) set of StyleCop configurations. Frankly, there's a high level of bikeshedding that can open yourself up to with configurable linters that I'm too old to give a shit about.

edit/ I have no horse in this race, either... I use neither of these languages today professionally.

One thing I like about prettier and gofmt is that there's no exceptions to the rules. You get what's there. RuboCop allows annotations to exclude a bit of code from the rules. This makes the code very unpleasant to read, because you have lines exclusively for the computer to read littered amongst everything else. It looks like this and I hate it: https://docs.rubocop.org/rubocop/1.59/configuration.html#dis...

Edit to add: I had experience years ago with RuboCop's auto correct making a breaking change, so I decided to distrust it. Be careful letting it change your source code.

TLDR: Rails is shipping a linter config by default in the future
(comment deleted)
Article is awful but linters are amazing and default linting is beautiful.

If you’ve coded as long as I have you’ll remember the endless bike shedding about style and random garbage that ended up in code bases. 2 spaces in a tab or 4? Who gives a shit.

My opinion is I don’t care what the style is so long as it’s consistent.

(comment deleted)
Oh Jesus Christ, here we go again.

> Imagine every novel written in the same style, Hemingway indistinguishable from Dickens, Tolkien from Rowling. It would be awfully gray to enjoy the English language if there was only a single shade of prose.

Code is not a novel and your run off the mill developer is NOT Hemingway, Tolkien or Rowling. Code is a plumbing, nothing more, nothing less.

Starting with the example, I find it counterproductive because our brains are always going for the condition first. (or my brain)

Waiting on a traffic light the thinking is "if light is red/green, then wait/cross" its not like "don't cross unless its green".

Also if there is only one obvious way to do things it's a productivity boost! I cannot stress enough how many times we have debated coding styles, wasting precious development time! No customer cares of your coding style! If you are an engineering who cares more about the length of a line or the import order instead of a critical feature for the customer, you have to rethink the priorities.

I'm still thinking about this on code style and what produces on the developers. In one hand if the medium enforces a pre fabricated style, that's not an issue among other developers anymore and a guaranteed reading style convention for all which is confort for all.

In the other hand, if the medium allows your own style, there is space created to become emotionally attached to unique coding styles.

As a preliminary conclusion, in this regard, would be to say, to what degree you value freedom of coder's expression versus commoditization of coder's work?

For libraries the answer is way less controversial. For your own apps in a tight group of very culturally aligned and productive Band of Brothers coders? Is not that clear.