Ruby 包含对象最佳实践

Ruby included objects best practice

首先大家好,

我想了解 ruby 中的对象包含最佳实践。 让我们描述一下上下文:

结果是我最终得到了嵌套对象,这些对象可能非常非常大并且会自我重复。

是否有任何其他解决方案/模式可以以更简洁的方式执行相同的操作? 有没有这类实施的好例子?

谢谢!

这是一个基本的例子,但想象一下这个对象更大,有很多属性。

require 'awesome_print'

class A
  attr_accessor :title

  def initialize(title)
    @title = title
  end
end

class B
  attr_accessor :a, :level

  def initialize(a, level)
    @a = a
    @level = level

    # Here, I need to access to a.title
  end
end

class C
  attr_accessor :b, :name

  def initialize(b, name)
    @b = b
    @name = name

    # Here, I need to access to b.level
  end
end

a = A.new 'test'

b1 = B.new a, 1
b2 = B.new a, 2
b3 = B.new a, 3

c1 = C.new b1, 'one one'
c2 = C.new b1, 'one two'
c3 = C.new b1, 'one three'

ap c1
ap c2
ap c3

c4 = C.new b2, 'two one'
c5 = C.new b2, 'two two'
c6 = C.new b2, 'two three'

# ... etc

我觉得结果很脏(将大对象包含在其他大对象中)

#<C:0x000001011e9680 @b=#<B:0x000001011e9720 @a=#<A:0x000001011e9748 @title="test">, @level=1>, @name="one one">
#<C:0x000001011e9630 @b=#<B:0x000001011e9720 @a=#<A:0x000001011e9748 @title="test">, @level=1>, @name="one two">
#<C:0x000001011e95b8 @b=#<B:0x000001011e9720 @a=#<A:0x000001011e9748 @title="test">, @level=1>, @name="one three">

关于面向对象的事情是封装数据、方法和其他对象以创建抽象。更多的抽象可以让你更容易推理你的项目,但它也增加了复杂性,让你的项目变得更加复杂。我特别发现很难平衡这两者。只有多年的实践才能做到这一点。

如果三级封装看起来太多了,试试看dependencies as a code smell

是否所有对象都代表有意义、有用的抽象?例如:

  • B 似乎在使用 A#title 做某事
  • B 公开 A 供 C 使用
  • B 公开 level 供 C 使用

这里B好像只是把A带上了level属性,这样C就可以使用了,这个抽象有什么用吗?

如果C收到一个A对象,一个level和一个name,我们可以简化问题吗?

class A
  attr_reader :title # Do you really need outside code to change this?

  def initialize(title)
    @title = title
  end
end

class C
  attr_reader :level, :name

  def initialize(a, level, name)
    @a = a
    @level = level
    @name = name

    # Here, you access a.title to do whatever you did in B
  end

  def title
    @a.title
  end
end