incubator-isis-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Dan Haywood <...@haywood-associates.co.uk>
Subject Re: More on the Oid refactor
Date Mon, 07 May 2012 17:40:02 GMT
On Saturday, 5 May 2012, Mike Burton wrote:

> Hi Dan,
>
> Thanks for the update, good work, worth eating a few bits of eggshell:-)
>
> Could you list/ clarify meanings of your canonical string for symbols #~!
> etc please- I'm confused by difference between ~ and # eg
> CUS:123~NME:2~CTY:LON
>



Hi Mike,

First off, I made two slight mistakes in my first email: # should have been
$ throughout, and CUS:123#NME:2 should have been CUS:123~NME:2.

Thus:

CUS:123                       - persistent root
!CUS:123                      - transient root
CUS:123$items                 - collection of persistent root
!CUS:123$items                - collection of transient root
CUS:123~NME:2                 - aggregated object within persistent root
!CUS:123~NME:2                - aggregated object within transient root
CUS:123~NME:2~CTY:LON         - aggregated object within aggregated object
within root
CUS:123~NME:2$items           - collection of an aggregated object within
root
CUS:123~NME:2~CTY:LON$streets - collection of an aggregated object within
aggregated object within root


I wonder whether that is what caused your confusion?  Otherwise, and to
answer the question, though:

There's no intrinsic "meaning" to the symbols, other than to distinguish
the parts of the OID.  The ~ is the prefix for each aggregated object,
while $ is the prefix for a collection, if any.  I chose "~" because it's
easy to see, I chose "$" because it is used as a separator in Java (outer
vs inner class bytecode).


A more useful answer, though , might be for me to explain why OIDs are so
important.

Within Isis we use an OID as the identifier of an ObjectAdapter, which in
turn is a wrapper around the pojo.  The main responsibility of an
ObjectAdapter is to manage the "resolve state", ie lazy loading of an
object.  It's also used in dirty tracking: whether an object needs to be
saved to the object store.  The ObjectAdapter also points to the
corresponding ObjectSpecification which describes the structure of the
object: ObjectAdapter is like java.lang.Object, while ObjectSpecification
is like java.lang.Class.  Also: an OID is a value object (equals, hashCode
etc).

OIDs are important because they are provide an immutable handle to an
object.  This is useful for webapps, eg to use in links and forms, and its
useful for the JSON (restful) viewer, eg in URLs.  It's also useful for
object stores, because they can (or rather, will now be able to) use the
OID's string form to represent a reference between an object or the
contents of a collection.

OIDs are also more generally useful in supporting workflows: an OID is
bookmarkable, so could be added into a favourites list, o (as we do on the
big Irish project), can be converted into a barcode, which is great for
handling incoming communications/correspondence that's been scanned.

~~~
We've had the concept of "CollectionOid"s for a while in Isis: if a
Customer has a collection of Order's, then the CollectionOid is the ID for
the java.util.List that holds a Customer's Order pojos.  The "AggregateOid"
is newer, introduced to support NoSQL databases and the more general DDD
concept of an aggregate root.  Each AggregateOid has a localId, which is
unique within the aggregate; or in other words it is globally unique in
conjunction with the parent Oid.

~~
The string format I'm suggesting here tries to reflect the "nesting" of
objects of both aggregated entities and of collections:

CUS:123 is the RootOid for a simple root aggregate; it's a CUS(tomer),
id=123.

CUS:123~NME:1 is an AggregateOid for the N(a)ME of a customer, with
localId=1.  In other words, this is modelling the fact that a customer
might have several names or aliases, this being the OID of one of those
names.  Note that we don't know how the name object is related to its
"owning" customer; but that's the responsibility of the
ObjectAdapter/ObjectSpecification to furnish that information.

CUS:123$items is the CollectionOid of a the "items" collection of customer
id=123.  We don't know what type of thing are stored in the "items"
collection; but that's not the responsibility of an Oid: such info can be
found from the ObjectSpecification for the Customer type.  Again, we also
don't know what the content of the "items" collection is: but that is the
responsibility of the ObjectAdapter.


~~~
Lastly, in case it's not obvious, the "CUS" is the abbreviated object type
(as per @ObjectType annotation).  If there is no such annotation, then the
object type is taken to be the fully-qualified class name.


HTH,
Dan



>
> Mike Burton
> ( iPhone)
>
>
> On 5 May 2012, at 10:13, Dan Haywood <dan@haywood-associates.co.uk> wrote:
>
> > Hello all,
> >
> > First, just to say that I *know* the build is broken, and it's a pretty
> > poor show on my part to let it happen, but it's a little bit of breaking
> > eggs to make an omelette.
> >
> > Second, wanted to update on my current thinking on OIDs ... because this
> is
> > what I'm currently working on and what I intend to commit as soon as I
> can
> > (hopefully this coming week).
> >
> > Already committed:
> > * our OIDs are now immutable
> > * we have three types of OID:
> >   - RootOid, which is the OID of a root entity  (implementation: is
> > RootOidDefault).
> >   - AggregateOid, which is an aggregated entity that is persisted within
> a
> > root entity (eg part of a JSON doc in MongoDB).
> >   - CollectionOid, which wraps a List or Set of a root entity
> > - The RootOidDefault was refactored from SerialOid, but it now has an
> > "objectType" (eg "CUS" for customer), so is self-describing.
> > - The CollectionOid also existed previously, and wraps a List or Set for
> an
> > entity
> > - The AggregatedOid we also had a version of; it has a localId to
> > distinguish it from other aggregates of its type (within its parent root)
> > - Both CollectionOid and AggregatedOid have a parentOid
> >
> >
> > Not yet committed:
> >
> > The first thing I've added to AggregateOid is its own objectType, and so
> > that has also led me to introduce a TypedOid interface: both
> RootOidDefault
> > and AggregatedOid implement TypedOid.  And so from there we can say that
> > parents (of either AggregateOids or of CollectionOids) are always
> TypedOids.
> >
> > With this change to AggregateOid, we can now say that all OIDs contain
> > enough information to fully recreate them as objects: we do know the type
> > of the object to instantiate and its unique identity.  That isn't to say
> > there's enough information to determine how these objects are wired back
> > together again, but that's a responsibility of the object store to
> persist
> > this additional structural information.
> >
> > ~~~
> > Following on from this, I've been working on a string format for each of
> > these three types.  Currently we have numerous incompatible ways of
> > memo-izing OIDs: the XML object store does it one way, the NOSQL object
> > store another, the SQL OS object store another, the "*Mapping" classes
> for
> > the scimpi and HTML viewers (for storing the states of transient objects
> in
> > the Http session) in another, the Memento utility class in yet another,
> the
> > JSON viewer (in its URLs) yet another.  It's all very complex and messy.
> >
> > Having a standard canonical string form would therefore simplify things
> > enormously.
> >
> > I've just been writing the unit tests for this, and I've come up with the
> > following:
> >
> > CUS:123                       - persistent root
> > !CUS:123                      - transient root
> > CUS:123#items                 - collection of persistent root
> > !CUS:123#items                - collection of transient root
> > CUS:123#NME:2                 - aggregated object within persistent root
> > !CUS:123~NME:2                - aggregated object within transient root
> > CUS:123~NME:2~CTY:LON         - aggregated object within aggregated
> object
> > within root
> > CUS:123~NME:2#items           - collection of an aggregated object within
> > root
> > CUS:123~NME:2~CTY:LON#streets - collection of an aggregated object within
> > aggregated object within root
> >
> > I've pasted in the unit tests for this below, so you can see the tests in
> > all its glory.
> >
> > Note how this allows for aggregates to be embedded within aggregates
> (even
> > though I'm not sure that any of the object stores could handle this yet).
> >
> > OK, that's it for now.  Wanted to put this out there for reaction; as
> usual
> > with these things, I'll assume silence = consensus.
> >
> > Dan
> > ~~~~~~
> >
> >
> > package org.apache.isis.core.metamodel.adapter.oid;
> >
> > import

Mime
  • Unnamed multipart/alternative (inline, None, 0 bytes)
View raw message