2010-11-21 1 views
1

Я недавно работал над упрощением метода Ruby, который я не писал. Это часть старого проекта, который написал коллега. В общем, мы сделали довольно хорошую работу, не накапливая задолженность по коду, но есть несколько методов, которые нуждаются в некоторой любви.Как упростить этот метод в Ruby-ish?

Метод, который я упрощал, первоначально представлял собой массу вложенных блоков if-else. Я определил, что метод делает и упрощает метод, поэтому больше нет вложенных ifs.

Теперь я хочу упростить его еще больше, и, если возможно, я хочу исключить все, кроме одного заявления return. Метод больше, чем это, но это общее понятие о том, что она выглядит как прямо сейчас:

def return_bool 
    return false unless condition1 && condition2 
    @var = SomeClass.getter(foo) 
    return true unless var.someProperty != 0 
    @stuff = @var.getsomething id 
    return false unless @stuff && somethingElse 
    data = JSON.parse(@stuff) 
    @stuff.each do |stuff| 
    return false if data[stuff['something']] != stuff['anotherSomething'] 
    end 
    return true 
end 

Я думал об использовании raise и обработки исключений для снижения return заявления, но если, например, condition1 является ложным , это не исключительная ситуация, я ожидаю это в определенное время.

Как уменьшить количество операторов return, предпочтительно до одного? Если возможно, я бы предпочел неявно вернуться, если смогу.

+0

'raise' никогда не лучше, чем' return' – Nakilon

+0

что на самом деле делает что-то полезное? –

+0

@Greg Да. Как я уже упоминал, это более крупный метод, но я просто хотел опубликовать небольшой пример кода, чтобы вы поняли его суть. – Alex

ответ

0

Образец кода не из-за того, что работает, потому что Ruby отказался выполнить это определение метода.

Вот как я его разгадал, но без значений образца для любой из локальных переменных или определения SomeClass нет возможности проверить его.

def return_bool 
    if (condition1 && condition2) 
    @var = SomeClass.getter(foo) 
    if (var.someProperty == 0) 
     @stuff = @var.getsomething id 
     if (! (@stuff && somethingElse)) 
     data = JSON.parse(@stuff) 
     @stuff.each do |stuff| 
      return false if data[stuff['something']] != stuff['anotherSomething'] 
     end 
     end 
    end 
    end 
    return true 
end 
+0

Это дает мне некоторые идеи для работы. Благодаря! +1 и принято. – Alex

+0

# 1, что я видел в исходном коде, - это ужасная зависимость от 'if'. Это эквивалентно 'if (! Some_boolean_value)', но заставляет мозг работать сверхурочно, расшифровывая, что происходит. Изменяя утверждения, используя 'if', чтобы' if (! ...) 'выглядел как вложенные операторы' if' были бы близки к одной и той же логике. –

+0

@theTinMan Я знаю, что я довольно поздно, но исходный код возвращает 'false', когда' condition1 && condition2' является 'false', а ваш код возвращает' true'. – michau

1

.all? Используйте вместо последнего .each цикла:

def return_bool 
    return false unless condition1 && condition2 
    @var = SomeClass.getter foo 
    return true unless var.someProperty != 0 
    @stuff = @var.getsomething id 
    return false unless somethingElse && @stuff 
    data = JSON.parse @stuff 
    @stuff.all? do |stuff| 
    data[stuff['something']] == stuff['anotherSomething'] 
    end 
end 

Кстати, возвращается против сослагательного наклонения подобен holywar. Я предпочитаю возврат.
Кроме того, если вам не нравятся возвраты, что с этим делать?

def return_bool 
    condition1 && condition2 && (
    @var = SomeClass.getter foo 
    var.someProperty.zero? || (
     (@stuff = @var.getsomething id) && somethingElse && (
     data = JSON.parse @stuff 
     @stuff.all? do |stuff| 
      data[stuff['something']] == stuff['anotherSomething'] 
     end))) 
end 
+0

Мне нужно немного подумать об этом, но если 'somethingElse' является ложным, то' @stuff = ... 'никогда не будет оценен, тогда как в исходной версии будет выполняться присваивание *. –

+0

BTW: это двойное отрицание выглядит немного противным, как насчет 'return true, если var.someProperty.zero?' –

+0

@ Jörg W Mittag, я согласен с вами в обоих комментариях. Я должен переписать ... – Nakilon

2

Использование ExtractMethod для вырезания метода в небольших логических частях. Ваши тесты должны помочь вам убедиться, что вы ничего не сломаете. http://www.refactoring.com/catalog/extractMethod.html

def return_bool 
    some_condition? && 
     var_is_valid? && 
     stuff_is_valid? && 
     parsed_stuff_has_something? 
    end 

    def get_var 
    @var = SomeClass.getter(foo) 
    end 

    def get_stuff 
    @stuff = @var.getsomething id 
    end 

    def some_condition? 
    condition1 && condition2 
    end 

    def var_is_valid? 
    get_var.someProperty == 0 
    end 

    def stuff_is_valid? 
    get_stuff && somethingElse 
    end 

    def parsed_stuff_has_something? 
    data = JSON.parse(@stuff) 
    @stuff.each do |stuff| 
     return false if data[stuff['something']] != stuff['anotherSomething'] 
    end 
    true 
    end 
Смежные вопросы