Dan, Thanks for such a thorough reply. I'm up late again tonight, shanghai time. lots of fun ;). I'll read through these notes a few more times as I'm working on associations and see if I can get it down.
thanks, Jon On Dec 23, 2:33 am, "Dan Kubb (dkubb)" <[email protected]> wrote: > Hi Jon, > > > Dan, > > I hope I didn't ignite some negative reactions. Not my intentions. > > Is this in reply to my message? It looks like you addressed this > reply to me, but replied to David's? > > > There are certainly parts of the DM API which are not consistent but > > that's why its not v1.0 yet, right? > > Yeah, that's why we've held off 1.0 despite alot of pressure to go > 1.0. As soon as we do, there's API lock-in and it will be alot more > difficult to make changes. Even now though there's a certain amount > of lock-in due to the size of the community that we have to work > around each time there's a change. For every change there needs to be > a deprecation period lasting at least a few months where the old and > new approach works, as well as updated specs, docs and dm-more > plugins. > > I think one of my points in my grandparent post was that IMHO being > consistent in an API is more important to me than convenience. I like > things that are consistent to use, and consistent internally. If one > is at odds with the other I personally opt for consistency when > designing APIs. > > I think that's why most people are attracted to DataMapper too -- they > prefer the explicitness of the property and relationship declarations, > and how easy it is to understand the structure of DataMapper models > due to their consistency. And while we could introspect the structure > from the data store to define the properties, we decided that trading > off a bit of convenience for something that is easier to understand at > a glance. > > > I'm ok with that as long as others are ok with continuing the debate > > on making it more so untl we get to a 1.0 API > > If we're doing something totally at odds with established conventions > in data modeling I would like to discuss it. However, I'll provide > the reasoning behind the way has() works the way it does, and give a > sneak peek into a future planned API that may actually solve some of > the usability issues. > > > I'm working more on my code tonight. I'll think about your comments > > and see if I can make a better reply > > There was a time when I first used AR about 3 years ago that has_one > and belongs_to was confusing. I would always forget which side of the > relationship the key was on with has_one, since I rarely use it. It > wasn't until I started working on DM earlier this year that it made > sense. > > In DataMapper the has() keyword implies ownership of the model on the > other end of the relationship. We decided to use the term parent/ > child to describe the two sides, after discussing it at length because > we couldn't think of anything better. The commands has(n), has(n..n), > has(1), and has(0..1) are all used on the parent model, and alter the > child model to have a child key (FK) that points back to the parent. > > In data modeling, at the conceptual level, the entities on either side > of a one to one relationship are equal. The term "has one" is correct > to describe the relationship each entity has to the other. It's only > when you attempt to describe the relationship at the physical level > that you have to decide which of the entities is going to receive the > foreign key. In all the data modeling reference material I could > find, it was stated that the FK should be placed on the entity where > the "must be one of this for the other" constraint is more likely to > be relaxed. > > A poor example of this (but the best I can think at this time) is > imagine you have a Part and a Bin, where "Part has one Bin", and "Bin > has one Part". Say that it doesn't make as much sense to store > multiple Parts in a Bin, and you can conceive that someday you might > have so many Parts than could fit in a single Bin. Given this you > place the FK on the Bin side, which would allow you at some point to > relax the application logic and the "Part has one Bin" constraint can > become "Part has many Bins". In DM this would mean you change the has > (1) constraint to has(n) and nothing changes at the schema level. > > I'll concede that the choice to put the FK at the "other end" when > using has(1) is totally arbitrary on DM's part. The main reason it was > done was to maintain consistency with other has() usages. > > IMHO belongs_to is a bit ugly, and a hold-over from AR. The term > "belongs to" is clumsy in alot of cases, and I think causes > confusion. Sure, it makes sense to have Order belongs_to Customer. > But there are many other cases where this doesn't read too clearly. > One option would be to have a few aliases that mean the same thing at > belongs_to, but that sort of breaks with consistency and increase the > size of the API that one would have to learn before being able to read > a DM model. > > The option that I am leaning towards right now is to deprecate > belongs_to and make it so you can define a property() that references > the other model. So instead of this: > > class Order > # ... > > belongs_to :customer > end > > You could write: > > class Order > # ... > > property :customer, Customer > end > > So the usage of a Model as the property type would create the customer > accessor/mutator (which is exactly what happens anyway for a type), > but it would also create whatever child keys you need underneath. Any > options passed to property() would be passed down to the child keys on > creation, allowing you to specify nullability, indexes, etc. I think > this reads quite naturally, and so far everyone I've shown it to > thinks it is pretty easy to understand. > > This also fits in nicely with the planned Embedded Value type (see > PoEAA). It would use the same API as a Model, so that the DM model > user would only see that there was a "customer" property, which could > map to an Embedded Value. Later it could be upgraded to a full Model > by changing the "include DataMapper::EmbeddedValue" line to "include > DataMapper::Resource", and of course a classic migration to move the > data over. > > The only barrier to this is that we have to figure out a strategy to > handle cases where the Customer model hasn't been loaded yet. Since > model load order is nondeterministic this is a very real possibility. > Unless it is dealt with an exception could be thrown because the > Customer constant hasn't been defined. I think I have a solution > using const_missing in DM::Model, but I want to make sure it will work > properly with threading and a few other scenarios. > > Dan > (dkubb) --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "DataMapper" group. To post to this group, send email to [email protected] To unsubscribe from this group, send email to [email protected] For more options, visit this group at http://groups.google.com/group/datamapper?hl=en -~----------~----~----~----~------~----~------~--~---
