# cparker@xxxxxxxxxxxx / 2007-04-09 15:29:01 -0700: > (I'm dealing with PHP4.) > > class User > { > var id; > var name; > var email; > var balance; > var accrual; > var is_manager; > > function User($user_id) > { > $this->id = $user_id; > $this->name = get_name(); > // ... > $this->accrual = get_accrual(); > } > > function get_name() > { > // get name from db > $sql = "..."; > > $db =& DB::singleton(); > $db->execute($sql); > } That static call on DB makes User tightly coupled to DB. This class won't work without the other. Aggravated by the multiple calls. Jochem cut the number down to 1 by doing the work in the constructor, but that doesn't remove the dependency, just makes it easier to remove eventually. The usual technique is to pass the database connection to the constructor: class User { function User($data_source, $user_id) { $this->ds = $data_source; $this->id = $user_id; $this->_fetch_data(); } var $ds, $id; function _fetch_data() { $this->ds->execute(...); } } Now, the User class is completely independent of the DB class. You can use User with any other class that has the same interface as DB. Of course, the more abstraction you provide, the more versatility you get, so you definitely don't want to have any SQL embedded in the business logic or classes as generic as User. I'll leave the issue of abstracting away data acquisition as an exercise for the reader. What about the places where you instantiate the User class? You would now need to change every new User($id) to at least new User($dbconn, $id) You can (and should) solve that by encapsulating the User instantiation. The tight coupling problem applies to all classes, including User. The industry standard technique to solve this is to use a creation or factory method: class UserFactory { function UserFactory($dbconn) { $this->dbconn = $dbconn; } var $dbconn; function create($id) { return new User($this->dbconn, $id); } } $uf = new UserFactory($dbconn); ... $user = $uf->create($id); And to prevent creating multiple instances of a single user (but you're screwed in PHP anyway): # NOTE: not bothering with references at all class Users { function Users($factory) { $this->factory = $factory; } var $factory; var $users = array(); function get($id) { if (!isset($this->users[$id])) { $this->users[$id] = $this->factory->create($id); } return $this->users[$id]; } } $users = new Users($factory); ... $user = $users->get($id); The classes follow two simple principles: Don't Repeat Yourself and Single Responsibility Principle (DRY, SRP). Sticking to them yields tremendous benefits in my experience, as does No Hardwiring, Please. Recommended reading: Design Patterns, Gamma et al.; Test-Driven Development by Example, Beck; Patterns of Enterprise Application Architecture, Fowler, C++ User's Journal archives. Also, did I mention that Singleton has turned a bit sour since its publication in Design Patterns, and is now considered an antipattern? Quoting one of the authors of the book: : It is a bad sign that the only pattern you mentioned was Singleton. : This shows you don't understand how to construct GUIs very well. : Singleton is a weak pattern, and whenever people start with : Singleton, it is a sign of a bad design. : : -Ralph Johnson -- How many Vietnam vets does it take to screw in a light bulb? You don't know, man. You don't KNOW. Cause you weren't THERE. http://bash.org/?255991 -- PHP General Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php