[PEAK] Persistence styles, MDA, AOP, PyProtocols, and PEAK
Phillip J. Eby
pje at telecommunity.com
Fri Jul 16 18:09:02 EDT 2004
At 05:45 PM 7/16/04 -0400, Phillip J. Eby wrote:
>At 01:51 PM 7/16/04 -0700, John Landahl wrote:
>
>>I'd like to hear more about your event/validation machinery ideas when
>>you get
>>a chance.
>
>It's really very simple, actually. I anticipate that any modification of
>a feature on any model object will call a generic function that takes
>arguments for the objects in question and the kind of association between
>them. The default implementation will update the object's attributes to
>point at each other (or not).
>
>To do validation, you'll add before, after, or around methods to the
>generic function, e.g.:
>
> [before("linkType is foo and (some validation condition)")]
> def link(linkType,ob1,ob2,...):
> raise ValueError("Now that just ain't right...")
Of course, it'll probably make sense to elevate the above to a higher-order
function like:
defconstraint(Someclass.feature, mode, condition, errorDescription)
where 'mode' indicates whether the condition is checked on link, unlink,
commit, or explicit validation, and 'condition' is an expression to be
checked. 'errorDescription' will be some sort of object that contains
enough info to allow localization or other formatting. (That is, it'll be
able to be just a string, but it'll be better if it has at least some kind
of additional context to it.)
Anyway, once we have something like this implemented, constraints become
more like a first-class part of the domain model, and less like a kludgy
hook mechanism.
Also, I didn't really answer your question about events... I assume that
there will be workspace types that are intended as a GUI workspace, and
which will contain an "observer registry" of some sort. One would then use
hooks like this:
[after("ws in GUIws and ob1 in ws.observed")]
def link(linkType,ob1,...):
ws.notifyLink(linkType,ob1,...)
To notify the observers after a change has been made.
Again, I don't yet know what the real argument signatures of these
functions will look like yet. I'm working on refining my mental model of
how peak.model can treat all associations in a uniform way, including
ternary and higher-numbered associations. Currently, peak.model doesn't
even have an explicit notion of binary associations, just an implicit one
for bidirectional associations. Its notions of 'link' and 'unlink'
actually roughly correspond to the notions we need for validation and
events, *except* for the symmetry issue.
By the symmetry issue, I mean that if x.foo == y means y.bar==x for any x,
then in the current model, we have two separate events that occur when
x.foo is set to y. One for the forward linkage, and one for the reverse
linkage. This unnecessarily complicates things, because for one thing, you
have to decide which end to put the validation on!
What I'd like to do is to define any such bidirectional association in the
manner, 'foo_bar(foo=y, bar=x)', but this doesn't lend itself to the
current system because neither end knows which end "goes first". That is,
is it 'foo_bar(y,x)' or 'bar_foo(x,y)'? Without a way to answer that
question, a sensible and uniform mapping isn't possible.
The solution in MOF, UML, et al is to define a separate Association object,
distinct from the features that implement it. When I build peak.model, I
didn't think we needed this because it seemed redundant. And, most of the
time it *is* redundant. Really, the main exceptions are symmetric
associations like 'spouse'.
Anyway, the upgrade to peak.model needs to take this issue into account, so
that existing models don't need any significant revisions to acquire
implicit association definitions that are adequate for use as link definitions.
(Note, by the way, that in the new model, *all* structural features will be
considered associations, it's just that regular attributes are
unidirectional associations with an unambiguous definition. Bidirectional
references are the only ones where potential ambiguity exists.)
More information about the PEAK
mailing list