Re: [Pharo-users] Updating singletons
On Thu, 3 Jan 2019 at 20:01, Konrad Hinsen via Pharo-users < pharo-users@lists.pharo.org> wrote:
Dear Pharo experts,
I am wondering if there is a good way to deal with singleton objects whose value needs to be updated following changes in the code that initializes it.
Following the model of many examples in Pharo itself, I have defined a singleton class with a uniqueInstance method for accessing (and creating if necessary) the single instance, and a method "reset" marked as a script to set the uniqueInstance back to nil when required, i.e. after source code changes make the prior value inappropriate.
This works very well, as long as I don't forget to do the reset, which has already caused me a few hours of debugging time. Worse, suppose someone else is using my project in progress, pulling changes from my GitHub repo once per week. That person cannot know if the latest changes require a singleton reset. More importantly, users shouldn't have to know about such internal details at all.
So is there a way to do the reset automatically whenever a new version of my package is loaded into an image?
Thanks in advance, Konrad.
You might use a Baseline #postLoadDoIt: https://github.com/pharo-open-documentation/pharo-wiki/blob/master/General/B... Consider that a person pulling your changes cannot know if you have upgraded the library versions of any dependencies, so always updating via a Baseline might be a reasonable expectation. But that doesn't help you while developing within the one image. cheers -ben
Have you considered to yield (an) proxy object(s) instead of the actual Singleton in uniqueInstance? This way it suffices to update the proxy with each update of the code. Am 3. Januar 2019 15:36:27 MEZ schrieb Ben Coman <btc@openinworld.com>:
On Thu, 3 Jan 2019 at 20:01, Konrad Hinsen via Pharo-users < pharo-users@lists.pharo.org> wrote:
Dear Pharo experts,
I am wondering if there is a good way to deal with singleton objects whose value needs to be updated following changes in the code that initializes it.
Following the model of many examples in Pharo itself, I have defined a singleton class with a uniqueInstance method for accessing (and creating if necessary) the single instance, and a method "reset" marked as a script to set the uniqueInstance back to nil when required, i.e. after source code changes make the prior value inappropriate.
This works very well, as long as I don't forget to do the reset, which has already caused me a few hours of debugging time. Worse, suppose someone else is using my project in progress, pulling changes from my GitHub repo once per week. That person cannot know if the latest changes require a singleton reset. More importantly, users shouldn't have to know about such internal details at all.
So is there a way to do the reset automatically whenever a new version of my package is loaded into an image?
Thanks in advance, Konrad.
You might use a Baseline #postLoadDoIt: https://github.com/pharo-open-documentation/pharo-wiki/blob/master/General/B...
Consider that a person pulling your changes cannot know if you have upgraded the library versions of any dependencies, so always updating via a Baseline might be a reasonable expectation.
But that doesn't help you while developing within the one image.
cheers -ben
Hi Steffen,
Have you considered to yield (an) proxy object(s) instead of the actual > Singleton in uniqueInstance? This way it suffices to update the proxy with each update of the code. I am not sure I understand what you are proposing. My problem is figuring out how to change in-memory objects when they become obsolete after a code change. So I'd say it doesn't matter much if the object I need to change is the singleton or a proxy to it, but maybe I am missing something!
Cheers, Konrad.
Hi Konrad, sorry, I might have misread your question such that it was about updating references to an obsolete object. However, there is another fun possibility to figure out that a change happened that does not involve configuration - though, a bit hacky. ;-) You could write the accessor method such that it recompiles itself with the first access after loading new code. For example:
Singleton>>uniqueInstance instance := self class new. self class compile: 'uniqueInstance ^instance'. ^instance
Best, Steffen Am .01.2019, 18:04 Uhr, schrieb Konrad Hinsen <konrad.hinsen@fastmail.net>:
Hi Steffen,
Have you considered to yield (an) proxy object(s) instead of the actual > Singleton in uniqueInstance? This way it suffices to update the proxy with each update of the code. I am not sure I understand what you are proposing. My problem is figuring out how to change in-memory objects when they become obsolete after a code change. So I'd say it doesn't matter much if the object I need to change is the singleton or a proxy to it, but maybe I am missing something!
Cheers, Konrad.
Hi Steffen,
However, there is another fun possibility to figure out that a change happened that does not involve configuration - though, a bit hacky. ;-) You could write the accessor method such that it recompiles itself with the first access after loading new code. For example:
Singleton>>uniqueInstance instance := self class new. self class compile: 'uniqueInstance ^instance'. ^instance
If I understand this correctly, it replaces the uniqueInstance method by another one that returns the singleton instance. And when the code is reloaded, it's the above method that is reinstated, to be used just once. Neat! Thanks, Konrad.
Ben,
You might use a Baseline #postLoadDoIt: https://github.com/pharo-open-documentation/pharo-wiki/blob/master/General/B...
Thanks, that looks like exactly what I need... except that it doesn't seem to work. My postload method is not run when a new version of the code is loaded into an image. Nor when I load my project into a fresh image. Which makes me wonder more generally how one can debug baselines. The mechanism that uses them is very opaque: you write some code as a kind of plugin to some framework, but it is not clear at all how this code is used.
Consider that a person pulling your changes cannot know if you have upgraded the library versions of any dependencies, so always updating via a Baseline might be a reasonable expectation.
Indeed, baselines make a lot of sense in principle. Cheers, Konrad
participants (3)
-
Ben Coman -
Konrad Hinsen -
Steffen Märcker