Another wonderful term for the reading list: Unit Testing. But Patterns first...
The first question is: Does it work?
The second: What is each classes responsibility?
The third: Does any class have more than 1 responsibility?
The way I think of objects are as small narrow-minded (maybe even miserly) packages of functionality. Each object does one thing, and does it well. It doesn't care what all the other objects are up to so long as they give it the input it expects, and accepts the output it provides. Otherwise the whole population should start complaining loudly.
So we could have Users (easy to spot), the DataAccess functions to operate on them, and sets of other methods for various tasks: Authentication, Authorisation, etc. Now each of these are separate tasks, which suggest we need different objects for each. (Objects should have focused areas of responsibility). Also, if we combine all of these into one big class, we run the risk of losing any future reuse. If we try to re-use a User class in another application, we'll need to edit it and start messing with all sorts of stuff if the new application already has its own Authentication module. (Objects should be reuseable). On another tack, Objects should also contain the least amount of data possible - afterall the data may change, or become deprecated. (Objects should be independent of the data they operate on.)
Aborint might pop up now, and correct me...

But these are my personal watch-outs...
As an example. Let's pretend the code exists. We have methods, but what are they? We start the fundamental building block. We have User objects first. These carry User data, which comes from a database. So to fetch a User we could have something like:
Code: Select all
$user = new User();
$user->getByPk(1);
No source code yet - we're just getting a feel for how things slot together. At a minumum this suggest we could have a User class with properties (the data), and some Data Access functions to access the database and populate the class data. In pattern speak, we might consider using the ActiveRecord pattern, or RowDataGateway pattern, or similar. Knowing the pattern points the way to a workable implementation for our use.
Since we know users need to be authenticated, we might try an Authentication class (this is all it does - it hates doing anything else). This would be used similar to:
Code: Select all
$auth = new Authenticator();
$auth->authenticate($user);
The authenticate() method needs more info, it may need the POST data, access to SESSION, etc. These are already superglobals so the simple option is to use them directly. Further down the road we might find a need for a Request object (auto filtered version of POST), and a Session object (maybe).
Since I'm rambling on a bit here, and maybe made a point... I'll conclude with another problem. Say we might have multiple ways of authenticating a user (Password-Match, LDAP, Challenge-Response, etc.). How would you add each option to your original class? It's here where OOP starts making sense. You could have a parent Authenticate class, and various sub classes which implement each different strategy. The parent (in PHP5) could also be abstract.
Code: Select all
abstract class Authenticate {
protected $user; // all subs a User object!
protected function __construct() {} // might not be needed - I have a habit of sticking common
// construction tasks into a parent constructor
// abstract is an enforcer - this will create an error if a sub-class does not implement
// an authenticate() method
abstract function authenticate($user);
}
class Authenticate_PasswordMatch extends Authenticate {
public function __construct() {
// any construct tasks (if any)
}
public function authenticate(User $user) {
$this->user = $user;
if($this->passwordsMatch())
{
// do authentication tasks (add to a private function for readability)
}
}
private function passwordsMatch() {
if($_POST['password'] == $user->getPassword())
{
return true;
}
return false;
}
}
Usage:
Code: Select all
$auth = new Authenticate_PasswordMatch()
$auth->authenticate($user);
Is this making a little sense? By splitting responsibility into separate classes, we can create smaller focused classes, which are easier to develop and modify. A simple PasswordMatch authentication class is a basic unit in a web app - it could be re-used in later projects with few changes (none if you remove the dependencies like $_POST, and add a function to set a Password field to match).
Such classes are also easier to test (Unit Testing or other), and more readable if you keep methods small and focused and dump complex bits of logic into nicely named private functions. It's also more complex which is the main cost of all these OOP practices.
Okay, I'm going to shut up now and stop typing away like a mad hatter on speed...