Refactoring for Growth
These notes are not complete or edited at all... once there's code... it'll be closer to done.
The only way to grow an application quickly without causing your system to topple from its own (code) weight is by investing some effort in creating better structures for code.
Mostly, I'm looking at a modified Model-View-Controller design. It has to differ, because MVC was meant for point-and-click GUIs, and web apps are all done via forms.
After mucking around with some test code, and reading articles on the web, I started to concretize something. The Controller tends to be the central component, and interface to the page, and loosely coupled with the View... making a View-Controller. The Model, on the other hand, tends to get split into the business logic and a database persistence class. The db part becomes its own class because each page load clears memory, and forces us to touch the db. I just call these the Manager and the Table-and-TableRow.
http://www.onlamp.com/pub/a/php/2004/10/14/page_controller.html
http://www.tonymarston.net/php-mysql/infrastructure.html
http://www.tonymarston.net/php-mysql/oop-for-heretics.html
According to OO gospel, you're not supposed to let the Controller access the db abstraction. This seems to be a real burden, though, because it would force a lot of code to be created in the Manager that really does nothing. My inclination is to allow reading from the db classes by the Controller, and letting the controller pass the data to the View class methods. Relegate the Manager to "management" of the contents of the data.
This makes it harder to swap out the db, but the risks are lower if you're strict about never writing data from the Controller.
Also, you're not supposed to do any of the fancy SQL in the db abstraction... but you have to do it somewhere. One dead-end (IMHO) was building up SQL from fragments of text, and encapsulating the idea of a JOIN in program code. This was hard to read and confusing. A nice solution was to put the SQL, complete, or more or less complete, in the Table-and-TableRows classes, and deal with these classes not as "db abstraction" but "data abstraction". Give them some liberty to join tables so the data they produce is useful.
If you want to fix your SQL, it's all in the classes that extend Table and TableRow.
If you want to change some aspect of how the program works, it's in the Controller or the Manager.
If you want to create a test case for some high-level behavior, it's best to create the "API" for the behavior in the Manager, and then test it there.
Lastly, for convenience, I'm putting all four classes into a single file, called a Package. You can split them into different files, but, that would make uploading the classes harder.
--------------
Inspired by Marston, I decided to go against my habit of turning rows in the database into full fledged objects, with properties that mirrored the columns. Most of the quick-and-dirty code I'd been writing for work (as well as Perl scripts for system administration) used associative arrays, and they were working fine.
Traditional OO code turns the array into an object, but typical PHP code uses the object, more or less, like an array again, almost immediately. Unlike a GUI app, where the data persists for a while, and is manipulated by the user a lot, before being saved to the database... the web app reads the data, alters it, writes it out, and then displays it. It does this over and over.
Reading from the db returns the data in an array. Writing to the db is via an SQL statement composed from the array or object. The display classes can be designed to use arrays or objects, but, ultimately, it doesn't matter - the code is almost identical. So, it's probably preferable to keep the data in an array format.
If we need real OO, we can implement it... but assuming data is passed around as arrays will save a lot of coding effort.
----------
An internal and external debate exists about returning arrays versus returning an object that iterates over the result set. The latter is generally considered better practice.
I recall that my original impulse to use the array instead stems from the fact that PHP has very good support for arrays, and, often, you end up iterating over the entire result set anyway. Building up the whole array takes more memory, but, web pages tend to consume memory quickly, generate the output, and then release the memory.
Still, having the iterator would be useful.
----------
A good article on real-world scalability.
http://www.onjava.com/pub/a/onjava/2003/10/15/php_scalability.html
