[Dbix-class] Re: Re: Re: Relations and inflation

Matt Rosin mattrosin at yahoo.com
Mon Jul 2 17:44:06 GMT 2007


Hi Jess,

I'm quite willing to give back to the project in terms of editing documentation but thought this might be limited to editing, because it should be written from the perspective of someone who knows the "right" way to use the system or its core philosophy.

I can't reply at length now since it is 1AM but will think about it some more. For a quick reply, yes I've read that page, the cookbook page, Relationships::Base, page, etc. and a number of times. But to me anyway it seems to assume a lot of knowledge, skips describing the foundation of what the module is intended to do, and skimps on the important parts. In order to get a feeling of which method to pick and how to practically use it you basically have to read many different documents over and over, pulling information in about other methods, and finally of course already know a lot of about what is really going on in the database. To me the module ought to be shielding you from having to think about it so much but that probably isn't realistic. To illustrate a couple points come to mind:

The very helpful replies I received about "insane layout" (i.e. having an id in both tables pointing to each other), it is not obvious to even someone who has used databases and perl a lot for small systems it isn't sane. Of course if the two relationships get out of sync then you might get different data depending on which table you start from, hence the insanity. But very little info on designing ORM based systems with lots of objects and relationships.

Also no information about Relationships and foreign relations. In fact I had been under the impression at least that mysql3 couldn't do foreign relations, and I'd decided to do it all using DBIx Relationships instead. The notion of foreign keys in the db being useful for maintaining integrity of data is not mentioned; it seems that a Relationship would do something like this but of course it isn't the same.

Also check out this part of the FAQ you mention, it is quite confusing actually.
"Relationships
   ... define a foreign key relationship where the key field may contain NULL? 
Just create a belongs_to relationship, as above. If the column is NULL then the inflation to the foreign object will not happen"

Now according to Matt's very helpful notes in the ML, allowing NULL in your db schema is used to tell belongs_to to be an optional Relationship, meaning that it will not enforce the belongs_to rule and autovivify. In other words use NULL so DBIx::Class::Relationships does not do inserts when it thinks that would be "the right thing". (or you can make a dummy record, but that's painful I found).

But the above passage comes from the other direction, assuming first that the developer wants to allow a NULL, and then explains that allowing NULL will disable object inflation (which I did not know until I just checked now!). It doesn't say that it disables autovivification, even though anything that does an INSERT is to me a potentially naughty thing and deserves to be well-documented. 

Now we go back to the perldoc for the belongs_to method does not mention that object inflation will be disabled, rather saying "If the relationship is optional -- i.e. the column containing the foreign key can be NULL -- then the belongs_to relationship does the right thing. Thus, in the example above $obj->author would return undef. However in this case you would probably want to set the join_type attribute so that a LEFT JOIN is done, which makes complex resultsets involving join or prefetch operations work correctly. "

This does not explain whether object inflation being "disabled" just means returning an undef if it's a NULL (which of course would be intuititive) or whether it means something like $listing->coupon will not return an object in any case if the field in question allows NULL. It also does not explain about from which side to make a Relationship (or both sides - no that's insane apparently, despite being logical in English anyway), though it is mentioned in the FAQ (regarding one-to-many) that "Currently these need to be set up individually on each side."

Also the pod mentions left joins and right joins. As I understand it a normal join would only provide records that match across the two tables but a left join would also show items not matched in the left table, and similarly right would for the right table. But this is not explained, and it is not clear why an ORM would not handle this sort of thing for you, or how the left/right sql metaphor for tables translates into parent object -> child object metaphor of DBIx::Class.

Something about usage of foreign relations in the db for integrity control would be helpful, and would explain the difference between what DBIx::Class::Relationships offers and what the db offers.

I think it would be quite helpful if a design example similar to what I had posted is used (you can use my objects if you want). For one thing there is confusion among people who want to use an object oriented system but then have to build an sql table schema to fit it. They start thinking in an object oriented fashion. Then they have to translate it into tables in their head (probably writing sql create statement by hand or with a tool like phpmyadmin, though maybe they really should use DbDesigner, or maybe they should just stay away from mysql and go to postresql). Anyway once they have the tables they start using DBIx::Class and it seems to work nicely, except it fails sometimes, and they end up having to figure out the more esoteric parts of the module which are not as well documented. I think this tends to lead to spaghetti objects, insane layout, and fragile schemas.

Well this turned out to be a long post. Sorry, and no offense meant at all, just that I'm willing to contribute to documentation in thanks for your support. So this is in response to how a non-dba person might see the module. I've used DBI and CDBI, etc. with Perl for many years but don't make my living as a database designer, and haven't needed to get high end database performance (my high performance mod_perl systems have used a Perl embedded db or a C++ based system). 

Anyway to try and wrap up this unending post, I would just mention that the DBIx::Class docs spend a lot of time talking about how you can agilely use lots of different chained methods to search or insert in related tables and so on, but spend very little time talking about what this actually does in the db, what the actual db schema is, whether something is available in mysql or another db or not, etc. For example I don't think I saw anything about sequences. I don't think foreign keys or null values were mentioned in the Artist/CD applications. Nothing about what "doing the right thing" could mean or how to design an application starting with a Perl (DBIx::Class) design and then what kind of tables you should make for those objects. I think this sort of thing might be useful.

Also I find a lot of my code tends to be paranoid. I test the results of all db updates and capture errors, displaying an error message and halting when processing hits an error. So I tend in my Catalyst app to first get required input arguments, test them (or die with a pretty error page to browser), then look up chained object info, testing whether the next link in the chain actually returns me an object or not and dying prettily each time if it doesn't. Finally I know I have good data and do the processing and output a template.

This is probably way too much code. For one thing a lot of this should be covered probably by integrity assurances in the db, at least that is my interpretation of a "sane layout". Though probably not to be expected if my client is editing the db manually. Also a lot of that should be done in Model modules, I'd expect, certainly it isn't DRY since I do it over and over. And I'd like to be able to look up a bunch of stuff with DBIx::Class and then check to see if any errors occurred, as one might with eval and $@, instead of doing so many tests, just to reduce the amount of code but maybe that isn't a great idea. So I admit the last app had just about all code in the controller modules and just schema and relationship creation lines in the model modules. This is not what the Catalyst people seem to like (since it makes it hard to access the system from command line or other interface than ordinary html browser) but it does seem to be what the cookbooks offer. So great
 volumes of extremely sane, DRY, smart layouts and uses of DBIx::Class and especially in a Catalyst environment would be quite useful to the world I think. This might require the developers of Catalyst and DBIx::Class to put their heads together but to me the more robust the better and if that can be done with less code and more extensibility to other interfaces then best yet.

Also for what it's worth, I found both startling, amazing, cool, mysterious and scary that I could access chained objects (in dot notation) from within a TT2 template that are not provided from the calling Perl subroutine, without any attributes specified, and that such a call could even cause INSERTS in my db from just trying to view what I'd planned as a read-only page in the browser (due to auto-vivification). Also if objects aren't available (I suppose if NULL, or if the id does not have a corresponding row in the other table) TT2 will crash I think, so you have to use TT2's defined keywords to try to sneak up on them, and sometimes that won't work it seems. So while this is a Catalyst and TT2 issue I think you might want to add something about this, and what actually is going on (what kind of a search is being made) when you call an object in TT2. (I'm talking about the case in which your TT2 template is displaying a list of "listing" objects, and if "r" is a single
 listing, you type "r.customer.b_company" to try and get the company name of the customer that owns the listing.)

Well I don't provide these as criticism, so much as trying to describe how the module looks to someone who does not have the same background as the developer. I hope you take it with a grain of salt too since it is more a measure of my own usage of it and lack of knowledge than as an imperative that you must do something about it!).

Thanks again and if you wish I would be happy to contribute or edit docs. Again, also I would like to thank Matthew Trout for his fabulous comments and help.

Matt Rosin


       
____________________________________________________________________________________
Moody friends. Drama queens. Your life? Nope! - their life, your story. Play Sims Stories at Yahoo! Games.
http://sims.yahoo.com/  



More information about the Dbix-class mailing list