Hacker News new | ask | show | jobs
by berkes 1534 days ago
I was on the same page, but now moving away from that.

I more and more dislike how Ruby (arbitrarily) allows omitting brackets. but not always. Often making the code harder to read. What is the call-chain in this rspec magic: `expect(something).to be >= 1` (quick: where and how do you add a custom failure message).

And while `attr_accessor :time, :date, :state` are really neat, I more and more dislike constructs like `validates :name, :login, :email, presence: true`. And prefer to write them explicit and unambiguous: `validates_presence_of(:name) etc`. Which is only a very slightly improvement over `validates_presence_of('name')`.

And don't get me started on "saving time" by typing less characters or shorter lines of code: if this is what makes you Go To Market faster, there's something very wrong with your IDE, editor or typing skills. If anything, those short things have cost me time in Rails codebases living years and years.

3 comments

> validates :name, :login, :email, presence: true`. And prefer to write them explicit and unambiguous: `validates_presence_of(:name) etc`. Which is only a very slightly improvement over `validates_presence_of('name')`.

That's Rails, not Ruby. Although Ruby allows it because of how flexible it is + metaprogramming.

It indeed is convention in Rails. A bad convention IMO.

But it is enabled by Ruby, as you state, by how flexible Ruby is. It may seem a nice touch that Ruby hands you the freedom to choose to e.g. omit brackets. But I think this is a bad freedom. As Rails shows, its a freedom that leads to, IMO, harder to read, and harder to reason about code.

With any language design, the limitations as well as its features, is what make the language. Limitations are an important feature of a language, IMO.

Yeah this threw me off so much that I wrote a blog about this: https://wbk.one/%2Farticle%2Fa463c360%2Fthe-ruby-tutorial-i-... It’s weird how not clear tutorials are about this.
Half agreement on the last part. I never care about typing, but I care a lot about readability.

And fewer characters often is proportionally easier to read.

I wholeheartedly disagree with this correlation.

Intent sometimes becomes clearer with less characters. E.g. "attr_accessor" is, IMO, vastly superior to a large list of getter and setter method definitions. Easier to read, clearer in intent. Especially when there is that one getter or setter: you can be confident its doing more than just setting/getting (which probably is a smell, but I digress).

Details, however, hardly ever become clearer. A single `has_many :tags, :through => :taggings, delete: :cascade` may seem easier to read than explicit method declarations and callback registrations, but its a faux abstraction. It also rapidly falls apart when you continue developing on this for years and end with things like `has_many :posts, :through => :taggings, :source => :taggable, :source_type => 'Post'`

The abstraction remains in tact with a `define_relation(:taggings, DatabaseJoinTable.new(:taggins))` an `delegate :tags, to: :taggins` and a `register_callback(:delete, InlineTagginsRemover.new(self.taggings)`. I just made this up. But I tried to design an interface that is explicit rather than implicit. One that uses dependency injection and common Ruby-isms over a framework DSL.

Point is: behind those seemingly "easy to read" lines, there's a large world of black magick, lurking. I've dug through these forbidden forests on numerous occasions when our Rails app started misbehaving, race-conditions popped up, performance degraded, or even random dataloss. It's only easy to read on the surface. And while that is where we spend a lot of time reading, readability of the underlying stuff is even more important, because that is where the details matter.

Rails sacrifices the readability and understandability of what happens below the hood for readability and understandability on the surface. This seems a deliberate choice. But I dislike it. Severely.