> а, еще лучше, постараться накидать диаграмму классов или взсамодействия на листке бумаги. Не обязательно эта должна быть диаграмма UML.
Фигня этот UML на самом деле. В документации - да, а на этапе разработки нифига не годится. Потому что код много раз может поменяться, а в месте с ним придется перерисовывать всякие схемы. Тесты, вот что надо. И мыслить абстракциями.
Вот к пример как выглядит доступ к экземпляру определенного класса
PHP:
include_once("reference/group.class.php");
$obj = new Group;
$conn = DBConnectionManager::getConnection();
echo "Init ".get_class($obj).": ";
try {
$conn->executeUpdate( $obj->getSqlCreateTable() );
echo "ok\n";
// make default groups
$obj->make();
$obj->f_system = true;
$obj->f_active = true;
$obj->name = "all";
$obj->description = "All users";
$obj->save();
}catch (SQLException $e){
echo "fail\n";
// echo $e->getMessage(),"\n";
}
Это инит БД, а в типовых случаях никаких экспекшенов, и никаких крейттейбл.
А это декларация вышезаюзанного класса
PHP:
include_once("orm/persistent.class.php");
class Group extends Persistent {
protected function _registerAtoms(){
parent::_registerAtoms();
// primary attributes
$this->_setAtom( "name" , new Atom_String(16),true );
$this->_setAtom( "f_system", new Atom_Boolean() );
$this->_setAtom( "f_active", new Atom_Boolean() );
$this->_setAtom( "description", new Atom_String(64) );
}
protected function _onDelete(){
if ( $this->f_system ){
$this->log("%s::%s Couldn't delete system group: %s",
ML_WARNING,__CLASS__,__FUNCTION__,$this->name);
return false;
}
return true;
}
}
По моему выглядит достаточно лаконично. И поведение объекта как и положено реализовано в классе. Это простой пример. Можно привести посложнее. Например User
PHP:
include_once("orm/persistent.class.php");
include_once("group.class.php");
include_once(dirname(__FILE__)."/../map/user_group.class.php");
class User extends Persistent {
protected function _registerAtoms(){
parent::_registerAtoms();
// primary attributes
$this->_setAtom( "login" , new Atom_String(16,3) ,true);
$this->_setAtom( "password", new Atom_String(32,32) );
$this->_setAtom( "name", new Atom_String(64) );
$this->_setAtom( "email", new Atom_String(64) ,true);
$this->_setAtom( "registred", new Atom_Timestamp() );
$this->_setAtom( "f_active", new Atom_Boolean() );
// flags & secondaries
$this->_setAtom( "signature", new Atom_Text() );
// other settings
}
// и методы
// аутентификация на основе данных базовой авторизации
public function authBasic($login,$password)
// работа с группами (на основе объектов класса Group)
public function addToGroup($v)
public function inGroup($v)
public function getGroupList()
public function removeFromGroup($v)
// переопределяем, что бы хешировать пароль при задании
public function _set($name,$value)
// и поведение по умолчанию
protected function _onInsert(){
if ( !$this->login ){
$this->setLastError("Login value must be defined");
return false;
}
if ( !$this->name ){
$this->name = $this->login;
}
return parent::_onInsert();
}
protected function _onUpdate(){
return $this->onInsert();
}
protected function _onSave(){
$this->addToGroup("all");
}
В базовых классах скрыта вертикаль абстракций. Т.е. уходя в глубину иерархии наследования понятие нашего объекта расплывается.
Т.к. поведение объекта такого типа лишь косвено зависит от источника данных, никаких коннектов в иерархии. Для управления источниками данных мы абстрагируемся до уровня DSN. А нужный коннект нам выдает DBConnectionManager::getConnection() в который можно передать DSN.
И еще раз к тестам. Сначала мы пишем тест. Пусть это будет тест абстракции которой не существует, но этот тест четко описывает - что мы хотим получить от этого класса. Естественно мы хотим получить методы и атрибуты. Тест определяет что должно быть в классе, а сам класс реализует механизм. Иначе говоря тест это ответ на вопрос - что, а класс - ответ как (каким образом). Рассматривая проектирование с этой точки зрения трудно представить, как можно программировать без тестов. Вот и я не представляю

Любое фатальное изменение класса отражается в тесте. Это значит что вам не придется искать "гдежев этойгребаннойкучемалескрылсябаг". Так как каждому классу соответствует свой тест (unittest,unitcase), набор тестов можно рассматривать как схему вашей системы. При чем эта схема однозначно и точно говорит о актуальности кода (в отличии от всяких схем, которые могут быть исправлены не зависимо от кода).
Кароч, я могу продолжать долго и примеров могу привести массу

но основная мысль - это учиться программировать не модульно или объектно-ориентировано, а test driven. А начать можно и отсюда
http://phpclub.ru/faq/wakka.php?wakka=TDD&v=155f