On Thu, Jan 17, 2013 at 3:25 AM, Igor Stasenko <siguctua@gmail.com> wrote:
After some thought i decided to contribute my 2cents.

First, i think it is impossible to introduce a (re)initialization
logic which would suit all different scenarios.
Because it is really depends on what is stored in class variables and/or pools
and if you add subclasses and then instances into the soup, you might
end up with something
which is really hard to safely reinitialize, because it may have some
inconsistent state at different stages
of initialization. It also, sometimes an order of initialization is important.

Yes, but on *can* write idempotent class initialization code. �So that if the system does reinitialize on every load old code may break until its fixed, but new code will have the advantage of always being correctly initialized. �Note that in the VMMaker class reinitializations of the core VM classes (the interpreter, garbage collector, jit, etc) are done *on each launch of the simulator*, and *each vm generation*, let alone on each package load :). �[ I'm not recommending this :) ].

One thing I do is when creating singletons for sentinels etc I check whether they've been initialized. e.g.

initialize
� � Sentinel ifNil: [Sentinel := Object new]

This avoids breaking existing instances that would end up referring to an older value for Sentinel. �Much the same goes for any class state that would end up in an instance. �One can use become: here too.

What we missing, i think is a package pre/post load/update action(s)
which tied directly to the package,
so developer can decide by himself what needs to be (re)initialized
and in what order without need of having some automated tool to decide
it (often wrongly).

The question is which is better, hooks to allow control of initialization on package load (be it Monticello or Fuel) or simple rules for (frequent) reinialization? �The former allows one to write naive initialization but at the cost of mastering some complex mechanisms in package loading. �The latter forces one to write careful initialization code but has the benefit of simple package loading rules. �Further, writing idempotent class initialization code is only a problem with complex class initialization code, and presumably a programmer who is writing such complex code is up to the task of making it idempotent. �In simple cases, writing idempotent code should be simple.

Personally I'm starting to prefer the latter approach because the complexity ends up in common Smalltalk code (class initialization) and in one place instead of in special Smalltalk code (package loading hooks) in multiple places (all the various package systems). �The tools always support common Smalltalk code better than these special hooks. �For example, load scripts may be stored as strings in packages, and there-in senders and implementors won't find them.

There are, I think, great advantages to having a system composed of freely reinitializable components. �It is one of Gilad Bracha's design goals behind Newspeak to allow running programs to be updated on the fly as fixes are released. �Gilad particularly likes the fact that this means one can discard legacy code, since all (if this vision is realized) Newspeak programs should be at the latest version. �A Smalltalk system with this property would be far more reliable. �Imagine a long-running server application that is simply updated as and when bug fixes are available.

I think that forcing frequent class reinitialization and forcing users to write idempotent class initialization is consistent with�Pharo's philosophical position on fixing broken things, and on good documentation and simplicity. �I also think that it's a good idea.

I would really like that one day we could have packages as a
first-class entities in a system, so we could express things in simple
way:

Package named: #Foo.

Foo>> onLoad
� "perform an action when the package is first loaded into image"
� �MyClass initialize.

Foo>> onUpdate: oldVersion
� "perform an action when different version of package is loaded into image"
� �MyClass reinitialize.

of course, being able to control those actions is just a tip of the iceberg.

Yes, this is exactly the route I took with VisualWorks parcels. �And it was necessary because the code we packaged was legacy and we didn't have the cycles to rewrite that code. �But I think it's too complex. �It adds another layer to class loading, with its own conventions, that may be specific to a particular package system. �Whereas if the rule is "your class will be reinitialized whenever it is loaded in whatever form" it's simple, unambiguous and something one can cope with.

KISS.


P.S. i know that MC supports package pre/post load scripts (but
strangely i cannot find where).
so, it is really opaque to all of the tools, since it is outside of
the source codebase of the package.

P.P.S. Metacello also supports pre/post actions, so i think right now
a best place where you can put (re)initialization code is into
metacello configuration, and initialize things explicitly, rather than
relying on implicit logic of tools.

--
Best regards,
Igor Stasenko.




--
best,
Eliot