From: Vsevolod (S. I. <si...@cs...> - 2004-12-04 15:57:29
|
Hi, > For auto/lazy fetch configuration, the publisher field in the book > object is ALWAYS the publisher OBJECT whose ID is stored in the > publisher column in the database. > $book->publisher == object > In the case of auto-fetch, the assignment, $book->{publisher} = > $book->fetch_publisher, is executed when the $book object is fetched. In > the lazy-fetch case it happens the first time $book->publisher is called > (or $book->{publisher} is accessed). Again, the purpose of this is to > allow me to think of my book's publisher field as a Publisher object. I don't think you can persuade me that this approach is neater. One of the best things about SPOPS is that it lets me think accurately in terms of my tables and my objects at the same time. Each database field name corresponds to an object variable name, period. Having the 'publisher' id column correspond to a 'publisher' object will break the neat mental picture. Plus, there is a huge downside that if I want to find out parent_id from a child (for the auto/lazy fetch), I'll have to call child->parent->id, which means that for the lazy fetch I have to retrieve the parent to get parent's id, though it's present in the child anyway. However, see more below. > - What do you call the field where you stash the auto-fetched object? > Always specify explicit name in config? This can be auto-deduced from class names (config hash keys, not Perl names). Currently SPOPS supports the config key {main_alias} to be used in such cases. > - When auto-saving how should SPOPS handle inconsistencies between the > id of the object in the publisher field and the value in the > publisher_id field? Or to put it another way, if I want to re-assign a > book's publisher, do I assign a new id to the publisher_id field or do I > assign a new object to the publisher field? It's possible to generate methods in such a way that all related id fields and objects are updated when a change happens. However, this is implementing caching all over again. This makes me think that maybe storing objects in fields is not such a good idea after all. (Currently SPOPS does not do it, and the code that I've written before Ray's objections does not do it either.) This brings up another problem, though. How should save() work in the many-to-many configuration when the parent is saved? Currently links_to calling addChild() method already causes an update of the linking table. Hence, when parent->save() is called, there is no need to update the linking table, though the framework can go ahead and save the children objects if auto-save is specified. Oh, wait! We don't have the children objects because we don't like storing objects in the fields! We have to re-fetch the children and then save them. Fortunately, I have the "cache_only" option for fetch_group() which will only return objects in cache, but we still have to make a database call because we don't know what IDs we want. In the one-to-many configuration, the addChild method updates the parent_id field in the child object and saves it, which amounts to auto-save, even though it may not have been requested. The code can be changed, though, to only save the new parent_id of the child object. The problem lies in the fact that we perform database saves not just in the save() method, but also in the add/removeChild operations. What happens if the add/remove operations do not access the database? We have to either 1) maintain a hidden list of dependent ids and work with it, or 2) go Ray's way and maintain a list of dependent objects. To maintain consistency we can either A) add logic to generated methods to keep those ids in sync, or B) prohibit saying child->parent_id if it can be obtained as child->parent->id. How do we deal, though, with manual fetch (when a dependent object is not stored) plus auto-save (when a dependent object/id should be stored to be saved)? I'll try to install Hibernate this weekend and see what they do there. I've looked at Fowler's "Patterns of Enterprise Application Architechture", but I don't think he brings up the problem of saves. Fowler gave me an idea, though - the various id fields pointing to other objects should be read-only. This way there is less chance of creating confusion. Currently the methods that return objects (parent() or children()) are only getters, but if we want to be really object-oriented, it would be nice to make them setters too, and if we can't set ids directly any more, setters may become manageable. > Seems much more messy to me for something that I consider to be > completely new functionality (no backward compatibility issues to worry > about). While it does eliminate the need for the manual fetch option, as > Simon mentioned earlier (and probably even lazy fetch), it also > eliminates one of the main features for me, which is the ability to take > an existing field and treat it conceptually as an object. But I like having parent_id() and parent() methods separate, because I should not completely forget that I'm dealing with a database. Simon -- Simon (Vsevolod ILyushchenko) si...@cs... http://www.simonf.com Terrorism is a tactic and so to declare war on terrorism is equivalent to Roosevelt's declaring war on blitzkrieg. Zbigniew Brzezinski, U.S. national security advisor, 1977-81 |