The thinking behind ColdFrame is that you should be making analysis models rather than code models. Martin Fowler discusses this in his Appendix A.
One way of looking at it is that modelling ought to be, as far as reasonable, independent of the software architecture (both the implementation language and the support infrastructure). What we are modelling is generalization. We may be able to implement generalization using inheritance in our implementation language, but this can easily fall foul of practicalities; perhaps we have to implement in C; maybe we're using an SQL database to implement persistence; our implementation language may not support multiple inheritance.
Another aspect is dynamic versus static classification.
The major use of generalization (well, specialization) is to classify aspects of the subject matter. Inheritance, as implemented in C++ or other object-oriented programming languages, is fine for static classification (subtyping Animal as Pig, Goat, Cow for example).
However, a very useful analysis technique is dynamic classification. Rent-a-Wreck has a fleet of vans, which are sometimes on hire. We might want to model this as Hirer hires Van, which is biconditional (a known Hirer may not have any Van on hire at the moment; a Van may not be hired to anyone at the moment). The model can be made less vague by subtyping Van into Hired Van and Available Van; now all Hired Vans have a Hirer, so the code doesn't need to check whether there's a Hirer or not.
The problem with implementing this model using programming language inheritance arises when the Van changes from being Available to being Hired. There's only one code object, so you have to create a new HiredVan, copy the relevant attributes from the old AvailableVan to it, break any associations with other objects (for instance, the ServiceHistory), delete the old AvailableVan and remake the associations.
ColdFrame adopts a halfway-house approach to this, combining the Executable UML (originally Shlaer-Mellor) view of generalization with dispatching and inherited operations.
Of course, there is a cost to dynamic classification; you have to decide whether increased precision in the model is worth the extra run time costs of maintaining the model.
See also the State Pattern.
ColdFrame does support composition, in that the «type» stereotype allows you to build types of arbitrary complexity and include attributes of these types in your classes.
If you have a Circle which is at a Point, create a «type» Point (presumably with attributes x and y, themselves of some appropriate type) and give the Circle an attribute centre : Point.
The thing to remember is that (almost by definition) these things are values not objects (that is, one Point(3, 4) is indistinguishable from another), and you don't need to navigate from the Point to the Circle.
If you feel the need to contain all Rent-a-Wreck's Vans in a Fleet (singleton) class, so as to keep track of them all, resist it! ColdFrame's implementation of Van includes a container which holds all the current Van instances, so you can get at them at any time.
It's not at all obvious what aggregation is for; it seems to add very little over a normal association.
If your intent is to classify in some way (perhaps you have a singleton HiredVans class, which aggregates all the Vans which are on hire), you'll almost certainly find that an existing association (between Van and Hirer) or specialization (of HiredVan from Van) will do the trick.
One clue here is the difficulty of providing strong role names for an aggregate association: "contains", "is in" are fairly feeble.
Another indicator that this is happening is the need to name a class "List" (Threat List, for instance).
Role names in associations are very important, and should be verbs or verb phrases. Each end of the association must be named; the object of the verb phrase is the class at the same end as the name, the subject is the class at the other end. So, for example, you might have Window "appears on" Screen, Screen "displays" Window.
Often the role names will be inverses of each other, but sometimes things really do seem different depending on where you're standing.
There are notes on usage.
Associations are implemented using pointers (handles) in one of the class instances involved in the association. Unlinking involves nulling out the handle variable.
ColdFrame doesn't enforce model integrity (at some future time, it may provide model validation checks), so it's left up to you to delete any instances you may need to. For instance, if every Author must "have written" at least one Book and you delete the last Book by a particular Author, you need to delete the Author too.
The Unlink operations that do nothing are those where the association concerned has an association class. In this case, the handle variable or variables concerned are in the association class. This has two consequences:
It would have been possible for Unlink to Delete the association class instance directly, but that would rely on your having cleaned up any other associations between the association class and the rest of the model beforehand (or in a «finalize» operation; however, using «finalize» operations to maintain model integrity is an advanced practice!)
At the moment, ColdFrame implements the minimum necessary to support navigation. For example, a one-to-many association is implemented by pointers from the many end to the one end.
This means that navigating from the many end to the one end is much quicker than navigating in the reverse direction.
At a later stage, it may become cleverer; it might add supporting tables of references to speed up navigation in what is now the unnatural direction (you might need to tell it to do so). Unlink would then do what was needed to keep those tables consistent.
Use the boolean variable (Domain.Domain_Initialized) that ColdFrame itself uses to ensure it only initializes a domain once:
while not Domain_Initialized loop delay 0.1; end loop;
"I want to post an event to be handled at a specific time in the future. It is however possible that my application is stopped before that time and I have deleted the object which would handle it. I understand from the documentation that once an event is posted, it cannot be cancelled.
"Will there be a problem when I delete the object if there is an event outstanding? Will there be a problem when the event reaches the head of the event queue if the object has been deleted?"
When an instance is deleted, all its instance events (whether held until some later time or just in the queue to be actioned immediately) are invalidated, so that when their time arrives or they get to the head of the dispatcher queue they are deleted without being actioned.
If an instance has a Timer, any event set on that timer will similarly be discarded when the instance is deleted.
So instance deletion is a very good idiom for getting rid of left-over events. I've recently seen a lot of models where this isn't usedfor example, a Target modelled as a singleton rather than only existing when there actually is a target. This means it has to have an 'idle' state and great unnecessary complexity in its state machinefor example, left-over events occurring in the idle state having to be marked «ignore».