1

I'm currently working with some code that IMO has abused ruby's mixin features. Given that I'm new to ruby, I wonder if MO in IMO is correct or not.

My primary question is what makes more sense (and if there are any major technical differences between them):

E.g.

1

to create Helper singleton classes (or Modules with class methods) to keep all my "helper" functions.

module Helper
 def foo(); p 'foo'; end # instance method
end
class User
 include Helper # foo() is now a method of User
 def initialize()
 foo() # included, invoked on User class object
 end
end

------- OR -------

2

create mixin modules that contain these functions and include them everywhere I need them.

module Helper
 def self.foo(); p 'foo'; end # class method
end
class User
 
 def initialize()
 Helper.foo() # Invoked on Helper module object
 end
end

An example of the way it's abused in my case:

module ComplexMathPerformer
 def perform_complex_math(); p 'perform_complex_math()'; end
end
module Renderer
 def render_3d_object()
 perform_complex_math() # from ComplexMathPerformer, which is NOT included here.
 end
end
module Game
 include ComplexMathPerformer
 include Renderer
 def play()
 render_3d_object()
 end
end

This code works because Game includes both Renderer and ComplexMathPerformer. But is a nightmare for someone who's looking at ComplexMathPerformer and trying to figure out where the hell is is foo() defined and how is it accessible in ComplexMathPerformer.

Logically it makes more sense to include ComplexMathPerformer but that's skipped because Game already includes ComplexMathPerformer (for it's own purposes). Making it a mess.

asked Feb 11, 2016 at 16:33
5
  • In the example you provide in #2, the dependency between Helper1 and Helper2 exists because you are declaring foo() inside Helper1. But you also allow that foo() is defined in the class itself. Commented Feb 11, 2016 at 17:00
  • @pietromenna I suppose you meant "But you CAN also allow that foo() is..." - In theory yes, but the in practice Helper1 & 2 both have 7-10 related methods each (addressing different responsibilities) with a total of 150-200 LOC so it makes sense to keep them apart. Commented Feb 11, 2016 at 17:13
  • You got me right! I have one additional question: You separated Helper1 and Helper2 because who should use the methods of each one is different, right? For example, you have class A which only needs to implement Helper1 methods, but class B does not need those, but only the ones from Helper2. The problem I see in the example is coupling between Helper1 and Helper2 modules, but not an abuse of mixin (which would be an abuse on abstractions) Commented Feb 11, 2016 at 17:20
  • @pietromenna It's more a dependency between Helpers, I updated the example to make a bit more clear. Commented Feb 11, 2016 at 17:56
  • Yeah, the class method approach is more immediately comprehensible but including a module is a fundamental thing that is frequently done, so its hard to say its abuse per se. Commented Dec 24, 2016 at 3:10

1 Answer 1

2

By checking the examples, IMHO, there is no abuse of the mixin feature of Ruby, but coupling between the modules ComplexMathPerformer and Renderer.

Mixin abuse is generally felt by developers when too much abstraction exists. Mixins should be used when you need to share behavior between a couple of classes.

Modules are usually used when you need to create functions more as functions (methods without state).

Maybe ComplexMathPerformer logic should be inside the game, or in another class which the Game consumes and not as a Module in your case.

answered Feb 11, 2016 at 19:07

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.