On Mar 6, 2013, at 1:02 PM, Denis Gervalle <dgl(a)softec.lu> wrote:
Hi Vincent,
On Wed, Mar 6, 2013 at 11:36 AM, Vincent Massol <vincent(a)massol.net> wrote:
Resending since I've made mistakes (it's
only about ObjectReference, not
Properties), sorry about that. Here's the new version:
------------
Hi devs,
ATM in the model module there's no ability to reference an xobject other
than by using a free form name.
We made this on purpose.
I know, I worked on this… but it doesn't make it right… :)
The problem is
that this is not really usable. This is why we introduced
the BaseObjectReference in oldcore.
We have introduce the BaseObjectReference in oldcore simply to easily
support the current storage implementation. At that time, we had a
discussion about using the object number (not to be confuse with the index)
or the object UUID. And, since the object UUID was suspicious in some edge
case, you convince me to use the object number to create the free form name
of these old objects (I should have resist more since I still do not have
evidence of these edge case).
What? That defeats one of the main goal of references which is that you can directly
address an entity without having retrieved it first!
The reason entities have names is to be able to easily reference them. Using a UUID makes
it impossible to reference something without getting it first...
If to reference an Object I have to load the Document first, then in practice it means we
don't need Object references and they shouldn't be considered entities. For any
entity, you should be able to construct a direct reference to it without needing to load
anything else.
In the 7-8 years of XWiki we've used Class reference and numbers/position to reference
xobjects and it has worked quite well IMO. In most cases you have only 1 xobject of a type
and it's very nice to be able to say: here's a reference to the first object of
type N in document P.
Exposing an internal id of a document as reference is a no go for me since it cannot be
constructed without retrieving the entity first.
However this
is major PITA since we can't have clean code that create an
object reference and that doesn't depend on oldcore.
Creating a reference to the third object of a given class in a document (or
object number 3, or even the third object of a document) has absolutely no
meaning unless you have already that object at hand
Why doesn't it have a meaning? If in my app, my spec says:
- each doc has 3 objects of type P and the first one means this, the second one that and
the 3rd one that other thing,
then the 3rd one has a meaning.
, and so you already
have a source for its reference (solved not nicely by the
BaseObjectReference actually, but this was another story).
I'd like to propose the following:
* Modify ObjectReference to add 2 named parameters: Class reference and
position
Since position is really fragile without any real meaning,
having a
reference using a position will be a source for spurious issues, I am
definitely -1 for any positional reference.
* Make the name optional in EntityReference
This sounds like a sign of bad design to me... what is a entity without a
name in general ?
It means it's a reference to an entity by a mean other than a name :)
We need to decide but we could very well decide that some entities don't have a name
and that they can be found/addressed by some other means (as in the case of Object
references when locating them through class reference and position).
More below
This means
that when we use an EntityReferenceResolver to resolve
"wiki:space.page^wiki2:space2.page2" we get an ObjetReference with:
* name = null
* param1: name = "classReference", value = EntityReference
* param2: name = "objectPosition", value = 0
Rationale:
* This is exactly what we already do for Locale (and what we'll do for
Version too probably) so it's logical to do it for Object References too
I agree with your sample and your rationale, there is a need to create a
reference to the first (and probably the only for such use case) object of
a given class in a given document without having to compose weird names or
positional references. This has definitely a meaning, much more than the
second or any numbered objects... And this object is not always "[0]" in
base reference syntax !
ah good, was trying to despair :)
If the first one has a meaning, then 2nd or 3rd can also have a meaning, see my example
above. Obviously the majority of use cases will be the first one but that doesn't mean
the other positions are not needed.
0 = first not null xobject
1 = second not null xobject
...
However, resolving
"wiki:space.page^wiki2:space2.page2" to that object is
not valid, since you do not really know what you are doing here, are you
speaking about the first object of a given class or an object named "
wiki2:space2.page2" ?
Exactly. Which is why in my proposal we would have to agree that the current notation
(thomas calls it syntax) only describes class reference and NOT a name (name = null). If
we ever want to also be able to write a string and specify a name in it then we would need
to invent a syntax, in the same manner that we currently have no syntax to express a
locale in a document reference when expressed as a string.
So if we need to resolve a string into the first (or,
even if I am against, any) object of a given class, we need another syntax
at least (BaseObjectReference had already cause some poor stuff in
LocalUidReferenceSerializer where we had to remove wiki in a very bad way
currently).
Using a name is very very far in the future so we don't need to invent a syntax for
that now IMO. We don't even know if it'll ever happen actually…
Consequences:
* We need to modify the Seralizers/Resolvers accordingly
According we have a new syntax for your kind of object reference, we may do
so. I resolver/serializer (as well as setter of class reference) I suggest
like Thomas that we support relative reference to classes based on the
containing document, both simplifying creation and avoiding
useless repetition.
That seems good for now, even though in some far future we may want to have a class
defined in a wiki and an xobject located in another subwiki… or not… ;)
* We need to
modify EntityReference to support a null name
Do we really need that, or the name would simply reflect our special syntax
?
It would be slightly misleading to use the serialized class ref as the name IMO but why
not... One danger is in code that will use it instead of using the well-known parameters
for class ref and position.
* We deprecate
BaseObjectReference
Does it really true ? It does not have the same meaning (even for your
initial proposal) since number and position are not the same and the
BaseObjectReference is a special reference, not a general object reference,
since it does not have a real free form name. Deprecating means we had to
replace them everywhere, and I am not sure it is easy to use index in place
of number in some places, like storage where we use reference for IDs.
Maybe, in any case what I meant is that we'll need to make our code use the new way
and not use BaseObjectReference as much as possible.
* Probably
some other stuff to modify like modifying event listeners
listening on objects since it's now going to be much easier, etc
WDYT?
So, to resume, I understand the need to have a way to create reference to
the first object of given class in a document. Even if using an object
reference with, let say a special syntax, will introduce some bad
consequences on the implementation of equals
equals/hashcode shoudl already work since they already take into account parameters.
and related methods on entity
reference (like those we have for locale or version), we should probably
consider it (Note that it will also affect property reference).
I am definitely -1 for any positional reference which are meaningless.
I think this is a pity and you're closing the door to lots of use cases and you're
going to make them really hard and not performant to implement as a consequence.
As a user, if I **want** to access the 3rd xobject because it has a meaning for my app,
I'm not going to be able to do so. I'm going to need to load the doc and do some
queries to iterate over xobject and count to 3… (which obviously is both painful and not
performant).
BTW your counter-suggestion to drop the position means you're going to break
everything that already exists since it's currently possible to reference an object
with class and number. It means inventing a new syntax, which is always painful to do.
Thanks
-Vincent