两个模型:一个Owner
和一个Dog
:
owner.rb
class Owner < ActiveRecord::Base
has_one :dog
end
dog.rb
class Dog < ActiveRecord::Base
belongs_to :owner
end
这是架构:
schema.rb
ActiveRecord::Schema.define(version: 123) do
create_table "dogs", force: true do |t|
t.string "name"
t.integer "energy"
t.integer "owner_id"
t.datetime "created_at"
t.datetime "updated_at"
end
add_index "dogs", ["owner_id"], name: "index_dogs_on_owner_id"
create_table "owners", force: true do |t|
t.string "name"
t.string "energy"
t.datetime "created_at"
t.datetime "updated_at"
end
end
很简单的设置。
我想owner
带他dog
去散步。步行结束时,主人的能量会下降 5,狗的能量会下降 20。
很明显,这个walk_the_dog
动作/方法,无论它在哪里存在,都会影响两个对象:一个owner
对象和一个dog
对象(当然,这个狗对象恰好与这个所有者相关联)。
我不知道把这段代码放在哪里。我知道我可以简单地在 中创建一个动作owners_controller.rb
,但这似乎是个坏主意。它看起来像这样:
owners_controller.rb
class OwnersController < ApplicationController
def walk_the_dog
@owner = Owner.find(params[:id])
@owner.energy -= 5
@owner.dog.energy -= 20 # this line in particular seems like bad OO design
@owner.save
@owner.dog.save
end
...
end
据我了解,对象应该只改变自己的状态,而不应该改变其他对象的状态。所以这似乎是个坏主意,因为在所有者控制器中,我们不仅要更改owner
对象的状态,还要更改关联dog
对象的状态。
我已阅读有关服务的信息。对于服务来说,这似乎walk_the_dog
是一个很好的案例,因为据我了解,服务允许对象之间的交互和多个对象的状态更改。我只是不知道该怎么做/实施它。
是否应该有一个名为的服务对象walk_the_dog
?它们是否应该只是服务目录中的一个文件,其中包含一堆服务方法——其中一个被调用walk_the_dog
并owners_controller.rb
在它的控制器中简单地利用这个方法?我不知道下一步是什么。
注意:我可以看到有人说“谁在乎这是否会破坏 OO 设计。只要去做,如果它有效,它就有效。” 不幸的是,这不是一个选择。我现在正在开发的应用程序遵循了这种心态。应用程序变得非常大,现在维护它非常困难。我想在应用程序的重大重新设计中解决这种情况。