Another approach to singletons

Posted by Thomas Mercer-Hursh on 15-Mar-2012 14:12

In discussion, I have been introduced to another approach to singletons which might be of interest to some of those having issues with non-deleteable statics.   If one defines a class, a singleton manager, if you will, which has a static variable to hold a class instance and a static method to retrieve that instance or simply a static property for the instance, that class can return the instance of a class one desires to be a singleton without the singleton having any statics at all.  Thus

class Singletons:

  define static property OneX as class X
    get():
      if OneX = ? then OneX = new X().
      return OneX.
    end get.
    private set.
   
end class.

then, any code which needs a singleton copy of X can say

MyX = Singletons:OneX.

and get a singleton copy of X.    The advantage of this approach is that one can also provide a DeleteX method which gets rid of X, since it has no statics and the only thing that remains in memory is the Singletons class.   And, the Singletons class could manage multiple singleton classes, although, of course, there is an issue of coherency there.  And, if one wanted, one could supplement the get with reference counting, provide a method for decrementing the count, and provide one's own garbage collection on the singletons.

Naming is, as usual, up to personal taste.

Not beautiful, but it might get someone past some of the sticky issues of using statics.

All Replies

Posted by jmls on 15-Mar-2012 14:43

err, this is old hat ... We use this mechanism all the time now, for the reasons you mention (unloading if required etc)

2009 http://communities.progress.com/pcom/message/27913#27913

2010 http://communities.progress.com/pcom/message/85780#85780

Posted by Thomas Mercer-Hursh on 15-Mar-2012 15:04

It is old hat to have a class with a singleton getInstance method or Instance property which returns an instance of *that* class.  But, that means that one has a class which has at least that one static element.   In this case, the class returned is *not* the class in which the static resides, so there are *no* static elements in the singleton class.

Posted by jmls on 15-Mar-2012 15:19

from dotr.hash42 (16 months old .. )

using Progress.Lang.*.

using dotr.hash42.Config.Asterisk.*.

/** instance handler

*  this class manages all the instances for the various singleton library classes */

class dotr.hash42:

  /** the skin instance for hash42 */

  def public static property Skin as class dotr.hash42.UI.Library.Skin no-undo

  get():

    if not valid-object(Skin) then Skin = new dotr.hash42.UI.Library.Skin().

    return Skin.

  end get. private set .

  /** windows API instance */

  def public static property WindowsAPI as class dotr.hash42.Utils.WindowsAPI

  get():

    if not valid-object(WindowsAPI) then WindowsAPI = new DotR.hash42.Utils.WindowsAPI().

    return WindowsAPI.

  end get. private set .

  /** the Session instance for hash42 */

  def public static property Session as class dotr.hash42.Session

  get():

    if not valid-object(Session) then Session = new dotr.hash42.Session().

    return Session.

  end get. private set .

end class.

Posted by Admin on 16-Mar-2012 01:19

tamhas wrote:

It is old hat to have a class with a singleton getInstance method or Instance property which returns an instance of *that* class.  But, that means that one has a class which has at least that one static element.   In this case, the class returned is *not* the class in which the static resides, so there are *no* static elements in the singleton class.

guess  that 'old hat' is what a singleton is all about... if the class really  is a singleton then the fact that there should be only one instance of  it should be enforced by the class itself and don't rely on somebody  else to do it.

that new version of singleton looks more like a service factory to me,  something that could also serve very well for things like dependency  injection but I wouldn't call that 'singleton'

Posted by bheavican on 16-Mar-2012 01:31

Thank you for your message. I am currently out of the office, with limited access to email.

I will be returning on Monday, 03/19/12.

Brent

Posted by Admin on 16-Mar-2012 01:36

that new version of singleton looks more like a service factory to me,  something that could also serve very well for things like dependency  injection but I wouldn't call that 'singleton'

Unless the class instance itself verifies using the service factory that it is the one and only instance of that class.

But that will create a dependency between the class and the service factory that may not be desired at all.

Posted by jmls on 16-Mar-2012 01:39

marianedu wrote:

guess  that 'old hat' is what a singleton is all about... if the class really  is a singleton then the fact that there should be only one instance of  it should be enforced by the class itself and don't rely on somebody  else to do it.

that new version of singleton looks more like a service factory to me,  something that could also serve very well for things like dependency  injection but I wouldn't call that 'singleton'

you can ensure that the singleton cannot get created by anything else but the "session library" by making the constructor of the singleton take a session library key as a parameter, and making the default constructor private.

fugly, but it works

The real important thing about the "new singleton" is that as it has *no* static members, so the entire class is not permanently loaded into memory, with all the associated problems that has.

Posted by Admin on 16-Mar-2012 01:48

jmls wrote:

marianedu wrote:

guess  that 'old hat' is what a singleton is all about... if the class really  is a singleton then the fact that there should be only one instance of  it should be enforced by the class itself and don't rely on somebody  else to do it.

that new version of singleton looks more like a service factory to me,  something that could also serve very well for things like dependency  injection but I wouldn't call that 'singleton'

you can ensure that the singleton cannot get created by anything else but the "session library" by making the constructor of the singleton take a session library key as a parameter, and making the default constructor private.

fugly, but it works

The real important thing about the "new singleton" is that as it has *no* static members, so the entire class is not permanently loaded into memory, with all the associated problems that has.

sure you can, hopefully there is something like an IService interface that need to be implemented by those 'services' - might also have a method called isSingleton to let the service factory new what to do when a new service instance is requested... the point is, this is not a singleton as we know it so I don't see why we have to name different things the same way, doesn't look very helpful for me

and this also implies that your 'session factory' is a singleton itself otherwise different instances of it would each instantiate one service 'singleton'.

Posted by Admin on 16-Mar-2012 02:01

mikefe wrote:

Unless the class instance itself verifies using the service factory that it is the one and only instance of that class.

But that will create a dependency between the class and the service factory that may not be desired at all.

even if the dependency is something desirable or accepted the singleton would have to rely on the factory to be a singleton, otherwise different factory instances will load separate instances of our singleton... having a public constructor that gets the factory as input still leave it open for others to get around the factory and call it directly, if there is already an instance there is no way to return that particular instance from the constructor and the only option would be to throw an error... this doesn't look like what a singleton should do does it?

Posted by jmls on 16-Mar-2012 02:12

by definition, the "session factory" (see, even this old brain is still capable of picking up the new jargon for doing old things)  is a pure singleton, with nothing but static properties . There is no logic in there except that to get the instance of the other "Single Instance Classes".

Perhaps we should define these classes as SIC 

Posted by jmls on 16-Mar-2012 02:21

it's back to the old proposition - if a developer has access to source

code, they can always find ways to subvert the system. In a true

singleton, they could change the private constructor to be public and

create a new instance that way.

My guys don't want to subvert the system - they just want an easy way

to ensure the right things are running without having to remember to

instantiate everything.

Posted by Admin on 16-Mar-2012 02:32

jmls wrote:

it's back to the old proposition - if a developer has access to source

code, they can always find ways to subvert the system.

you  don't have to have access to the source code to call a public  constructor that just sits there, a singleton doesn't have a public  constructor... it's advisable to make it protected though (for unit  testing, see Tim's post on your other thread about statics... find that the hard way myself ).

but after all if you like to call that the new singleton I don't have any issue with it

Posted by jmls on 16-Mar-2012 03:11

to be perfectly honest, I am finding that I am falling out of favour with singletons or statics of any sort, with the possible exception of a single entirely static class consisting of just static properties for things like TerminalID, SessionGUID etc

unless you have a really tight loop spanning several thousand iterations, instantiating a new instance (especially with -q ) is so relatively fast the startup time is not noticable.

in fact, the latest iteration of Maia does away with the static helper classes entirely

we used to say

message dotr.Maia.Sports:Helper.Customer:Find(123):Cust-name view-as alert-box

we now say

message (new Model.Customer()):Find(123):Cust-name view-as alert-box

or

message (new Model.Customer(123)):Cust-name view-as alert-box

in other scenarios where we used to say

dotr.Hash42:PBX:ConferenceRoomList()

we now say

(new dotr.Hash42.PBX():)ConferenceRoomList()

both the above mechanisms take less than a millisecond to load and execute, so to my mind there is no point in having the static dotr.Hash42 class

This was a big thing with 10.1 (possibly 10.2A (can't remember)) , as there was no abl garbage collection, so doing the (new foo()) actually physically caused a memory leak. In this case we had to do the following

def var a as dotr.Hash42.PBX.

a = new dotr.Has42.PBX().

a:ConferenceRoomList().

delete object a.

because of this, it made sense to have a static helper or property pointing to an instance of dotr.Hash42.PBX

Since we now have the automatic GC , the disposal of the temporary instance is now handled for us, and we can do (new dotr.Hash42.PBX():)ConferenceRoomList() with impunity

IMHO there is no need now to have singletons / statics with the exception of the edge case described in the first sentence.

Posted by Thomas Mercer-Hursh on 16-Mar-2012 11:27

Having bashed this thoroughly in the ground, a couple of points:

* "New" is not the right word.  "Another" is a better word.  Not that people haven't done it before, but that I haven't seen it documented here before.  In fact, the source was not new at all, but rather the other way around.

* Yes, as a general rule, one would prefer that the class enforce its own singletonness.  Obviously.  I offered this simply for those cases where there was a reason why people were reluctant to use statics to create a singleton.   If one does not have those concerns, it is clearly better for the class to do it itself because it is more cohesive, more positive, and avoids the use of a helper class.

* Which said, I agree that singleton's and statics are often over used.  Often, the singleton nature of a class is something inherent in its relationships and there is actually no need to enforce that with special coding.  Statics are often used as a fancy version of a global variable and are equally dubious.  They have some very valuable uses, but one should try to talk oneself out of them before blithly using them.

Posted by durkadurka005 on 16-Mar-2012 13:50

If you want to see some interesting uses for singletons, check out how some languages like Ruby or Smalltalk implement metaclasses. Ruby's metaprogramming abilities that arise from this, in particular, make it quite powerful.

Posted by Peter Judge on 19-Mar-2012 13:47

jmls wrote:

to be perfectly honest, I am finding that I am falling out of favour with singletons or statics of any sort, with the possible exception of a single entirely static class consisting of just static properties for things like TerminalID, SessionGUID etc


IMHO there is no need now to have singletons / statics with the exception of the edge case described in the first sentence.

I generally agree with limiting the use of singletons and static members - but wanted to point out that these 2 are not interchangable terms. You can create singleton classes that don't use statics.

-- peter

Posted by Peter Judge on 19-Mar-2012 13:50

tamhas wrote:


* Yes, as a general rule, one would prefer that the class enforce its own singletonness.  Obviously.  I offered this simply for those cases where there was a reason why people were reluctant to use statics to create a singleton.   If one does not have those concerns, it is clearly better for the class to do it itself because it is more cohesive, more positive, and avoids the use of a helper class.

I don't believe types should manage their own lifecycles at all. They do what they're supposed to do, according to the SRP. Someone else's R is to manage their lifecycles.

-- peter

Posted by Thomas Mercer-Hursh on 19-Mar-2012 14:03

I don't see an object managing its singletonness as the same as it managing its own lifecycle.  Yes, for most objects, someone else decides when it is needed and when it is no longer needed.  But the idea that there is only ever supposed to be one of something is a property of the thing.  It is just that using statics to implement that can have unpleasant sideeffects in some cases.

Of course, I think there is also a temptation for some people to force something to be a singleton when there is no particular need to do so.  Often, the singletonness is inherent in the object's relationships and there is no need to force.

Posted by Thomas Mercer-Hursh on 19-Mar-2012 14:06

Yes, one can, but it requires a kludge like this technique or the facade/implementation approach I defined on OE Hive to completely avoid statics.

This thread is closed