2015-07-11 86 views
9

我正在看PSR-7接口並考慮如何實現它們。我也一直在閱讀this blog post。顯然,實現PSR-7接口的對象必須是不可變的。如果我實現從MessageInterfacewithProtocolVersion方法Psr7 Http消息,爲什麼不可變?

所以那麼它會是這個樣子:

public function withProtocolVersion($version) 
{ 
    if ($this->protocol === $version) 
    { 
     return $this; 
    } 

    $new = clone $this; 
    $new->protocol = $version; 
    return $new; 
} 

我真正的問題是,爲什麼不變?爲什麼不簡單地做一個return $this;

這不是我關心它分配的內存量,我真的沒有看到任何好處,保持它不可變。

像博客文章說,當你這樣做:

$request = $request 
    ->withMethod('POST') 
    ->withUrl(new Url('http://example.org/') 
    ->withHeader('Content-Type', 'text/plain'); 

然後四個副本的創建,但最終的結果在$request是一樣的,當我會簡單地使用return $this,對不對?

爲什麼決定保持它不變。那麼,爲什麼我必須做一個clone $this?它有什麼好處?

我真的沒有想到這個想法。

+3

博客文章該部分的最後一段說:_這個決定是爲了健壯的緣故。這顯然會「刪除整個類的錯誤」。@ – Barmar

+1

@Barmar我真的不明白他的意思。我真的不知道它會如何去除整個類的bug。那麼,如何刪除一類錯誤?你仍然可以*「設置」*所有的屬性。它所做的只是返回對象的新副本,而不是它自己的對象。 – Vivendi

回答

6

我建議您閱讀this document,其中詳細解釋了所有設計選項。

尤其是您應該閱讀Why value objects?New instances vs returning $this部分。

其要點如下:

在本質上,建模HTTP消息作爲值對象確保消息狀態的完整性,並防止需要進行雙向的依賴關係,這通常可以去OUT-或導致調試或性能問題。

這些操作可以與值對象以及來實現,具有許多好處:

  • 原始請求狀態可以通過任何消費者被存儲以供檢索。
  • 可以使用默認標題和/或消息主體創建默認響應狀態。

如果您想更深入,我建議你在無花果郵件列表的歷史看(你可以找到它here),那裏有關於對象的不變性很多討論

+0

謝謝,目前正在通過郵件列表工作。但是這已經讓我理解了不可變請求對象背後的想法。 – Vivendi

+0

我沒有看到提供的鏈接中的原因。這個直接問題不是直接回答,而是有一些聯繫和模糊的意見。關於其他開發人員可能存在的誤解的意見。這向我證明,這個嚴肅的設計決定沒有很好的基礎,可能僅僅基於如何使用php和現在/過去的行爲。 –