Singleton vs Static - Forum - OpenEdge Development - Progress Community
 Forum

Singleton vs Static

  • The problem is that simply having an active buffer reference in any active code instance will prevent a db DISCONNECT() from running to completion.

    If the db reference was dynamic, and the dynamic buffer was deleted before the DISCONNECT, then it might work.

  • In that case, you will need to tell your STATIC class that you are about to disconnect the DB in which case you call a method of the STATIC class to release the lock. You call another method to reacquire the lock after reconnecting to the DB. I would suggest wrapping the DB disconnect/connect process into another static class.

    That won't work! As Cameron and myself have shown with the sample code is that it's not about record locks you can control with your code. It's about a schema lock because the static instance remains in memory.

  • A class with a static member is ALSO static class. The reference to the hInstance have to be released. That class you guys refer to as singleton is missing a method that releases the static member Instance. The static instance that is created will remain in the memory even if you delete all the instance of objects. In this case you must call a method to release "hInstance" then disconnect.

  • A class with a static member is ALSO static class. The reference to the hInstance have to be released. That class you guys refer to as singleton is missing a method that releases the static member Instance. The static instance that is created will remain in the memory even if you delete all the instance of objects. In this case you must call a method to release "hInstance" then disconnect.

    Camerons code has shown that this won't work.

  • This is happening because you have not released CustomerHelperSingleton. Remember that a class with a static member is also static class.

    Try adding

    DELETE OBJECT CustomerHelperSingleton:Instance.

    DELETE OBJECT CustomerHelperSingleton. /* I'm not sure if this is possible, but basically, there is an instance that is implicitly created behind the scene the first time you try to access Instance when you run CustomerHelperSingleton:Instance, you are in fact creating a second instance of CustomerHelperSingleton. It just so happen that the property Instance is shared */

  • DELETE OBJECT CustomerHelperSingleton.

    Won't compile:

      • Unknown Field or Variable name - CustomerHelperSingleton. (201)

  • I found this old thread after reading Tom Bascom's presentation slides about static classes:

    http://pugchallenge.eu/images/2014pdfs/tom_bascom_stop_shared_variables.pptx

    We have been using the same approach for replacing shared variables with static properties.

    However, now I started to wonder if we should use a singleton class instead. In OE 11.4 you can pass an object as a parameter between client and AppServer. Using singleton, we could send this singleton object to AppServer but the same can not be done with a static class. So, if we need to access the same common values both in AppServer and client, using a singleton pattern might be useful. 

    Any thoughts?

  • As Thomas Mercer-Hursh  says early in the thread
    > Singleton is a pattern; static is a language feature. 
     
    You can easily have singletons that are not implemented using static members. The only trick is that someone, somewhere needs to hold at least one reference otherwise the garbage collector will do its work.
     
    If you want to have 2 instances of the same class running on client and server, you will need to pass the values back and forth. Were you thinking of passing the singleton itself?
     
    -- peter
     
    From: Marko Myllymäki [mailto:bounce-mmy@community.progress.com]
    Sent: Monday, 08 December, 2014 06:39
    To: TU.OE.Development@community.progress.com
    Subject: RE: [Technical Users - OE Development] Singleton vs Static
     
    Reply by Marko Myllymäki

    I found this old thread after reading Tom Bascom's presentation slides about static classes:

    http://pugchallenge.eu/images/2014pdfs/tom_bascom_stop_shared_variables.pptx

    We have been using the same approach for replacing shared variables with static properties.

    However, now I started to wonder if we should use a singleton class instead. In OE 11.4 you can pass an object as a parameter between client and AppServer. Using singleton, we could send this singleton object to AppServer but the same can not be done with a static class. So, if we need to access the same common values both in AppServer and client, using a singleton pattern might be useful. 

    Any thoughts?

    Stop receiving emails on this subject.

    Flag this post as spam/abuse.

  • Hi Peter, thanks for you reply. Yes, I was thinking of passing the singleton object itself. Do you see some obstacles in that?

  • Passing a singleton will give you a new instance on the client each time so there will only be one instance of it on the server (well one on each agent)... on the client you'll have a bunch of those unless you only ask for it once but I doubt singleton pattern will enforce only one instance on the client. This is only a creational pattern while when passing objects around those are serialized and de-serialized back, will be interesting to find out what progress is going to do though.

  • In my experience, the type of context you may typically want to pass  around like this tends to be bound to the client, not the server. So the singleton will always be passed in one direction, towards the server, where it is treated and handled as a singleton for the duration of the call, but needs to be discarded at the end of the call in favour of the singleton passed by the next caller.

    A typical use case that I can think of:
    Each branch has a cash book and the responsible users can only access the cash book data for their own branch. They cannot select another branch. But the internal auditor needs to access the cash book data of any branch. You could ask him in each program which branch he is working with, or you can always default it to the last one he used. In order to do this, you need to track his "working" branch in some environment variable. Legacy code typically use a global shared variable, modern code will need a singleton. This also enables both the branch user and the auditor to use common programs without forcing the branch user to enter the only possible valid value each time, since the "working branch" variable/property can be set to the user's branch.

    If the singleton contains a lot of data that are always needed in the business logic, you typically end up passing all of these as separate parameters to the AppServer (which later causes problems when more data is needed) or as some formatted string (which can be extended if more data is needed) with every call to the AppServer. The latter would simply use the parameters, store it in a singleton or, in traditional code, replace the values in the global shared variables with those in the parameters. If you pass the singleton from the client to the AppServer, you have the option of replacing any possible pre-existing singleton with the received object or copy the whole object's values in a simple call, rather than copying values one by one from a formatted string.

    Simon L Prinsloo

    www.vidisolve.com

  • It's technically possible, of course, but then (I think) you're moving into a place where you're treating the object as a value object (or data transfer object) rather than a singleton. A singleton in my mind is one isntance of an object that does some work. By definition, there is one per AVM (one on the client, one per agent on the server). As Marian says elsewhere, passing the singleton results in more than one singleton.

    The pseudo-code below shows how I'd think about it. (there are some details that will vary). The point is to keep the singleton and data-transfer-object patterns distinct in your mind.

    /* this is a singleton*/
    class UserContextManager:
      /* this is ONE way of implementing a singleton; not my first choice,
         but it's readable */
      def static property Instance as UserContextManager get. private set.
      method public UserContext GetCurrentContext().
      method public void SetCurrentContext(poUC as UserContext).
      /* other methods to do Stuf */
    end class.
    /*this is the data transfer object */ class UserContext serializable /* 11.4+ or roll-your-own */: def pub property Name as char get. set. def pub property SomeOtherData as class Foo get. set. /* whatever you want to consider context */ end class. class Client.ServiceAdapter: method public void CallAppServer(<args>): oUC = UserContextManager:GetCurrentContext(). run Server/ServiceInterface.p on hAppServer ( input <args>, input-output oUC). UserContextManager:SetCurrentContext(oUC). end. end class. /* ServiceInterface.p */ def input parameter <args> def input-output parameter poUC as UserContext. UserContextManager:SetCurrentContext(poUC). /* run update_ledger.p or whatever needs running */ poUC = UserContextManager:GetCurrentContext().

    hth,

    -- peter

  • I do agree that that would be a cleaner implementation than having the actual data contained inside the singleton and passing the singleton itself. With this pattern, the choice of how to implement the singleton would become irrelevant again, since that is not what is passed.

    Simon L Prinsloo

    www.vidisolve.com

  • Peter, thanks a lot for sharing your thoughts and sample code. That approach makes sense.

    BTW, there seems to be a couple of typos in the sample code:

    e.g. UserContextManager:GetCurrentContext(oUC) should be UserContextManager:SetCurrentContext(oUC).

    but the idea if fully understandable.

  • Hi Marko,
     
    The cut&paste demon strikes again ... fixed now :)
     
    From: Marko Myllymäki [mailto:bounce-mmy@community.progress.com]
    Sent: Monday, 15 December, 2014 02:33
    To: TU.OE.Development@community.progress.com
    Subject: RE: [Technical Users - OE Development] Singleton vs Static
     
    Reply by Marko Myllymäki

    Peter, thanks a lot for sharing your thoughts and sample code. That approach makes sense.

    BTW, there seems to be a couple of typos in the sample code:

    e.g. UserContextManager:GetCurrentContext(oUC) should be UserContextManager:SetCurrentContext(oUC).

    but the idea if fully understandable.

    Stop receiving emails on this subject.

    Flag this post as spam/abuse.