Second thoughts on initializing modules

February 15, 2010 Pivotal Labs

This morning Yehuda Katz posted a response to my previous post, Technique for extending a method from a module, showing how a more modular organization of the Person class would allow for a solution that does not require a crazy meta programming hack. The idea is that by extracting the method we want to decorate into an ancestor class, Ruby makes it a lot easier to do what we want.

Previously I was aware that there were other ways I could structure the host class to make the module’s job easier but I did not try that because but I was writing the code with the knowledge that I would only be in control of one side of the equation, the module. The host class was going to be written by the end-user of the Rubygem the module was to be packaged in. Since I did not want to try dictate how the end-user structured the host class I ended up adding a lot of complexity to the module. The goal became how to write the module in a such a way that the class would “just work” upon including Teacher without requiring any additional steps to be taken. Asking the user to create an AbstractPerson class that contained their initialize method and then creating a subclass felt like an obtrusive request to make through a README that would ultimate negatively impact the user’s experience with the library.

Shortly after I put that blog post up I got this tweet from Josh Susser:

egad! are you sure you're solving the right problem?

I was trying to solve how to decorate the initialize method from a mixed-in module. My real problem however, was that I was trying to modify the behavior of the host’s initialize from a module which is a good way to get into trouble. I am now of the opinion that if the module does need to be instantiated in some way, a good solution is to provide a initialization style method that the host class can call.

class Person
  include Teacher

  def initialize
    initialize_teacher
    # initialize person
  end
end

An added benefit of this approach is that initialize_teacher can be called from anywhere, and doesn’t have to happen within Person.new. This explicit instantiation violates my original goal of being unobtrusive to the user but it sidesteps the can of worms that the original approach has. One obvious problem that was likely to come up was the case where the module’s initialize needs to take a parameter. Once that happens it is not longer completely transparent to user. Even worse is if the host class’s initialize needs to take it’s own parameter. At that point it falls apart completely.

Credit to Austin Putman for suggesting this in a comment on the first post. Also thank you to Yehuda Katz for his informative post on writing modular ruby code.

About the Author

Biography

More Content by Pivotal Labs
Previous
What’s so funny ’bout pseudo-classical inheritance (in JavaScript)?
What’s so funny ’bout pseudo-classical inheritance (in JavaScript)?

Our customers are asking for richer interfaces and user experiences. And so we - and by "we" I mean the Rai...

Next
Technique for extending a method from a module
Technique for extending a method from a module

Update: Read the follow-up post Second thoughts on initializing modules I was recently presented the probl...

How do you measure digital transformation?

Take the Benchmark