DEV Community

Nick Schwaderer
Nick Schwaderer

Posted on

3 1

Ruby Science Saturday: use Mixin Modules or Reopen Classes? πŸ‘©β€πŸ”¬πŸ”¬πŸ§¬πŸ§ͺ

Ruby legend Xavier Noria recently penned a tweet that got me thinking about how we organize and package up our native Ruby code:

Xavier Noria Tweet

How often do we just dump our code into mix-in modules (that never get reused) when our classes get too large? What if we continued to organize our code into separate files, but reopened classes?

This is something we can debate all day in the comments, but that sparked my Ruby Science question:

What if one of these approaches was faster?

Well, thanks to benchmark-ips, (which I have also bundled into my own performance logging gem) we don't have to wonder.

I fired up three example cases (Reopen, Include mixin module, Extend mixin module) and ran them against each other in a simple test case. Code below:

module MixinDependency
  def open_door
    puts 'Door is open!'
  end
end

class DoorOpenerMixin
  include MixinDependency

  def close_door
    puts 'Door is closed!'
  end
end

class DoorOpenerMixinExtend
  extend MixinDependency
end

class DoorOpenerReopen
  def close_door
    puts 'Door is closed!'
  end
end

class DoorOpenerReopen
  def open_door
    puts 'Door is open!'
  end
end

And we tested it with:

require 'benchmark/ips'

Benchmark.ips do |x|

  x.report('Include') { DoorOpenerMixin.new.open_door }
  x.report('Extend') { DoorOpenerMixinExtend.open_door }
  x.report('Reopen') { DoorOpenerReopen.new.open_door }

  x.compare!
end

Results? Nothing exciting.

Comparison:
              Extend:   214816.5 i/s
              Reopen:   197784.3 i/s - same-ish: difference falls within error
             Include:   182298.2 i/s - same-ish: difference falls within error

Even inconclusive findings are still findings, and I hope you enjoyed seeing how I picked through this hypothesis to give a clear answer. If you're unfamiliar with benchmark-ips, copy this code and try it out yourself! It really is one of my favorite tools in my toolbox.

One small but fun finding, I tried running this on different Ruby versions, you can see a clear speed bump since Ruby 2.1! Here's the results on the old version:

Comparison:
              Extend:   178840.8 i/s
             Include:   167210.7 i/s - same-ish: difference falls within error
              Reopen:   166005.2 i/s - same-ish: difference falls within error

If you have any 'experiments', feel free to share your results and thoughts below! πŸ₯Ό πŸ€”

πŸ‘‹ While you are here

Reinvent your career. Join DEV.

It takes one minute and is worth it for your career.

Get started

Top comments (2)

Collapse
 
ludamillion profile image
Luke Inglis β€’

One of the big reasons I’ve preferred mixins over reopening classes is that it β€˜reads’ a bit better. To me there is less cognitive load to thinking about collections of like behavior separated out into modules which are self-documenting rather than having the same class opened in multiple places which can β€˜hide’ behavior.

I usually take the β€˜middle way’ when trying to thin out my classes and extract common behavior into service objects.

Collapse
 
schwad profile image
Nick Schwaderer β€’

I think you're right. There's a benefit to using well-trodden patterns to keep code readable for others as well.

Plus in my mind I do like one file being the 'home base' for a class, and then using mixins to group and store methods used by it elsewhere.

The class-reopening-approach definitely is used a lot more in gems though (in my experience!)

Heroku

Simplify your DevOps and maximize your time.

Since 2007, Heroku has been the go-to platform for developers as it monitors uptime, performance, and infrastructure concerns, allowing you to focus on writing code.

Learn More

πŸ‘‹ Kindness is contagious

Explore a sea of insights with this enlightening post, highly esteemed within the nurturing DEV Community. Coders of all stripes are invited to participate and contribute to our shared knowledge.

Expressing gratitude with a simple "thank you" can make a big impact. Leave your thanks in the comments!

On DEV, exchanging ideas smooths our way and strengthens our community bonds. Found this useful? A quick note of thanks to the author can mean a lot.

Okay