|laziness, impatience, and hubris|
Re: Reflections on the design of a pure-Moose web app...by sundialsvc4 (Abbot)
|on Mar 23, 2009 at 13:31 UTC||Need Help??|
Sure... the first post was “a bit of a late night ramble,” so let me explain a little bit.
All of the database-access in the application does use an ORM tool: DBIx::Class. But the term, “object relational mapper,” in this case is entirely a misnomer. DBIx::Class is merely the tool that a Thing uses to avoid writing erroneous SQL queries.
An object ... a Thing ... is not “a database table,” nor “a query” nor “a view.” It is ... a Thing. You can instantiate it at any time, and having done so, because it is with Storage and somehow directly-or-indirectly associated with a session, you can keep it as long as you like. Each web-page request, or each AJAX request or what-have-you, can get access to “any Thing,” just as it was, without thinking about it. (The application actually uses a separate SQL database just for session and Thing persistence.)
In the application I've just finished, for example, a Seminar is something that you can sign-up for. The underlying database has several different tables that describe different kinds of seminar-offerings, but conceptually “a Seminar is a Thing that People can sign-up for.” It is not “conceptually, a database table or tables.” It is a well-formed, persistent Perl (Moose...) object, with methods to do any task and to answer any question that you may have with regards to it, anywhere in the application.
When you are dealing with a particular Seminar, the user may or may not ask to look at “the complete brochure.” If he does, we ask the Seminar object for its brochure information ... which the object retrieves (and remembers in its own properties) if it has not already done so. Some volatile information, like attendee counts, is always retrieved from the SQL database on-request, but most of the information is retained in the object itself. Information that you have not yet referred-to (like detailed brochure information) is probably not yet retrieved and may never be ... but if and when you do, the Thing knows it doesn't yet have the information you seek and the Thing knows how to get it. To the object making the request, “It Just Works.™”
The “shopping cart” is probably a better overall example. What is a shopping-cart, really? Well, it's a container in which you store things that you might eventually buy ... or it might be a container that you leave on Aisle 7, having walked out of the store. But it is a Thing that contains, among other things, a collection of other Things, and that can do things to that collection and/or answer questions about them. So, a Shopping-Cart, like all Things, is just a persistent, storable Perl object. And you work with it as a Perl object. Like all Things, it automagically serializes and de-serializes itself such that “it's always there when you need it.” When a sale is completed, the shopping-cart is responsible for “becoming a Real Boy” by creating appropriate entries in the SQL database.
I believe that the real “win” of this approach is that you are neither modeling an application that revolves around its database, nor an application that revolves around being a web-site. Both the registration application and the internal staff applications will use the same set of objects (and their descendents). The same coding techniques can be used in any context. And if the SQL database structure changes (as it inevitably must do from time to time), those changes don't ripple throughout the code.
The ORM, along with the database(s), has been kicked out of its center-of-the-universe position, and the web-framework has been reduced to being “just the engine that drives one-of-many possible user interfaces.” The central precept of this universe is: persistent Perl objects, built in Moose, which I call Things.
Does this help?