我有一个方法(land_connected_rover(coordinates))接受一个参数(包含两个数字和一个字母的字符串,空格分隔)end基于此执行提示,我的问题是我很难从这个方法中提取我的赋值,我尝试了私有方法,但一旦这样做,就没有了我注入的类中的任何一个都可以访问这些变量。我想有一个优雅的,基于srp的解决方案,而不是目前混乱的一个…呃,对不起,伤到你的眼睛了!
“x”、“y”和“position”变量名对于其他类很重要,因为它们依赖于这些提示…
我想提取将x,y和position变量名赋给字符串右侧的步骤。
class Controller
attr_reader :current_rover, :current_surface
def initialize
@current_surface = nil
@current_rover ||= []
end
def connect_to_surface(destination)
@current_surface = destination
end
def connect_to_rover(rover)
@current_rover = rover
end
def land_connected_rover(coordinates)
coordinates = coordinates.delete(' ')
x = coordinates[0].to_i
y = coordinates[1].to_i
position = coordinates[2].to_sym
self.current_rover.x_coordinates = x
self.current_rover.y_coordinates = y
self.current_rover.position = position
add_to_grid(x,y)
end
def navigate(command)
self.current_rover.read_input(command)
end
private
def add_to_grid(x,y)
@current_surface.record_on_map(x,y)
end
def turn_on_rover
@current_rover.online = true
end
end
我真的很感激你的帮助!很抱歉,如果我问错了问题,我是个新手。
最佳答案
关于opportunity cost的注释。有可能过度考虑。担心这种方法可能不值得你花时间。这是一个简单语句的八行方法,很容易理解,而且很有效。可能已经测试过了,但如果没有,那就最好花点时间。
例如,将@current_rover
初始化为列表,但它用作用户对象。我怀疑如果用户不设置@current_rover
,很多事情都会以混乱的方式发生。那将是一件值得花时间的事情。您可以使用尝试使用新初始化的对象并确保它们产生有意义的异常的测试,或者您可以回避所有的复杂性,并决定必须使用rover对其进行初始化。
让我们把重构当作一个练习。
首先,让我们试着描述land_connected_rover
所做的所有事情,通过注释每个块的事情来解释它们所做的事情。
def land_connected_rover(coordinates)
# Parse coordinates.
coordinates = coordinates.delete(' ')
x = coordinates[0].to_i
y = coordinates[1].to_i
position = coordinates[2].to_sym
# Set rover coordinates.
self.current_rover.x_coordinates = x
self.current_rover.y_coordinates = y
self.current_rover.position = position
# Add something to the grid for some reason.
add_to_grid(x,y)
end
像这样的评论在提取方法的关键点上。我们需要一些东西来解析坐标。设置坐标的东西。以及向网格添加坐标的东西。我们已经有最后一个了,所以把另外两个提取出来。
def parse_coordinates(input)
input = input.delete(' ')
return {
x: coordinates[0].to_i,
y: coordinates[1].to_i,
position: coordinates[2].to_sym
};
end
def set_rover_coordinates(coordinates)
@current_rover.x_coordinates = coordinates[:x]
@current_rover.y_coordinates = coordinates[:y]
@current_rover.position = coordinates[:position]
end
现在这些可以被记录、重用和单元测试。测试可能会显示在坐标不解析或未设置
@current_rover
时需要添加错误处理。我使用
@current_rover
来保持与其余代码的一致性,这些代码使用实例变量进行内部访问,而不是访问器。无论哪种方式都有争论,选一个吧。然后把它们放回去。
def land_connected_rover(input)
set_rover_coordinates( parse_coordinates(input) )
add_to_grid(x,y)
end
从那里我们可以做更多的观察。为什么控制器要编写方便的方法来设置rover的属性?
set_rover_coordinates
应该搬到罗孚去。 def land_connected_rover(input)
@current_rover.set_coordinates( parse_coordinates(input) )
add_to_grid(x,y)
end
谁应该解析坐标?我可以看出罗孚和管制员都需要这个的充分理由。这表明你需要一个坐标类。
# In Controller
def land_connected_rover(input)
@current_rover.set_coordinates( Coordinate.from_a(input) )
add_to_grid(x,y)
end
# In Rover
def set_coordinates(coordinates)
@x_coordinates = coordinates.x
@y_coordinates = coordinates.y
@position = coordinates.position
end
现在,我们观察到,与其说漫游者的坐标是一堆属性,不如说它应该有一个单一的坐标属性,它接受一个坐标对象。
# In Rover
attr :coordinates
# In Controller
def land_connected_rover(input)
@current_rover.coordinates( Coordinate.from_a(input) )
add_to_grid(x,y)
end
现在我们有了坐标对象,控制器可以传递一个坐标对象,而不必担心其输入的规格化。
def land_connected_rover(coordinates)
@current_rover.coordinates( coordinates )
add_to_grid(x,y)
end
让调用者处理规范化。
controller.land_connected_rover( Coordinate.from_a([10,20,30] ) )
既然有了坐标对象,调用者就可以使用它们了,而且对转换的大部分需求可能会消失。
从这里开始,我的下一个关注点是月球车和地表之间的坐标复制。月球车有自己的坐标,表面似乎独立地跟踪月球车的坐标。我想两者必须保持同步?如果是这样的话,这就增加了复杂性,并有可能出现错误。或者表面只是跟踪探测器最初降落的地方?这是一个值得考虑的问题。
请注意,在我开始重构之前,大多数情况都不明显。我最初在第一次重构
land_connected_rover
时就停止了,但后来又考虑了一下,提出了coordinate类,然后它从那里级联。我认为最终的结果要好得多,远远超出了我当初的预期。所以…是啊,有时候真的很担心八行法。:)
关于ruby - Ruby-从另一个方法中提取较小的方法(将字符串转换为两个数字和一个符号),我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/41840132/