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

Can we talk about Ruby’s laissez faire approach to syntax. Ignoring all the purely technical stuff every ruby project I’ve seen that has at least a small team behind it looks like a kitchen sink. Bob does it X way, Tina does it Y way, Joe does it X way. Every person does it their own way and readability becomes an eyesore as the project grows.

If I didn’t know any better I’ve seen teams so bad it’s almost a game of “look how gross this block is, now let’s see how much worse you can make the next one”.

I’ve always found ruby very off-putting for this reason alone. I don’t want to inherit or work on something where everyone just wants to show off. How do organizations manage this? Is it just me?



There are multiple ways to do things in many languages. And Ruby is a rather sane one.

The worst language in that regard is Scala by far.

There are the "Scala is Haskell" people where everything is a pure function and written in point free style.

There are the ones who think Scala is just Java with type inference.

And the everything needs to be a DSL people.

Or everything needs to be implicit and generic in a static singleton.

There are a bazillion ways to write the most trivial stuff. Use for comprehensions, recursion, higher order functions, or your usual for each loop. If you hate your coworker use some fancy type system trickery. Does not matter pick and choose.

Ruby is mostly confined compared to many similar languages like Python.

I would say that even JavaScript is way more chaotic in that regard.


When it comes to showing off with Ruby, I think that only occurs in two cases: creating unnecessary DSLs (cough Rspec) when plain Ruby was already adequate, and doing as many chained collection operations in one line as possible.

The former adds a layer of abstraction which is often unnecessary, and the latter can go from succinct to slightly-too-clever to fully obfuscated.

As others have mentioned, Rubocop can help keep some uniformity (although some of the default rules suck, imo). And beyond that, the company just has to have people who agree to be decent. It will happen that developers of different skill levels will write more or less readable code depending on the perspective of the viewer, but that's true in all languages. You _could_ write Ruby code like you would write Basic.


The solution is the same as in many other programming languages: adopt a coding standard and enforce it in an automated fashion, i.e. in the CI/CD pipeline. Code style then becomes mostly a non-issue and not an object of discussion.

In the case of Ruby:

* most popular style guide: https://rubystyle.guide/

* automated tool for linting and enforcing code style: https://rubocop.org/


I just would like to point out that even though that is the most sane way, it comes with it owns set of problems. One of them is when developers start to code to cheat the linter, or they complicate the code just to "make the linter happy", another is when the linting rule introduces problems/errors like https://github.com/rubocop-hq/rubocop-rails/issues/418


Yeah I would never recommend relying on just a linter. The linter can reduce scut work, but you always want to have at minimum a thorough code review process that’s looking at things like “ok, we made the linter happy; but are we happy with the result, or should we have just disabled the linter here?” and “the linter didn’t catch that we solved this thing with X here but with Y&Z last time. Let’s rationalize our approaches and get everything on the same page”


yes, well that's in the ideal world. In the reality, the "linter said so" is said sadly quite often.


Following Rubocop's Ruby Style Guide [1] to the dot helps a lot with this, and it's quite easy to enforce using the rubocop gem + a GitHub action

[1] - https://github.com/rubocop-hq/ruby-style-guide


I wouldn't really go that far though, as you'll end up with a codebase that the linter likes (and appears clean) but is still an utter nightmare to read because of all the forced indirection. I'm talking about things like: restricting method length to 10 lines, restricting class length to 100 lines, and similar ones that prevent you writing code in a certain way because the preferred approach to writing code is 'out of sight, out of mind'.

Default Rubocop is why you have codebases where code is still complicated, it's just hidden away inside single use modules (concerns) or inside single-use private methods. As far as I'm concerned you just can't defer the architecture of your codebase to a tool like that and I'm sure it teaches more bad habits than good ones.

Instead, decide these things for yourself and keep it in check during code review or the stage before that. Maybe even design rubocops of your own to help. The linter can still do a good job without telling you how to handle complexity.


Very refreshing to see this take and I largely agree. People all too often refer to linters as The Rule rather than The Tool, and forget that a robot will never be able to evaluate the quality of a codebase. That requires human input (though Rubocop is very efficient for people that want to avoid human input--often the root cause of the problem).

That said, I am a fan of single-use private methods and think they have their place, with or without method-length rules.


You can configure rubocop however you want.

If you find the defaults to be not good (which I agree), then simply update the rubocop.yml.


In fairness, ljm was responding to a comment that suggested following the style guide "to the dot".


That was that's exactly the point I was aiming to address, thanks :)


Couldn't agree more. Our Rubocop is FULL of customizations and the odd override too (though there is a case some overrode a rule which caused massively confusing code).

"Single use private methods" is a little triggering to me... not even rubocop's fault. I've seen the likes of this before (single use):

  def redirect_to_home_unless_user_present
    redirect_to :home unless user.present?
  end
Why!?? (that is a rhetorical "why")


That's a horrible usecase for single use private methods, agreed. But I think they're an excellent way to breakdown a complex chunk of code into smaller components, using the method names to describe what they're doing. That requires good naming, though; without good names, the effort is moot.


I think they serve a good purpose once you realise you've stepped out of OOP. You have the idea of a command, or a service, and it does a bunch of procedural things as part of its execution. It only has one public method, so the private methods are a way to describe the steps of the command.

But that's an architectural decision, it's not code style. If rubocop tells you how to write a function then you're going to see nonsense like the example in our parent comment.


> I think they serve a good purpose once you realise you've stepped out of OOP. You have the idea of a command, or a service, and it does a bunch of procedural things as part of its execution. It only has one public method, so the private methods are a way to describe the steps of the command.

It doesn't have to be a step out of OOP, and their usage is not limited to "Single Public Method Objects". Single use methods are just a convenient and clean way to make complicated code easy to digest, OOP or not.


I'd argue the issue is better acknowledge in ruby than in many other popular languages, which just assume having few options means everyone can mostly code as they want from there.

Sister comments are pointing to rubocop which mostly makes it a solved problem. I'd add that having multiple potential ways to do things, and being able to also favor a specific way through linting is very powerful.

You can actually choose the best option for your current project and enforce it, while choosing a different tradeoff for another project and still enforce it there. And you still can opt-out of the rules on a case by case basis in a standard way.


> Can we talk about Ruby’s laissez faire approach to syntax. Ignoring all the purely technical stuff every ruby project I’ve seen that has at least a small team behind it looks like a kitchen sink. Bob does it X way, Tina does it Y way, Joe does it X way. Every person does it their own way and readability becomes an eyesore as the project grows.

This is why Python has deliberately chosen to not add Ruby's blocks. To make any code readable by everyone. (And to prevent bad coding patterns that blocks promote, but that's besides the point.)


That's not exclusive to Ruby, though. Is there a language in which a project of at least a small team would not diverge?

Devs at my current dayjob have established, in multiple rounds, that it is impossible to find at least a minimum of viable coding standards, where every draft has been heavily opposed.


> Devs at my current dayjob have established, in multiple rounds, that it is impossible to find at least a minimum of viable coding standards, where every draft has been heavily opposed.

Tangential, but this mostly sounds like a leadership issue? Ultimately software development is a team sport, and teams work if and only if individuals put the team's interests ahead of their own – and it's not realistic to expect a group of individuals to develop that mentality by consensus. Absent leadership, all you have is a bag of individuals who will bicker about the bikeshed endlessly.

A good leader would hear that feedback and accommodate it to an extent, but they also have to take the responsibility for saying "alright folks, I've heard your feedback, but ultimately it's more important to the team as a whole that we have something than it is that everybody got that something to be what they liked most. This is arbitrary, but this is what we're running with, so it's time to fall in line".

(This is something of a pet peeve of mine, as my team occasionally has to work with an ops group that is stuck in the stone age solely because they've lacked clear leadership for a decade or more. Every time they meet to discuss aligning and modernizing their approach ends in a lack of consensus as to how, and consequently in 2021 they continue to manage their servers each by hand, each in their own way, a collection of expensive single points of failure. Literally any approach they discuss would improve on the status quo, so any competent leader at this point should simply roll the dice, pick one at random, and get on with the task of moving forward)


While not perfect, Go has much more "developer convergence" than any other language I've worked in. Ruby has numerous ways to do the same thing, but one of Go's design objectives was to minimize that.

So divergence does occur, but some languages make it a lot easier than others.


We can talk about anything we want. Don't even have to open the link. Now let me tell you what I think about Ruby...




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

Search: