The weakness of the CleanupIF
In the course of fixing the Singleton/Cleanup entaglement problem described in the CleanupIF vs. Singleton thread, I removed the singleton aspect of the HarvestScheduler class, but I'm still struggling with implementing a logically consistent lifecycle of the class.
I think the reason for this is that the current CleanupIF design is broken, because it introduces a asymmetrical object lifecycle where it is difficult to control what the state of the object is. The default object lifecycle is the symmetric:
Creation/Construction Reference ->State: Active Dereference Destruction
Now the CleanupIF introduces a new step in this lifecycle so the lifecycle becomes:
Creation/Construction Reference ->State: Active CleanupIF ->State: Inactive Dereference Destruction
It isn't exactly clear from the CleanupIF name that the functionality defined here is actually a lifecycle step, but the cleanup functionality will make the object unusable (and no way to 'restart' the object), which implies that the idea properly it to dereference the object quickly afterwards. The CleanupIF javadoc says this more directly "Interface for classes which can be cleaned up by a shutdown hook". Many of the CleanupIF classes tries to clarify this by defining a close() method, which implies that we are starting to end the objects life.
In my opinion a more clean design would be to define something like a ComponentLifecycle interface defining 2 operations:
- start: Starts the component, creates connection, starts threads etc.
- shutdown/stop: Does the opposite of the start implementation.
This means the life of a ComponentLifecycle would become:
Creation/Construction Reference -> State: Inactive Start ->State: Active Shutdown ->State: Inactive Dereference Destruction
This a more symmetric design and will enable a clear design of ComponentLifecycle objects state where they are used. The 'start' operation is actually found in many CleanupIF classes under different names, but they should be promoted to the same logical level as the current cleanup, to make it clear that they are symmetric lifecycle steps. A lot of the functionality found in the CleanupIF classes constructors might also be moved to a new start method to support the symmetry of the classes.
This is by the way a common component lifecycle pattern which can f.ex. be found in application servers, component frameworks etc.