Beefy Boxes and Bandwidth Generously Provided by pair Networks
Clear questions and runnable code
get the best and fastest answer

Re: How to structure applications using a RDBMS

by Ovid (Cardinal)
on Jul 18, 2002 at 22:57 UTC ( #183078=note: print w/replies, xml ) Need Help??

in reply to How to structure applications using a RDBMS

I'm not entirely sure that I understand what you're asking, but I'll answer what I think you meant.

For every program, we basically have two things: things that need to be done and the data that it's done to. Things that need to be done (procedures) are like:

  • Get orders for given month and year
  • Sum orders and generate inventory report based on orders
  • Output order totals report and inventory totals report

The "procedural" type of stuff goes into procedural code. However, creating objects as wrappers around all data access can be convenient. For example, you don't return an order as a hashref, but as an object (ignore the names, this is slapped together):

my $order_obj = Foo::Order->new; my $orders = $order_obj->by_date( $date ); foreach my $order ( @$orders ) { my $items = $order->items; # arrayref of item objects my $total = $order->total; # returns a value # do more stuff }

Now, you can rearrange your procedures all you want and not worry about the data. Also, you can change the internals of the objects all you want as long as you keep the API. If you want to minimize the impact of schema changes on the business logic, this will eliminate the impact of schema changes. Update your object code and ensure that the API doesn't change.

This has another advantage people don't think about. If you force the programmer to use accessors any time you return anything other than a scalar (and mutators for virtualy all data) you have a single point of control for the data. If you realize that a particular piece of data must never be set to negative three, by forcing the programmer to use your mutator, you have one and only one spot that you have to worry about. Giving them direct access to the data means there are probably multiple places that you need to check.

Further, you can put the SQL in the objects themselves or push the sql down into another layer so that even your objects don't connect to the database directly. This is a great refactoring. You can define some consistent ways for individual objects to identify their tables, fields, and keys and you can write generic routines like this:

sub delete_me { my $self = shift; my $sql = "DELETE FROM $self->{_table} WHERE $self->{_id_name} = ?"; return $self->{_dbh}->execute( $sql, $self->{_id_value} ); }

You can abstract away a lot of code with this, but you will almost always have special cases. It ain't perfect :)

Of course, this is great if you have black box unit testing. Update your objects to your heart's content, run the tests and you know your API hasn't changed and any procedural code that's dependant on the API is much more likely to work without changes.

Sorry if this seemed pedantic :)


Join the Perlmonks Setiathome Group or just click on the the link and check out our stats.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://183078]
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others drinking their drinks and smoking their pipes about the Monastery: (2)
As of 2017-06-29 06:06 GMT
Find Nodes?
    Voting Booth?
    How many monitors do you use while coding?

    Results (653 votes). Check out past polls.