将三种类似的方法转换为一种方法

时间:2012-02-15 22:24:46

标签: ruby refactoring

我想将这三种方法合而为一,但此时无法将我的大脑包裹起来。由于1/3需要稍微不同的呼叫这一事实而复杂化。他们都很相似,我知道有更好的方法,但现在超出我的技能水平。传入一个额外的变量(获取,检查或处理)我可以把它变成一个,如何做到这一点让我望而却步。

如果你要将这些重构为一种方法,你会怎么做?

def fetch(subjects = current_subjects, queues = QUEUES)
  subjects.each do |s|
    queues.each { |x| fetch_results(x, s) } unless queue.nil?
  end
end

def check(subjects = current_subjects, queues = QUEUES)
  subjects.each do |s|
    queues.each { |x| check_results(s["#{x}_recent"]) } unless queue.nil?
  end
end

def process(subjects = current_subjects, queues = QUEUES)
  subjects.each do |s|
    queues.each { |x| process_results(s["#{x}_recent"]) } unless queue.nil?
  end
end
编辑:一个解决方案接近我之前的想法,但我没有明确表示我想将what作为一个小型数组传递,这可能是可扩展的,可用于表示是否获取,检查或处理或其中任何组合。所以,基本上,我试图用一种方法循环三件事:

  • 行动:I.E.,取,检查或处理。
  • 任意数量的科目。
  • 任意数量的队列,目前是一个常数。

此外,其他解决方案:

http://refactormycode.com/codes/2002-three-into-one

4 个答案:

答案 0 :(得分:2)

@Lucapette提出了一种自上而下的解决方案(我认为它在大多数情况下非常有效)。但是,@ Tony正确地指出方法可能会发展,因此可能过于僵化。替代解决方案是自下而上的方法:

def iter_queues(subjects, queues)
  subjects.each do |subject|
    (queues || []).each { |queue| yield(queue, subject) }
  end
end

def fetch(subjects = current_subjects, queues = QUEUES)
  iter_queues(subjects, queues) { |q, s| fetch_results(q, s) }
end

同样适用于其他方法。顺便说一句,那个双each也可以写成:

subjects.product(queues).each { ... }

答案 1 :(得分:1)

def execute(what, subjects = current_subjects, queue = QUEUES)
  subjects.each do |s|
    queue.each { |x| send("#{what}_results", s["#{x}_recent"] ) } unless queue.nil?
  end
end

是一种方法。当然,命名取决于你。

答案 2 :(得分:1)

我可能会这样做:

def with(subjects,queues)
    subjects.each do |subject|      
        queues.each do |queue|
            yield subject, queue
        end
    end
end

with(my_subjects, my_queues){|s, q| fetch_results(q, s)}

答案 3 :(得分:0)

为什么要将它们重构为单个函数?它们现在相似,但是如果它们后来发展并变得不同呢?每个函数都有自己的用途,应该作为单独的函数保留。