2012-09-03 157 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