Another approach to singletons - Forum - OpenEdge Development - Progress Community
 Forum

Another approach to singletons

  • 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.

    Consulting in Model-Based Development, Transformation, and Object-Oriented Best Practice  http://www.cintegrity.com

  • 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

  • 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.

    Consulting in Model-Based Development, Transformation, and Object-Oriented Best Practice  http://www.cintegrity.com

  • 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.

  • 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'

  • 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

  • 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.

  • 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.

  • 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'.

  • 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?

  • 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 

  • 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.

  • 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

  • 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.

  • 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.

    Consulting in Model-Based Development, Transformation, and Object-Oriented Best Practice  http://www.cintegrity.com