> -----Original Message-----
> From: Fran Fabrizio [mailto:[EMAIL PROTECTED]] 
> Sent: 13 June 2002 06:48
> To: [EMAIL PROTECTED]
> Cc: [EMAIL PROTECTED]
> Subject: Re: separating C from V in MVC
> 
> 
> 
> Ok, great stuff, now we're getting somewhere.  So, the model = the 
> nouns.  Good.  That helps.  Now, how do you represent in the model a 
> complex query that joins across 5 of the nouns?  

In my other post about Controller, I assert [but feel free to disagree!]
that Models are really Nouns+Business Verbs


> network monitoring and display tool.  It receives status 
...
> them."  We call this a stale watch.  We have a report that 
> shows all of the 
> currently stale watches across our network.  The query is a 
> join of around 
> 4 tables (or nouns) - Site, Watch, Watch Config, Message - 
> something along 
> those lines.
> 
> Does one create a model object called StaleWatchReport?  That 

Not generally. Having grasped the core business Model classes, you now
need to also realise that the real world often deals with Collections of
objects. So instead of a StaleWatchReport class, what you need is a
collection of Watches that are stale.

You should ask this collection to present qualifying Watch items.

Collection can be powerful, so give some careful thought to this, and
don't bind your Collection base class too closely to the database (there
was another post by someone on keeping $dbh chroot jailed!)

Here is an example, though there are many other possible collection
approaches.

Controller:
-----------
my $Stale  = Model::WatchCollection->new( status => 'stale' );
my $View   = View::StaleWatches( stale => $Stale );

$self->headers();
print $View->render();


View::StaleWatches
------------------
foreach my $watch ( @{$Stale->fetch()} ) {
  describe_in_HTML( $watch );
}

Note that the web controller knows nothing about stale watches, it just
knows that given the current request, it will pass the token 'stale'
into the WatchCollection. You can use the same Model::WatchCollection
class in a batch overnight report, and it too will understand how to
identify stale Watches.

Here is an alternative, possibly better approach:

Controller:
-----------
my $WC    = Model::WatchCollection->new();
my $View  = View::StaleWatches( watches => $WC );

$self->headers();
print $View->render();


View::StaleWatches
------------------
foreach my $watch ( @{$WC->fetch( status => 'stale' )} ) {
  describe_in_HTML( $watch );
}


In this second example, we have even moved the need for the Controller
to know about 'stale' into the View, which already knew that it only
wanted stale Watches.

> In your concert example, if I wanted to define a report that 
> showed me all 
> of the seats that were purchased by people from New Jersey with a 
> Mastercard in the last week, how would I represent that?
> 

The web request might look like this:
  /seats?qstate=NJ&qcard=MC&qpurchased=-7

Controller:
  my $query = {};
  foreach ( parameter starting with q ) {
    $token = param name without the 'q';
    $query->{token} = URLDecode(parameter value);
  }
  my $SC = Model::SeatCollection->new( query => $query );
  my $View = View::SeatGeneric->new( seats => $SC );
  $self->headers();
  print $View->render();

Note that the Controller handles decoding the parameters etc, but
doesn't care what queries that the SeatCollection understands. It does
understand a mini protocol where query params start with 'q', but this
is not business logic, it is UI logic.

Next you'll want to know about handling Form validation and Models with
multiple field level exceptions? 8-)

Jeff


Reply via email to