codahale.com٭blog

This is my old blog. My current writing is here: codahale.com

Singletons: Only The Lonely

I’ve never really spent much time on design patterns, but recently I’ve been reading Head First Design Patterns and I can’t help but notice how much easier Ruby makes certain patterns. Composition over inheritance becomes as easy as sneezing with mixins, and the thoughtful Ruby folks have already implemented quite a few.

I don’t use Singleton as much as I should (preferring instead to just stuff all the methods in the class), but for objects which have an expensive or complicated instantiation method, it’s extremely useful. (I mean, that’s why it’s a pattern, right?) Also, the Singleton mixin takes care of all the threading complications to which Singletons often fall prey.

But effective and useful it may be, Singleton is ugly, and for one big reason: instance. I hate typing instance all over the place, and it’s been a big stumbling block in my acceptance of the Singleton mixin. I understand why it’s there–the pattern doesn’t mention moving methods from instance to class scope–but on a syntactic level it irks me. If I’m using a singleton, I really shouldn’t need to know that it is a singleton–it could be a magic happy fairy princess castle for thread-safe methods, for all I care.

So yeah, I went and did something about it. I combined the power of Singleton and Proxy. Check it out:

module Singleton
  class << self
    def included_with_proxy(base)
      included_without_proxy(base)
      base.class_eval do
        class << self
          def method_missing_with_proxy(m, *args)
            if instance.respond_to?(m)
              instance.send(m, *args)
            else
              method_missing_without_proxy(m, *args)
            end
          end
          alias_method_chain :method_missing, :proxy

          def methods_with_proxy
            return (methods_without_proxy + instance.methods).uniq
          end
          alias_method_chain :methods, :proxy

          def respond_to_with_proxy?(m)
            return respond_to_without_proxy?(m) || instance.respond_to?(m)
          end
          alias_method_chain :respond_to?, :proxy
        end
      end
    end
    alias_method_chain :included, :proxy
  end
end

You’ll need to require singleton and activesupport for this one, and since it uses alias_method_chain, you’ll need to either be running Rails edge or grab it from the source.

What it does is pretty simple: if it’s not already a class method, Singleton passes it on to its instance:

class Magician
  include Singleton

  def dove
    "*poof* A dove!"
  end

  def segway
    "*rides Segway around*"
  end
end

Magician.dove   #=> "*poof* A dove!"
Magician.segway #=> "*rides Segway around*"

No more instance, though it’s there if you need it.

14 Responses to “Singletons: Only The Lonely”

  1. josh Says:

    Sweet! I was just going to do this myself. Now I don’t have to.

  2. atmos Says:

    I’d seen someone on IRC griping about this the other day, nice one.

  3. josh Says:

    atmos: That was me griping. I wasn’t kidding when I said I was *just* going to do this myself :-)

  4. brad Says:

    Nice bit of coding (your ruby fu is strong)…but I think if you’re going to use singletons, you should be forced to use ‘instance’. It serves as a good reminder that you’re using a singleton rather than a class method and if you keep having to type ‘instance’, maybe you’ll realize eventually that either you really should be using a class method or that you really should just be instantiating a real object.

    Here’s a good read:
    http://www.cabochon.com/~stevey/blog-rants/singleton-stupid.html

  5. Coda Says:

    Brad–So using instance builds character? ;-)

    I’m well aware of Singleton’s less-than-favored status (esp. with static language programmers), but I needed this for a very specific project, and the alternative looked something like this:

    Singleton.instance.do_something(other_function(Singleton.instance.do_something_else(another_function(whee))))

    (And yeah, this could be restructured to use a code block.)

    Really, though, I like metaprogramming, and this seemed like fun. ;-) I’ve got a pet project I’ve been working on, and I’ve spent the past week or so shuffling the classes around, and this seemed like a neat bit of Ruby hacking. I may refactor out the proxying bit into a ClassProxy mixin or something.

  6. evan Says:

    I’m curious why you needed the above line. I’ve used singletons about once in a real project (seriously), and it was a textbook case, an agent dispatcher in a mobile networks simulation.

  7. Coda Says:

    Shortly after I wrote that comment, I went back and refactored the code to use a block. That chunk was just bad code. I’ve been playing around with a really broad markup–>HTML renderer, trying out different internal configurations, and I had stuffed the rendering functions into a singleton. Brad was right for that particular usage–singleton was a bozo move. I’m still far from done with the refactoring, but Hampton is getting on my case about spending all my time fiddling with classes, so I’m putting it off for later.

    That said, I am using this code (refactored out into SingletonProxy) for a data object which will be tossed around by a few BackgrounDRb processes, and I think that’s a valid usage, especially since the Singleton mixin is thread-safe. Brad’s point remains valid, but I also remain lazy. ;-)

  8. Julik Says:

    Coda, you seem to have forgotten that Ruby classes have instance vars, which entitles you to write a singelton inside of the eigenclass. Thus, your example is effectively reduced to:


    class TallMagician
    class 234
    TallMagician.get # => 234

  9. Coda Says:

    Julik–I’m not at all sure what you mean, and your code snippet confuses both me and the Ruby interpreter–did Wordpress eat some of it? 234 isn’t a valid class name, and unless you’ve already defined it elsewhere, TallMagician.get isn’t going to give you anything but a NoMethodError. What would instance variables have to do with adding singleton methods to an object? One of my favorite characteristics of Ruby is that I’m constantly replacing big chunks of my code with small, elegant bits, so I’m curious to know what you mean.

    Also, on a side note: Brad–I’m using this method in Blame Game, so, uh… there. ;-)

  10. Julik Says:

    WordPress ate my code for breakfast.

    What I meant is that you can do the class «« self trick and hop into the “class level” of methods avoiding the module altogether. Just write your methods directly onto the class.

    Classes in Ruby have ivars as well by the way.

  11. Julik Says:

    god, I hate commen cleanups. But I hope you know what I meant. To repeat:
    http://pastie.caboo.se/10447

  12. Coda Says:

    Julik–Sorry about WordPress munging your code; it seems to happen sometimes.

    And yes, you’re right, adding simple class-level methods works fine, but that approach lacks the thread-safety provided by the Singleton mixin.

  13. Julik Says:

    Sure, I missed that point. Thumbs up to you Coda :-)

  14. Coda Says:

    Also you can’t really control when a class is initialized, whereas a class with the Singleton mixin isn’t initialized until you need it.

    That said, your approach is far easier and is probably the right approach given that the vast majority of Rails programming doesn’t involve concurrency.