Ruby’s module – Categories from ObjC
Today I did quite a bit of work on refactoring the existing code which represents a simple buffering storage container for the output of the pipeline in our project. The original version had a lot of things in it that had no real need - the output was ordered (why?), there were a lot of methods and nested classes that really didn't need to be there. So Jeff and I started peeling the layers back and cleaning up a lot of this code.
What we came up with was a very nice design. The store had two basic methods, and two optional ones, if it happened to maintain a state:
class Store attr_accessor :backend def store(block) self.backend.store(block) end def bulk_store(blocks) self.backend.bulk_store(blocks) end def clear self.backend.clear if self.backend.respond_to?(:clear) end def flush self.backend.flush if self.backend.respond_to?(:flush) end end
With this, we can have a very simple store class and then use it as the "backend" to the main store that just happens to be a Singleton (not shown):
class StreamStore attr_accessor :stream def initialize(stream = $stdout) self.stream = stream end def store(block) write_one(block) end def bulk_store(blocks) blocks.each do |b| write_one(b) end end private def write_one(b) stream.puts b.to_s end end
All this is nice, but it doesn't address the buffering, and that's where I've come to find one of Ruby's really nice features: Modules. You can write a module - like a class, and then you can augment an existing instance with this behavior without having to include this in the class inheritance.
Methods will be added, ivars as well - it's just like the categories in ObjC - but maybe even one step better: in Ruby you can add this to a single instance, and in ObjC you have to add it to the class everywhere in the runtime.
I'm really impressed. This is really powerful, but at the same time, it's possible to have one instance of an object have entirely different methods and ivars than another. One might think this is really cool, but from a production stand-point, it's also very dangerous. This kind of power can be abused so easily.