2012-09-03 139 views
2

我一直在开发用PHP编写的PBBG(游戏)& MySQL 7个月。该项目即将完成并可能即将发布,但我担心一些问题。我正确使用OOP吗?

这是我第一次编程一个真正的项目,也是我第一次使用OOP。我的代码现在有大约25k行,这里是我的问题:

我是否正确使用OOP?我相信我是过度调用类构造。我有大约20个不同的课程,有时他们需要彼此。下面是一个示例代码,我如何使用OOP(只是一个草图,可能无法正常工作)

class A { 

    public $b; 
    public $c; 

    public function __construct(){ 
     $b = new B(); 
     $c = new C(); 
    } 

    public function sampleA(){ 
     //some stuff that depends $c->sampleC 
    } 

} 

class B { 

    public $c; 

    public function __construct(){ 
     $c = new C(); 
    } 

    public function sampleB($id){ 
     return $this->c->sampleC($id); 
    } 

} 

class C { 

    public function sampleC(){ 

    } 

} 

然后我会使用:

$a = new A(); 
$b = new B(); 
$c = new C(); 

$whatIWant = $a->sampleA($b->sampleB($c->sampleC())); 

虽然我可以只

$a = new A(); 
$whatIWant = $a->sampleA($a->b->sampleB($a->c->sampleC())); 

在这个简单的例子中,这看起来没有任何意义,但是我的脚本有超过200个不同的构造函数调用,我想这会减慢并超载我的服务器。

也许我的例子wasnt很清楚,所以我把我的XDebug探查结果的打印:

Print http://img820.imageshack.us/img820/2166/possiblensting.jpg

是单身我需要什么?我试过用singleton这样一个简单的例子,但我有相同的结果(每个类超过1个构造)。
也许我需要扩展这些类并使用父类的构造函数?但是,20个不同的阶层怎么可能有时是独立的,有时是相互依存的?
或者我正在使用它正确的方式(我不这么认为)

+4

一个单例只不过是一个[hackish]方法来使用一个稳定的标识符来引用一个特定的实例。也许“依赖注入”这个词是否值得探索? – 2012-09-03 19:21:14

+0

25K LOC,只有20班,每班1250 LOC。即使其中一半是NCLOC,这也意味着你的课程太大了,你很可能没有遵循SRP。 – Gordon

回答

3

我不会这样做。我会这样做的方式是使用依赖注入。我已将类中的实例设置为protected(或将它们设置为private)。没有必要公开它们。如果你认为你需要这样做,那么你肯定违反了一些规则,你需要重新考虑你的设计。

我改变的另一件事是你做了$b = new B()。有两个问题:

  1. 我想你的意思做$this->b = new B()
  2. 您的B类紧密耦合到其他类。

这使得它不可能做任何单元测试,因为您不能用模拟类替换B类。所以不是测试单元(类),而是测试多个类。

我做的另一件事是键入提示构造参数。当你有类的接口时,这将会更加有用。这也使得测试类更加容易。另见this related answer

一些您可能感兴趣的视频:Dependency InjectionUnit testingInheritance, Polymorphism, & Testing。你可能还想看一下SOLID programming。您的代码似乎也违反了LoD,这意味着您尝试通过其他对象访问内容。

像这样的东西是什么,我会做:

class A 
{ 
    protected $b; 
    protected $c; 

    public function __construct(B $b, C $c) 
    { 
     $this->b = $b; 
     $this->c = $c; 
    } 

    public function sampleA() 
    { 
     $this->c->sampleC(); 
    } 
} 

class B 
{  
    protected $c; 

    public function __construct(C $c) 
    { 
     $this->c = $c; 
    } 

    public function sampleB($id) 
    { 
     return $this->c->sampleC($id); 
    } 
} 

class C 
{  
    public function sampleC() { } 
} 

$b = new B(); 
$c = new C($b); 
$a = new A($b, $c); 

$whatIWant = $a->sampleA(); 

如果你想写正确的OOP代码,你不应该永远(恕我直言)利用signleton反模式。基本上它只是global的另一个名称(具有相同的特征)。

也许我需要扩展这些类并使用父类的构造函数?但是,20个不同的阶层怎么可能有时是独立的,有时是相互依存的?

您应该只在子类可以替代父类时扩展类。这在SOLID中称为Liskov substitution principle。换句话说,你必须能够说class child是一个class parent

2

你需要的是控制反转模式与依赖注入。

使用这些模式,您可以保持您的类失去耦合,并强制每个类都使用正确的类和参数构造。

大多数优秀的PHP框架都有IoC和DI实现。看看来自Symphony的tutorial