2017-05-26 36 views
2

我現在有一類Message_Repository具有類似的方法:OOP原則 - 如何構建類

getLocationDetailsByID($messageId), 
getCustomerDetailsById($messageId), 
getMessages(), 
updateMessageForEmail(array $data), //this takes an array which includes the message ID 
getLinkIndicatorById($messageId), 
setIndicator($data) //this takes an array which includes the message ID 

這些方法,其中在大多數情況下,我選擇各種數據的所有數據庫交互,並在某些情況下,我正在進行更新。

我發現,因爲我充實了這一點,我的類的名字不再代表發生了什麼事在班上,至少不完全。

是否有最好的做法是說一個Location_Repository類和一個Customer_Repository類,該類將容納獲取與主題相關的數據的方法?

仍試圖理解單一責任。理論上它似乎很簡單,但實際上我發現它更具挑戰性,特別是當我的課程不斷髮展和變化時。絕對需要重構,但要確保我正確地思考這個問題。

編輯 我可能會添加與我的班級的名稱混淆。它不是嚴格意義上的設計模式的「存儲庫」,而僅僅是我用來與數據庫進行交互的類的命名約定。可能需要重命名它。

+0

你能簡單介紹一下這些功能的用途嗎?你傳遞給這些功能的ID是什麼?它是一個消息ID,還是位置/客戶/ LinkIndicator ID? –

+0

@NiettheDarkAbsol消息ID是數據庫中各個表之間的主鍵,大多數方法都使用該消息ID來獲取所需的數據,所以它被傳遞到我提到的所有方法中。有一個或兩個其他方法(我的問題中沒有列出)不接收消息ID。 – hyphen

+0

我明白了。在這種情況下,你的構造函數應該使用這個ID,那麼你應該把'getLocationDetails'作爲對象的非靜態方法,它會返回這些細節。 –

回答

2

Single responsability是OOP的原子化概念,它會導致Encapsulation concept

這些概念是由SOLID Principle粘合在一起的,強大的原理,將節省您大量的時間和避免麻煩你的餘生:

單一職責原則:一類應該只有一個單 責任(即只有一個潛在的軟件 規格的變化應該能夠影響類的規範)

打開/關閉原則「的軟件實體......應該是開放的 擴展,但關閉modificati on「。

Liskov替換原則」程序中的對象應該是 可以用它們的子類型的實例替換而不改變該程序的正確性。「另請參見按合同設計。

界面偏析原理「許多客戶特定的接口是 多於一個的通用接口更好」。

依賴倒置原則一個應「取決於抽象, [不]結石。」

如果不理解您的所有業務規則並仔細閱讀您的代碼,則很難分析如何組織您的軟件,但我會給出一個答案:

MessageRepository不會擴展客戶或地點,但它們是compounded

Composition Example 在上圖中,從維基百科

在你構建從MessageRepository你會實例這些類使用,你想裏面MessageRepository組成托克的一個例子。完美的情況是避免在類中存在公共變量,並深深依賴方法來檢索和設置數據(我看着你已經以這種方式做了一些事情)。

MessageRepository方法:那麼,據我可以通過方法名稱理解

  • 公衆的getMessages();
  • public updateMessageForEmail(array $ data); //需要一個數組,其中包含消息ID
  • public getLinkIndicatorById($ messageId);
  • public setIndicator($ data); //這需要一個陣列,其包括消息ID

LocationRepository方法:

  • 公共getLocationDetailsByID($ MESSAGEID);

CustomerRepository方法:

  • 公共getCustomerDetailsById($ MESSAGEID);

重要的是要記住:您的業務規則方法應該是私有的。

建議可讀性:

  • 避免強調到類名;
  • 避免重複類名或總線。統治方法。 I.E. getLocationDetailsByID應該是getById(),永遠記住 - 你的方法將有實例,所以會被調用:$ this-> location-> getById()。這同樣適用於你描述的所有方法。

關於命名,這是一個偉大的問題。我建議你學習設計模式/軟件架構,我最喜歡的一個(opposing Uncle Bob perspective)是MVC(Model-View-Controller)架構:

MVC Schema

你的「庫」,這有業務規則的原則和數據庫抽象應該是一個模式,所以,如果你想使用該模式,創建MVC目錄結構並努力實現它!

+0

關於可讀性的要點。任何關於命名的想法?如果我有一個Location_Repository類,那應該是Location嗎?我是否需要在名稱中區分它作爲訪問數據庫的東西,還是不必要?命名事情很難。 – hyphen

+0

我會提出我的回答,堅持 – calexandre

+0

恕我直言,UncleBob的講座不太關於MVC,更多關於「Rails如何不做MVC」。 –

1

通常我會把它們分開,所以你將有一個每個模型類型的存儲庫。例如,所有返回「位置」模型的方法都應位於「位置」存儲庫中。與更新方法類似,它將傳遞一個'位置'模型來更新。

+0

他們不是「模型」 –

1

如果我們使用Doctrine庫去爲標準,則非常肯定的,你就必須爲每個數據類型的存儲庫。

Message_Repository::getLocationDetailsByID(); 

可能會變成:

Location_Repository::getLocationDetailsByMessageID(); 

單這裏的責任是通過有關他們自己的數據類型每個倉庫取數據遵守。在Doctrine中,EntityRepository :: createQueryBuilder()預加載了一個->select(/* own data type */)的構建器。

但每一個庫是不同的,你可以組數據類型爲「概念」和處理他們在同一個地方,同時還符合SRP,但隨着應用的增長,最大努力把它分開。

2

存儲庫只應管理實體或domain objects,屬於同一類的實例。在您的特定情況下,您應該至少分成三個單獨的存儲庫,分別用於Message實例,Location實例和Client實例。可能是任何「鏈接指標」的第三個存儲庫。

此外,庫類是not were your SQL code goes

對於SRP,代碼遵守的最佳描述是:「當類只有一個原因需要更改時」

如果你看一下福勒的文章,你會發現,這是倉庫實際上有它自己的多個依賴交互。並且SQL應該可能進入一個或多個data mappers

+0

這是關於庫類的好信息。我認爲對我來說,這僅僅是一個名字而不是一個具體的設計模式,因爲我還沒有經歷過OOP。這本質上是一個數據訪問類。任何模式或命名公約的建議呢? – hyphen

+1

版本庫不是真正的「數據訪問類」。我會說這是一種抽象,他們會在代碼中放置代碼,在選擇哪個數據映射器用於與持久性進行交互時開始需要邏輯。那是你創建一個存儲庫來隔離這部分邏輯的時候。 Lemmes看看我能不能挖出一個代碼的例子,在那裏很有用。 –

+1

@hyphenas舉個例子,[this method]中的大部分邏輯(https://github.com/glome/cbc/blob/overhaul/src/cashback/Model/Services/Recognition.php#L19)實際上應該被移動在一個存儲庫中(只是不要使用該代碼庫進行學習,這很糟糕),因爲它可以讓你將所有「擺弄」與「選擇哪個映射器」相提並論。 –