OO難題在Ruby中有了新解 (原文最終修訂於 2006-08-21 凌晨02:27:38)

單一職責原則(SRP)認爲,一個類應該有且只有一個改變的原由。換個說法,一個類中的方法應該出於同樣的一種原由而改變,它們不應被不同原由所驅使,而導致朝着不同的方向改變。

舉個例子來說,考慮一下以下的Java類:

class Employee
{
  public Money calculatePay() {...}
  public void save() {...}
  public String reportHours() {...}
}

這個類由於擁有三種改變的原由,所以違反了SRP。第一種,是跟支付薪水方式有關的商業規則;第二種,是數據庫的結構;第三種,是報表的時間格式的字符串。我們不希望這樣一個單一的類會被這三種完全不同原由所影響,不希望因爲會計認爲需要每天改變報表的時間格式,或是DBA每天都要改變數據庫結構,也可能是管理人員每天要改變支付薪水的方式,而去改變Employee類。相反,我們希望把這些方法分離到不同類中,這樣它們就既能彼此互不干擾,又可隨意改變。

當然這好像又與OO的概念相違背,因爲一個好的對象應該包含所有操縱它的方法。分解的做法的確有這種趨勢,我們因爲不希望商業規則與報表格式混雜起來,所以就需要將這些方法放入到不同的類中。

然而,在Ruby中,情況會有些不同。仔細想想下面三個文件:

employeeBusinessRules.rb



employeeDatabaseSave.rb



employeeHourlyReport.rb


由於在Ruby中,類是在運行時被創建的(也就是說,上面的代碼也可視作是一段程序執行片斷),類可能是在程序執行的任意時間被展開,更多的方法和成員也可能是在此時被賦到類上。在主程序中我們也許會看到一些諸如:

require 'employeeBusinessRules.rb'
require 'employeeDatabaseSave.rb'
require 'employeeHourlyReport.rb'

因此,類會在餘下的程序開始執行前被構造完成。可是沒有一個源文件包含了所有這三個不同的方法。實際上,這三個源文件對彼此一無所知,而這就意味着,這三個文件之間並沒有耦合。

毫無疑問,我們必須要關注這些成員。爲了能訪問這些成員(分散在多個源文件中),我們搞不好會使得這些源文件拙劣的耦合起來。可是,假如你有那麼一點點地關注並抽象的話,就能使得這些源文件非常漂亮的解耦,進一步的,還可以把這些方法保留在同一個類中(因此也在同一對象中)!

所以,在Ruby中,不用違反SRP原則,就可以把不同的方法放置在同一個類中,並且屬於同一個類。你只需簡單的將這些有着不同原由的方法放置在不同的源文件中即可。真是魚與熊掌得其兼啊!

 

 (原文鏈接網址:http://www.butunclebob.com/ArticleS.UncleBob.SrpInRuby; Robert C. Martin的英文blog網址: http://www.butunclebob.com/ArticleS.UncleBob 

譯者注:Robert C. MartinObject Mentor公司總裁,面向對象設計、模式、UML、敏捷方法學和極限編程領域內的資深顧問。他不僅是Jolt獲獎圖書《敏捷軟件開發:原則、模式與實踐》(中文版)(《敏捷軟件開發》(英文影印版))的作者,還是暢銷書Designing Object-Oriented C++ Applications Using the Booch Method的作者。MartinPattern Languages of Program Design 3More C++ Gems的主編,並與James Newkirk合著了XP in Practice。他是國際程序員大會上著名的發言人,並在C++ Report雜誌擔任過4年的編輯。

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章