2011-11-24 50 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 

这是我的两美分。