2011-11-24 48 views
5

我似乎遇到了很多設計問題,我從來不知道 是否是 真的很合適。一方面,我經常聽到我應該限制耦合,並且堅持單一責任,但是當我這樣做時,我經常發現難以在需要時將信息獲取到程序的一部分 至 。對於 例如,最佳原則原理

class Singer 
    def initialize(name) 
    @name = name 
    end 
    attr :name 
end 

這時應該樂曲是:

class Song 
    def new(singer) 
    @singer = singer 
    end 
end 

class Song 
    def new(singer_name) 
    @singer_name = singer_name 
    end 
end 

後者具有較低的偶合,所以根據原則我應該使用它。 但是如果我後來在Song中發現某些東西需要了解更多關於 歌手的內容,我的感覺就不好。例如

class Song 
    ... 
    def play 
    puts "Belting it out by #{@singer.name}, winner of 
    #{@singer.grammy_count} grammies!" 
    end 
end 

我會用一個固定的,如果我用了以後的宋級,而不是 前者。 但我懷疑有人會提醒我的SRP,單一職責 原則,並建議改爲:

class SongPlayer 
    def initialize(singer, song) 
     @singer, @song = singer, song 
    end 
    def play 
     puts "Belting it out by #{@singer.name}, winner of 
     #{@singer.grammy_count} grammies!" 
    end 
    end 

而且是啊,我想這是有道理的,因爲其他歌手可以做掩護的 另外一個人的歌曲,對吧?但是,那真的會和 歌曲一模一樣嗎?在我的大多數情況下,它從來沒有相同的「歌曲」,所以我從來沒有 那 種情況。那麼SRP是否值得爲 代碼增加額外的類呢?

我有時會認爲許多OOP原則,SOLID或其他,出現了Java的侷限性,並且不適用於Ruby。

回答

6

耦合應該與另一個概念cohesion抵觸。你想在兩者之間取得平衡,而不是僅僅把它們中的一個帶到極端。在您的示例中,singer_name似乎屬於Singer,因此爲了保持內聚性,應該將Singer對象傳遞給Song,而不是name

更一般地說,您需要記住,這些原則僅僅是指導方針。你總是必須運用常識和你對問題領域的獨特理解。很少有清晰的案例 - 它可能會隨着您的應用程序的增長或者您更好地理解域而改變。

2

面向對象的程序應該模擬真實的對象。在生活中,一首歌曲屬於歌手,而不是歌手的名字,在你的節目中,你應該用這種方式來塑造歌曲。

由於@troelskn已經提到了耦合的概念,但也有凝聚力的概念......原則很好,但常識應該優先。

2

紅寶石有程序員幸福在其核心。你應該考慮你的代碼的可讀性以及你的(或者你的同事的)大腦的緊張程度,特別是當你需要在長時間的停頓後再次理解它時。

我會說SRP應作爲建議,而不是一個規則。如果SongPlayer使得更難理解正在發生的事情,只要放棄SRP並堅持使用Song#play,如果它讓事情變得更加容易,那就一起去吧。

請記住,您可以隨時重構。我會從Song#play開始,如果Song開始因與遊戲相關的代碼而變得臃腫,那麼我會將這些東西重構爲SongPlayer類。

0

你應該把歌手傳給宋,這是真正的OOP方式。因爲,你們正在分離擔憂,這很好。

至於你的例子,'你應該告訴,不要問'。因此,宋總是告訴歌手廣告自己是這樣的:

class Song 
    ... 
    def play 
    # So that, singer will use the template and add the details 
    puts @singer.to_s("Belting it out by #{name}, winner of #{grammy_count} grammies!") 
    end 
end 

這是我的兩美分。