SRP是骗局
根據羅伯特·馬丁 ( Robert Martin)的 《 清潔法 》( Clean Code) ,“ 單一責任原則 ”意味著“一個階級應該只有一個改變的理由”。 讓我們嘗試解密這個模糊的語句,看看它如何幫助我們設計更好的面向對象軟件。 如果是這樣。
約翰·麥克蒂爾南(John McTiernan)的《托馬斯王冠》(Thomas Crown Affair)(1999)
我在有關SOLID的帖子中曾經提到SRP,說它并不能真正幫助程序員理解1974年由Larry Constantine提出的古老的“高凝聚力”概念。現在讓我們通過示例進行觀察并分析如何考慮到SRP以及是否會變得更加面向對象 ,改進類。
讓我們試著類AwsOcket從jcabi-S3 (我已經簡化了代碼):
class AwsOcket {boolean exists() { /* ... */ }void read(final OutputStream output) { /* ... */ }void write(final InputStream input) { /* ... */ } }如果我錯了,請糾正我,但是根據SRP,此類負責太多事情:1)檢查AWS S3中對象的存在,2)讀取其內容,以及3)修改其內容。 對? 這不是一個好的設計,必須對其進行更改。
為了更改它并使它僅負責一件事,我們必須引入一個getter,它將返回一個AWS客戶端,然后創建三個新類: ExistenceChecker , ContentReader和ContentWriter 。 他們將檢查,讀取和寫入。 現在,為了閱讀內容并將其打印到控制臺,我目前正在這樣做:
if (ocket.exists()) {ocket.read(System.out); }明天,如果我重構班級,我將這樣做:
if (new ExistenceChecker(ocket.aws()).exists()) {new ContentReader(ocket.aws()).read(System.out); }除了一個事實,即這些跳棋,讀者和作家都算不上類,但程序純持有人,這的用法ocket變成了一場噩夢。 當我們將其傳遞到某個地方時,我們真的無法再知道會發生什么。 例如,我們不能保證來自其內容的內容會即時解密或解碼。 我們根本無法裝飾它。 它不再是一個對象,而是一個AWS客戶端的持有者,其他地方的某些類也使用它。
是的,現在它只負責一件事:封裝對AWS客戶端的引用。 就SRP而言,這是一個完美的課程。 但這不再是一個對象。
如果您完全使用SRP原理,則對任何類都將發生相同的情況:它將成為數據或其他對象的持有者,并且在它們之上具有一組setter和getter。 也許除了這些之外還有一種額外的方法。
我的觀點是SRP是錯誤的想法。
使班級小并且具有凝聚力是一個好主意,但是讓他們對“一件事情負責”是對“高度凝聚力”概念的誤導性簡化。 它只會使它們變成其他東西的笨拙的載體,而不是成為較小實體的封裝和裝飾者,以構造較大的實體。
在為這個假的SRP想法而斗爭時,我們失去了一個更重要的原則,那就是關于真正的面向對象的編程和思考:封裝。 與負責保護封裝的實體的緊密程度相比,對象負責多少事務并不重要。 具有一百種方法的怪物對象比具有五對吸氣劑和吸氣劑的DTO的問題要少得多! 這是因為DTO在整個代碼中散布了問題,而我們甚至都找不到它,而Monster對象始終就在我們面前,我們可以將其重構為更小的片段。
如果有的話,封裝是第一位的,尺寸是第二位的。
翻譯自: https://www.javacodegeeks.com/2017/12/srp-is-a-hoax.html
總結
- 上一篇: nuke设置中文(nuke使用手册)
- 下一篇: apache camel_使用Apach