最佳原则原则

时间:2011-11-24 10:14:02

标签: ruby oop

我似乎遇到了很多设计问题而且我从来不知道是什么 是 真的很合适。一方面,我经常听到我应该限制耦合和 坚持单一责任,但当我这样做时,我常常觉得很难 至 在需要时将信息提供给程序的一部分。对于 例如,

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

后者的耦合较少,所以根据原则我应该使用它。 但如果我后来发现宋中的某些东西需要了解更多关于 歌手,我的方式很糟糕。 e.g。

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

如果我使用了后来的Song类而不是 前任的。 但后来我怀疑有人会提醒我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。

4 个答案:

答案 0 :(得分:6)

耦合应该与另一个概念cohesion相抗衡。你想在两者之间取得平衡,而不是仅仅将其中一个推向极致。在您的示例中,singer_name似乎属于Singer,因此为了保持凝聚力,您应该将Singer对象传递给Song,而不是name

更一般地说,您需要记住,这些原则仅仅是指导方针。您始终必须运用常识和对问题域的独特理解。很少有明显的案例 - 甚至可能随着您的应用程序的增长或您更好地理解域名而改变。

答案 1 :(得分:2)

面向对象的程序应该模拟现实生活中的对象。在生活中,一首歌属于歌手,而不是歌手的名字,在你的节目中,你应该以这种方式对其进行建模。

正如@troelskn已经提到的那样,耦合的概念,但也有凝聚力的概念......原则是伟大的,但常识应该优先。

答案 2 :(得分:2)

Ruby的核心是程序员快乐。您应该考虑代码的可读性以及它对您(或您的同事)大脑的压力,特别是当您需要经过长时间的停顿后再次理解它时。

我认为SRP应该被视为推荐而不是规则。如果SongPlayer让人更难理解正在发生的事情,只需放弃SRP并坚持使用Song#play,如果它更容易,请务必使用它。

请记住,你总是可以重构。我从Song#play开始,如果Song开始变得臃肿与播放相关的代码,那么我会将这些内容重构为SongPlayer类。

答案 3 :(得分: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

这是我的两分钱。