ruby picture

RCR 246: Rename singleton.rb

Submitted by austin (Thu Apr 15 10:04:34 UTC 2004)

Abstract

Rename singleton.rb to singletonpattern.rb and the module it implements from Singleton to SingletonPattern.

Problem

There is often confusion when discussing singletons, because it is not always clear when we are discussing singleton objects (class << o; end) or objects that implement the GOF Singleton pattern.

This proposal is not so much about programming Ruby as programming the Ruby community. See the short discussion in https://rcrchive.net/rcr/RCR/RCR231">RCR231.

Proposal

Rename singleton.rb to singletonpattern.rb and the module it implements from Singleton to SingletonPattern.

Alternatively, move it from singleton.rb to patterns/singleton.rb and implement the module as Patterns::Singleton (which would suggest that the third-party library Multiton would then become Patterns::Multiton and observer.rb becomes Patterns::Observer). The latter is a longer-term and more sustainable change, but is also more broad-spectrum.

Analysis

There is significant confusion between the various meanings of singleton in the Ruby community that is at odds with most other language communities. Because people are most used to hearing "singleton" refer to an implementation of the Gamma, et al. Pattern "Singleton", it is not immediately clear that "singleton" refers to the object's singleton class. This will help disambiguate discussions.

Implementation

Implemented by renaming and/or moving the singleton.rb and modifying it such that the module is either renamed or wrapped within another module, Patterns.
ruby picture
Comments Current voting

Is it possible, that singleton.rb should be avoided, if we look at following facts:

Singleton means there is only one Object.

With singleton.rb there are two objects, once the object and again an object of , which can be accessed with .instance.

In GOF, there are listed 5 consequences of using the pattern:

  1. controlled access to sole instance
  2. reduced name space
  3. permits refinement of operations and representation
  4. permits a variable number of instances
  5. more flexible than class operations

1.-3. are the same with and without singleton.rb . 4. and 5. means, sometimes you decide to change from singleton to factory controlling the instance count.

So, if I want to change, I remove class << self and add a factory method to the class.

The main difference is the initialization of the Class object. Therefore, there have to be a pattern for only initializing once, like undefing the init method after calling it, which permits also an easy change to factory pattern. Also it have to be clear, when the initialization takes place, which is a bit strange with Singleton#instance, I find.

Do i make some serious error in reasoning ? Is singleton.rb useful anymore, if we have an advanced class initialization scheme ?

-- Matthias Georgi


Simon: I'm not sure that all patterns need to go into the Pattern namespace, but it's a good collection. From a usage perspective, though, it would be possible to "include Pattern" and have access to Pattern::Iterator::Collection as if it were still Iterator::Collection. If we use the Pattern namespace, then it definitely should go in lib/patttern/singleton.rb, as an example.

Matthias: I'm not sure that I understand what you're saying here. From a practical perspective, there is only a single instance with the use of Singleton (singleton.rb). The module Singleton provided by singleton.rb simplifies the implementation of making a GOF Singleton pattern object. Using Singleton, you simply do:

  class MySingletonObject
    include Singleton
  end

MySingletonObject.new is made private and a new method MySingletonObject.instance is provided. As I understand it, there is the Multion pattern that should be as simple to implement (e.g., "include Multiton"). There is no removing "class << self" involved. I think that singleton.rb is still useful, but it needs to either be renamed or put into a different namespace. -- Austin


Well, what I meant, was


class MySingletonObject
  singleton_class do
    def initialize
    end
  end
  initialize
end

As you see, this is simpler and does nearly the same.


It doesn't do the same at all, presuming that singleton_class does much the same as class << self; self; end. The Singleton module does, more or less:

  class MySingletonObject
    class << self
      private :new
      def instance
        ...
      end
    end
  end

It has been a while since I've used singleton.rb, but it is not related to class << self (the singleton class object for the class of MySingletonObject). Quite honestly, I'm not seeing where you're going because of this. It is easier to tell people that they can make an object have one and only one instance by doing "require 'singleton'; include Singleton" in their class definition. -- Austin Ziegler


I just wanted to point out that the singleton pattern exists inherently in the singleton class itself, which can be used _without_ creating an instance. -- Matthias Georgi


Matthias, if you run your code with this added:


m = MySingletonObject.new p m m = MySingletonObject.new p m

(and with your block version of singleton_class) you'll see that you're not actually doing the equivalent of Singleton. You can create two different instances of MySingletonObject.

I'm not sure whether there's a way to implement Singleton using singleton classes. I don't think it's necessarily important, though, especially if it's only done to make sense in retrospect of the coincidence of names. I think it's better to break the names out, as Austin suggests.


I am voting yay for the Pattern::Singleton and pattern/singleton.rb modification. Beyond the points made by Austin, it follows the scheme of keeping the root dir of lib/ relatively clean . As far as removing singleton completely, I think too many people use it for it to be removed, but it is worth getting more opinions about it. -- Zachary P. Landau


I was reading through my major backlog of ruby-talk archives and I found that points out that a proper singleton (ensuring only one instance of a class) could be used to control access to a database that doesn't do concurrency very well.

Also, to the anonymous poster before Zachary, thank you for saying what I was finding difficult to say. The Singleton Pattern is intended to restrict instance creation; the separate MySingletonObjects would actually have separate singleton classes. While the pattern could be generalised to a Pool of objects (with count 1), I think the case of one object and only one object is common enough to warrant Singleton. -- Austin Ziegler


I admit, I left something out, I just wanted to give a hint. To show a working example:


module Kernel
  def singleton(&block)
    s = class << self; self; end
    s.class_eval(&block)
    s.class_eval do
      private :new, :allocate
      def instance; self; end
    end
    initialize
  end
end
class MySingleton
  singleton do
    def initialize
      ..
    end
    def hello
    end
    ...
  end
end
MySingleton.instance.hello MySingleton.hello

-- Matthias Georgi


IMO if Singleton is to be put into a module/namespace, it should be Antipattern::Singleton, not Pattern::Singleton. Blind use of the singleton pattern makes for code that is difficult to unit test, and I think unit tests are something the Ruby community would like to keep as one of its defining characteristics.

I also think that renaming singleton.rb or moving Singleton to a module solely to reduce confusion with the singleton class is a bad idea (since it will break existing code). Newcomers to Ruby come in with an idea of what "singleton" means already and so they will be confused when they see "singleton class" if it is not explained to them. It would be better to either clearly address this in a FAQ somewhere (explaining the difference between the two and why singleton class is a singleton of its own right), or start a movement to start writing metaclass instead of singleton class.

-- Paul Brannan


Strongly opposed 0
Opposed 0
Neutral 0
In favor 5
Strongly advocate 1
ruby picture
If you have registered at RCRchive, you may now sign in below. If you have not registered, you may sign up for a username and password. Registering enables you to submit new RCRs, and vote and leave comments on existing RCRs.
Your username:
Your password:

ruby picture

Powered by .