Ok, thanks to you all and this great discussion I want to try to make our current project into an MVC-style app, so what now? This MVC discussion could not have come at a better time - our little app is all grown up now and needs a real architecture. I have read the MVC threads in depth now, and I have questions.
WHERE WE ARE NOW -------------------------- We have a multiuser application that has about oh, I dunno, 100 different "screens" to the interface. They can be roughly divided into the following areas - status, admin, registration, reports, and graphs. Most of the actions involve either retrieving data from a database or processing a form and inserting into a database (in other words, it's a very typical web application). This application started as a CGI script. For performance reasons, we installed mod_perl and use Apache::Registry to run it now. It's pretty much still a dumb CGI script with a mod_perl wrapper, but I did develop a couple of modules to do user authentication with AuthCookie-based solutions and tied that into Apache::Session for state maintenance between requests. The CGI script has grown to accomodate these ~ 100 actions and is now basically a 4,000 line if statement. The script decides which request to do based on a target= parameter passed in (in other words, target=summary or target=doctoractivity, etc...). For sanity's sake, many months ago, we switched to HTML::Template (our view) to define our screens, which has worked well to date. On the back end we have PostgreSQL with a healthy sized schema of around 150 tables or so that has ~ 350 megs of data and on the order of 500,000 transactions a day (lots of data turnover, some tables get UPDATEd so frequently as to have 100% data turnover within 15 minutes). Anyways, back to the perl part.... Basic code structure: [snip] my $dbh = DBI->connect( $r->dir_config('RMSDBI_DSN') , $r->dir_config('RMSDBI_user') , $r->dir_config('RMSDBI_password') ); # giant if statement - closest thing I have to a controller, I suppose if ($target = 'summary') { my $tmpl = getTemplate('summary'); doSummary($dbh,$tmpl); print header . $tmpl->output(); } elsif ($target = 'doctoractivity') { my $tmpl = getTemplate('doctoractivity'); doDoctorActivity($dbh,$tmpl); print header . $tmpl->output(); } elsif ....... [snip] # lots of subs basically one per target, closest thing I have to a model, I suppose sub doSummary { ($dbh, $tmpl) = shift; $sth = $dbh->prepare("SQL STATEMENT HARD-CODED HERE"); # process result set into hashes and arrays of hashes such as @summary that HTML::Template wants [snip] $tmpl->param(summary => @summary); } sub doDoctorActivity { ($dbh, $tmpl) = shift; $sth = $dbh->prepare("SQL STATEMENT HARD-CODED HERE"); # process result set into hashes and arrays of hashes such as @summary that HTML::Template wants [snip] $tmpl->param(summary => @summary); } etc.... This basic pattern repeated ad infinitum. It's grown way out of control, is a pain to work with, and just feels wrong, very wrong. :-) To be fair, it grew very fast and it was all we (by we I mean the two of us that were this entire dept. back then) could do to keep up with the feature requests, let alone worry about proper architecting of the software. We're paying for it now, of course. WHERE WE WANT TO BE ------------------------------ I would like to introduce some semblance of organisation, sanity, maintainability, separation of logic, etc.... to this project. In other words, MVC would be a good fit. Some of the concrete, basic questions I have are: 1. Is there one Controller or many? Should I have one for each main area of my site? /myapp/admin/ goes to an Admin Controller, /myapp/reports to another controller, etc... 2. Does the first part of my code above even remotely resemble a Controller? I mean, it takes the input, calls essentially a 'model' object (but passing it the view object, nice, eh? =), but then seems to break the model nicely by doing things like printing out the HTML from the Controller, etc... 3. How do you prevent a Controller from just becoming another big if statement, or is this their purpose in life? 4. In the case of a form, what perl structure is used to pass the data into the model? 5. Do you create an actual class for each form? 6. Do you need to create objects at all? Is OO a prerequisite to MVC? 6.5. (thought of while proofreading :-) Is the statement "there is one set of controllers for each defined view" correct? In other words, if we someday want to output the "reports" section of the site as Excel spreadsheets in addition to HTML, would we define a new set of controllers or how would that work? Now onto the model, I think I have a little better grasp of the model compared to the controller, but I have questions... 7a. Is it insane to leave my SQL hard-coded in there? The queries don't change all that much, and it's nice to have the query in the same place as the processing of the result set so you can kind of "see" the structure of the result set better. This helps our less-experienced developers. 7b. Should I really investigate real object persistence like discussed at the POOP site (I have used Tangram with some success on tiny side projects but nothing remotely this size)? Begging the question, should I really be migrating to more of an OO style of programming? 7c. Is there some middle ground that would consolidate our database query code but not be a full abstraction layer which I simply think is overkill for what we need and for our current talents? 7d. Or do I -really- want an object/structure that represents every result set we need to get back from the database? 8a. What structures are used to pass back the data from the model through the controller to the view? 8b. The view is expecting HTML::Template style hashes and arrays, do I form these in the model (which seems to be too much knowledge of the view while still in the model) or does the controller convert it to the structures expected by the HTML::Template view? 8c. The model is getting DBI record sets from the db. I have to put this data into -something-, why not the exact format that HTML::Template view needs rather than process it twice? 9. Does the bottom half of my code resemble a model layer at all? Would each of those subs typically become a separate mod_perl module, or all live in a library of some sort, etc...begs the question again, is this all really supposed to be OO and I'm supposed to have a bunch of MyApp::Model::DoctorActivity modules that the controller 'use's? And finally, the view. This layer seems to be the 'simplest' of them to me since it's really limited in what it can do programmatically (for a good reason, I know). 10. We have situations like "if you are an admin show all three menu options, if you are regular joe user, you get one option. With HTML::Template now we handle this like so...getTemplate sets a number of standard parameters on each and every template. Kind of publishing the user's session to the template for the template designers to use. So, templates often look like this: menu option #1 menu option #2 <tmpl_if admin_user> Super secret option only admin can see </tmpl_if> How does this fit into the MVC model? Is this an appropriate use of the view? Doesn't "feel" like it is. These are just some of the many, many questions I have on this topic. I just can't quite get my head around it. I've got a small window of opportunity to introduce some of these concepts into our application but I need to be able to understand them a little better. Some stripped-down code samples would be nice (sometimes it's hard to decipher real code examples because of all the little quirks and intricacies of their specific situation clouding the raw demonstration of MVC and how it works), but any feedback at all to my questions would be met with wild enthusiasm. =) Thank you very much and I'm looking forward to your feedback. -Fran