Slash Boxes
NOTE: use Perl; is on undef hiatus. You can read content, but you can't post it. More info will be forthcoming forthcomingly.

All the Perl that's Practical to Extract and Report

The Fine Print: The following comments are owned by whoever posted them. We are not responsible for them in any way.
More | Login | Reply
Loading... please wait.
  • by Ovid (2709) on 2007.08.20 16:08 (#57098) Homepage Journal

    When people talk about ORMs, I think they're generally looking at them the wrong way. The more I work with them, the more I think that trying to marry an class and a table is a terrible idea. I recently worked on a system where I could do something like this:


    That mapped to a table representing dedicated server, but that class had several other ORM classes it needed to interact with. That particular method hid tons of complexity behind it, including logging, deallocating IP addresses, interacting with Nagios, updating billing information and plenty of other things. There was no way you could think of it as a class mapping to a table, even though it had one main table for the bulk of its data.

    I now think the best way of using an ORM is to not hide the fact that you're dealing with a database and allow the programmers building the classes to merely think of the ORM layer as merely an object interface to the database. The code which uses the classes built on the ORM should never see a database, but so long as we don't think of the ORM as being the model, but rather as a persistence layer underneath the model, we can focus on creating a clean interface for people and merely have the model delegate behavior to the ORM as needed. The controller and view would generally not need to interact with the ORM at all (except where there's a direct delegation of model behavior to ORM behavior).

    This gives the developers plenty of freedom. Plus, when you find it easier to drop down to SQL, you still have a clean model hiding that. In this view, model classes don't inherit from the ORM, but merely delegate responsibilities as appropriate.

    I think this fits very well with what you're saying. If an ORM tries to do too much, it gets overly complex and difficult to maintain and work with. By accepting the limits of this way of working, we can let the ORM do what it does best but keep the hard customization bits in the model.

    • I disagree, kind of.

      I agree that a direct marrying of a class to a table can be a bad idea.

      I disagree that the abstraction cannot be a positive thing.

      My non-CPAN ORM ignores the class to table link and models the data at an entity-relationship level.

      From there, it derives BOTH the classes and the tables.

      Some of those classes don't have a table ("Transient Entities", imagine doing FormMail with all the structure and support of an ORM, but not ever needing to actually store the data) or don't write (I have "V
    • That sounds very much like how I think of DBIx::Class. Have you looked at it? I don’t think of DBIC as an ORM so much as I think of it as an OO API for SQL. Its basic unit is the result set – in other words, an OO wrapper around an SQL query. The main win for me is that I can accumulate conditions into queries (including composing result sets into one another) and let DBIC build the resulting SQL for me, instead of having to manually write template-ish SQL-generating logic for highly parametrisa

      • I've looked at DBIx::Class and it looks very nice, but I chose Rose::DB::Object. The project in question was an attempt to apply some discipline to a system where the code was rather typical of "legacy" systems. It was basically a bunch of CGIs and some of it already was a tad slow. One of our developers already had some performance issues with DBIx::Class on another project and I read some experiences others had with its performance. Since Rose is known for how incredibly fast it is (and I love how it

      • The main win for me is that I can accumulate conditions into queries (including composing result sets into one another) and let DBIC build the resulting SQL for me, instead of having to manually write template-ish SQL-generating logic for highly parametrisable queries.

        Any chance you could show an example? This is frequently cited as an interesting feature of DBIC, but there's not much in the docs about it. How is accumulating conditions and letting it build the SQL different from what the other SQL builders
        • It’s sort of a higher-order SQL.

          I can pass a ResultSet to someone else, and they can add constraints, joins, a group clause or such, as they like. This makes it much easier to decouple (and sometimes reuse) code. F.ex. I can build a ResultSet piecemeal along a chain of controllers in URI dispatch. I can even change some aspect of the query from within a template, eg. add a LIMIT clause to a passed-in ResultSet, without automatically having to tie the template to that particular query.

          Such a thing

          • Thanks, that's the best explanation I've heard of it.

            I've mostly used the data structure approach. RDBO includes a query builder which is much more powerful than SQL::Abstract and is able to represent joins and complex conditions reasonably well. I've done work with that where the conditions are built up similar to what you describe and then passed to the query builder to be turned into SQL.