Re: [Modeling-users] inheritance and relations confusion
Status: Abandoned
Brought to you by:
sbigaret
|
From: Sebastien B. <sbi...@us...> - 2003-11-15 19:40:01
|
Hi all,
Back on the subject, now that the problem is identified. I think this
can be interesting to anyone willing to understand faults and the way
they are handled by the framework, so I'll try there to be as explicit
as possible. This message concludes with... a question on how this could
possibly be handled by the framework in the future, your opinion is
appreciated.
Remember we have a model: A <<----> B, with B inheriting from A, and we
have an two instances 'a' and 'b' in relation to each other: a <<----> b
you fetch object 'a':
>>> a=3Dec.fetch(..., isDeep=3D1)[0]
>>> b=3Da.getB()
Now, if we suppose that the fetch only fetched 'a' and *not* 'b' as well
(which is possible since the fetch has isDeep=3D1), assuming furthermore
that b has not been fetched before within 'ec', we have:
>>> b.isFault()
1
>>> b, b.__class__
(<A.A instance at 0x820b24c>, <class A.A at 0x81d7f6c>)
>>> b.getAs
[...]
AttributeError: A instance has no attribute 'getAs'
--> b is a faulted object, and indeed, its class is A; like any fault,
its class is the root entity's class. That is basically why you get
an AttributeError when trying to send to this object a 'getAs()'
message, to which only class B's instances can answer.
Now if you clear the fault (b.willRead()), then b.getAs() works as
expected.
I understand this can be surprising. The fact is that the model here
is very simple, and that you expect to get a B instance, not an A. To
understand why a fault is *always* an instance of the root entity when
created, just imagine there is a third entity in the model such as:
C <<-----> A <<----> B=20
and an object 'c' such as: c <---> b <----> a
If you fetch c first, then getA() returns 'b', a fault for an 'A',
then you fetch 'a', and you expect to get the _same_ object 'b' when
you ask for a.getB() --this is uniquing: the same row can only be
represented by one, and only one, object in the editing context.
As you can see here, even by examining the model there is no way to
deduce from it that 'b' will be a 'B' when we ask for c.getA() --and
I'm sure we do not want the fault's class to be checked and eventually
changed when a is asked for getB(), or we'll experiment a real slow
down in the process of uniquing & fetching objects.
I hope I succeeded in making it clear /why/ faults are created w/ the
rott entity's class. Now it can be also surprising that the fault is not
automatically cleared when it gets the 'getAs()' message. In fact, this
is not a bug in itself, the fault is just not programmed to act like
this.
There would be a way to do this: define __getattr__() so that it calls
willRead() on the object when it gets called. But this is not
something I want to add to the default behaviour, I do not think this
is a good thing to do, just because __getattr__ gets called in a lot
of situations where you do want a fault to be actually triggered. For
example, asking 'dir(b)' makes __getattr__ be asked for '__members__'
and '__methods__', printing 'b' (in log e.g, or wherever) makes
__getattr__ be asked for '__str__', then for '__repr__' (when none of
them exists and before falling back to the default --clasic-style
classes only), etc.
--> I'm pretty sure that, if this is made the default, almost everyone
will complain sooner or later about faults being triggered for
choose-any-reason-here...
That's the reason why this is not the default, and why the choice is
left to each developer there.
Now, of course, __getattr__ could be designed so that it only calls
willRead() if any of the class' subclasses methods are searched...
Should we go that way? Or does anyone see an other possible approach?
Or maybe is it enough to explicitely add this to the documentation?
-- S=E9bastien.
|