拆分一个大型PHP类


Splitting a large PHP class

我有一个很大的类(1500行,但很快就会是这个类的几倍),我想拆分它,这样它更适合SRP(并且每个文件都更小,更易于管理。)

该类包含50-100个属性,并对其执行了几种不同类型的操作,其中一种是update,它依次执行几个步骤,如更新数据库和发送电子邮件。

所以我想我想要4节课。

我应该如何构建类?


这是我现在拥有的一个简化版本:

class Foo {
    public function __construct ($params) {}
    public function update () {
        $this->updateDatabase();
        $this->sendEmails();
    }
    private function updateDatabase () {}
    private function sendEmails () {}
}
$foo = new Foo($params);
$foo->update();

updateDatabase()sendEmails ()分别调用许多其他方法——每个方法都有数百行代码,它们有几个兄弟方法执行其他任务。

使用静态方法的基本重写

class Foo {
    public function __construct ($params) {}
}
class FooUpdate {
    public static function update ($fooParam) {
        FooUpdateDatabase::main($fooParam);
        FooSendEmails::main($fooParam);
    }
}
class FooUpdateDatabase {
    public static function main ($fooParam) {}
}
class FooSendEmails {
    public static function main ($fooParam) {}
}
$foo = new Foo($params);
FooUpdate::update($foo);

使用实例化对象的基本重写

class Foo {
    public function __construct () {}
}
class FooUpdate {
    private $foo;
    public function __construct ($fooParam) {
        $this->foo = $fooParam;
    }
    public function main () {
        $fooTemp = FooUpdateDatabase($this->fooParam);
        $fooTemp->main();
        $fooTemp = FooSendEmails($this->fooParam);
        $fooTemp->main();
    }
}
class FooUpdateDatabase {
    private $foo;
    public function __construct ($fooParam) {
        $this->foo = $fooParam;
    }
    public function main () {}
}
class FooSendEmails {
    private $foo;
    public function __construct ($fooParam) {
        $this->foo = $fooParam;
    }
    public function main () {}
}
$foo = new Foo($bar, ...);
$fooTemp = new FooUpdate($foo);
$fooTemp->update();

或者我应该以某种方式使用遗传或特征?

正如@SparK所说,

  • 您的对象(Foo)
  • 一个处理数据库通信的类(FooRepository)
  • 发送邮件的类(Mailer)
  • 包装所有内容的类(FooManager)

    $foo = new Foo($params);
    $fooManager = new FooManager(FooRepository, Mailer);
    $fooManager->update($foo);
    $fooManager->notify($foo); //this could be inside the update or an event.
    

通过这种方式,您还可以分解类(即:分离处理数据库连接的类,并将其注入FooRepository等)。但我不认为拥有代表一个动作的类是一条路吗?

类是可以执行操作(以及其他操作)的对象,而不是操作(这只是一个注释,因为您在示例中使用了名称:p)。

我想发送电子邮件是一回事,表示数据是另一回事,对数据库的读写操作是第三回事。

所以class Fooclass FooPersistenceclass FooMailer
无论谁调用FooPersistence::update($foo),都应该同时调用FooMailer::sendUpdateNotification($foo)

附带说明:
如果您设置了类似Events的东西,我会在持久性类中触发"更新事件",并为其添加一个发送电子邮件的侦听器。