2012-02-15 3 views
2

Я хочу превратить эти три метода в один, но в настоящий момент я не могу обмотать мозг вокруг него. Сложно из-за того, что 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 

EDIT: Одно решение близко к тому, что я думал раньше, но я не сделал это ясно, что я хочу передать в what как небольшом массиве, которые могут быть расширяемой и может использоваться для указания будь то выборка, проверка или обработка или любая их комбинация. Поэтому, по сути, я пытаюсь выполнить три метода одним способом:

  • действие: I.E., выборка, проверка или процесс.
  • любое количество предметов.
  • любое количество очередей, которое является постоянным на данный момент.

Кроме того, другие решения здесь:

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

+0

сторона примечание: очередь является перечислимы, так называют его соответствующим образом: _queues_. – tokland

ответ

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 

Ditto для других методов. Кстати, что двойное each также может быть написано:

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

Ну, большие мысли думают одинаково :), но я думаю, что мне больше нравится каждый лучше – pguardiario

+0

я тоже, если честно :-p – tokland

0

Почему вы хотите, чтобы реорганизовать их в одну функцию? Теперь они похожи, но что, если они развиваются позже и станут другими? Каждая функция имеет свою цель и должна быть оставлена ​​как отдельные функции.

+0

Отличный момент, но нет смысла повторять излишне. Это может пойти в любом случае. – blueblank

+1

DRY их сейчас, чтобы сделать код проще. Если один или несколько процессов будут изменены позже, тогда извлеките это. Нет смысла держать плохо организованный код только в случае «что, если». – Pavling

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 

это способ сделать это. Конечно, именование зависит от вас.

+0

Похоже на то, о чем я думал раньше, но не понял. Во-первых, «выборка» требует немного другого вызова, поэтому мне нужно либо изменить это, либо обойти его, я предполагаю, спасибо. – blueblank

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)} 
+0

ну, моя идея ниже ;-) обратите внимание, что 'with' также может быть написано' subjects.product (очереди) .each (& блок) ' – tokland

Смежные вопросы