|
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
|