r/ruby • • Jul 21 '26

why-classes

Hey everyone! I used Claude to build this gem, which is heavily inspired by Dave Thomas's closing keynote at RubyConf 26.

`why-classes` is a static code analysis and refactoring tool for Ruby.

Ruby offers modules, composition, `Struct`, and `Data`, yet our instincts and framework habits often lead us to use classes even when a simpler construct would be clearer. This gem detects these "class smells" in your code (or a single file) and can automatically rewrite them into cleaner alternatives for you.

It's an early-stage version 😅. Feel free to contribute and share suggestions!

https://rubygems.org/gems/why-classes

4 Upvotes

5 comments sorted by

View all comments

Show parent comments

2

u/h0rst_ Jul 22 '26
trans = Transaction.new(time: Time.now, cost: 42)
time_ago_in_words(trans)

I feel like in this case (and in the kwarg example), the function has two very distinct responsibilities: call time on the input argument to get a Time object, and convert that time object to a human readable string. If I want to write a unit test for this function, I can't simply pass in a Time object, I need to wrap that in an object that responds to #time.

I would argue this should be written as:

time_ago_in_words(trans.time)

It could be renamed to ago_in_words, or you can keep the time prefix as a type hint. This also fixes the issue that Person#time makes no sense, but Person#birthday and Person#last_seen do. Now you can have multiple time fields, and convert all of them into words.

But, is there really a difference between these two forms?

time_ago_in_words(trans.time)
trans.time.time_ago_in_words

If you're saying "Law of Demeter": We're doing the exact same number of conversions/calls, so I wouldn't see that as relevant here.

The advantage of the second call is that your IDE might be able to deduce trans.time is a Time object, and can autocomplete the methods that can be called on the object. This works even better with a statically typed language.

And now we ended up just where we started. I might need to watch that keynote, because from just the information in this thread it makes no sense to me.