Hello perl-bikkhus!

I've been working on a photographer's application suite for several months, in Perl. It's object model contains about 20 business objects in photographer-speak: Client, Shoot, Image, and so on. And about 15 many-many relationships between these objects, which a user of the object model API never has to deal with directly.

It's implemented using Class::DBI against a MySQL backend. If you've never used Class::DBI and would like to be able to dash off a complex data model in a few hours, look into it. And then look into its helpers, Class::Accessor and friends. Then look into your alternatives, which I encourage fellow monks to suggest in comments below.

Now, after being quite pleased with how easy the modeling was, even the 15 many-manys, letting me get on to the 'more important' business of application coding (it has a CGI and command-line interface, GUI coming soon(TM)). All was well until... bumbumbum.... requirements change.

The app system must now be able to dump its records as XML, as well as read records. Ideally, the XML records would be fairly human-readable, follow the same object model previously developed for the Perl API, and be potentially recoverable or exportable to other apps as painlessly as possible. Eventually, database replication may occur over an XML pipeline, so the XML schema-space ends up covering the entire Perl API.

In other words, like so many Perl data objects these days, I need to be able to serialize the object's state into XML, and move between different datastores. Many times, I will not have access to a DBI (or more specifically, Class::DBI) type datastore, and will operate in XML-only mode.

Unfortunately, one place where Class::DBI doesn't shine so well is operating in "in-core-only" mode. In fact, there's no such thing :-). AFAIK, You can't (meaningfully) work with Class::DBI subclasses without a real, working database with your particular schema.

Ok, you can do some wizardry - maybe even edit Class::DBI to you liking - but that seemed grueseome. And my new req's do allow me to have Class::DBI initially disabled, and then turn it on later. So I didn't have to implement a "turn-off" feature, just a more careful object loader ("don't turn Class::DBI on until I say to").

I've started writing a "Pure Class" that follows the object model already established, and I have abstracted out the persistence engine (CDBI or XML) as an optional has-a instance attribute. So, a FooApp::Shoot has-a FooApp::CDBI::Shoot, and so on. Sounds easy, right....

Traps I've hit so far, and feel free to add:

You see where I'm going. Mind you, I'm still getting a lot of mileage out of Class::DBI as the worlds niftiest SQL generator, but whew, this looks hard. And perhaps a monk has been down this road before....

Replies are listed 'Best First'.
Re: many-many relations in object modeling
by Corion (Patriarch) on Jun 03, 2005 at 08:18 UTC

    I would use something like Class::DBI::Loader to keep the data model definition in one place, and there has recently been a hack on the cdbi mailing list to create "unbound" Class::DBI-like mock objects that one can manipulate and only later save into the database (or not at all).

    Here is the mail by Peter Speltz, a tentative name is Class::DBI::Plugin::Temp.

      Hmmm, good call. Mind you, I have my 20-or-so objects already coded up using Class::DBI (each in their own little .pm file, aren't I precious). One of my next steps was going to be autogenerating that sort of code anyway - and Class::DBI::Loader will be a huge help on that front. I'm still stuck with 'class definition code' somewhere - but at least now it can be in my "Pure Class" where it belongs. Thanks!
Re: many-many relations in object modeling
by castaway (Parson) on Jun 03, 2005 at 08:19 UTC
    I see this is formulated mostly as a discussion rather than a question, but still it seems to beg the answer:

    Did you look into/at DBD::AnyData? (Which is a DBI interface to using text/XML/CSV files as a database)

    C.

      I could be wrong, but I don't beleive DBD::AnyData (or AnyDBD) is on Class::DBI's supported database list.

      I did look at it; I've used it on a mystery CSV file a few times. Maybe the right tool, but the wrong handle.

      Straight DBI coding style never suited me; when I code up an app I want to think in terms of objects. I want some glue to hide the row fetching, etc. That's one reason I like Class::DBI; I want the object model glue.

        DBD::AnyData should work with Class::DBI now. I even have a Class::DBI::AnyData and Class::DBI::Loader ::AnyData sitting around somewhere if you want them.