Понимание влияния ложного в методе - PullRequest
0 голосов
/ 28 августа 2018

Мой метод обрабатывает программный цикл для true / false. Код принимает число целых чисел, затем проверяет:

  1. Если представленное значение является числом
  2. Если число находится в диапазоне от 1 до 100

Код:

def self.number_validator(*numbers)
    numbers.each do |number|
        unless number.is_a?(Integer)
            puts "#{number} is not an integer" 
            return false
        end
        unless number > 0 && number < 100
            puts "#{number} is out of range"
            return false
        end
    end
    return true
end

Насколько я понимаю, возвращение false завершит весь метод. Я обеспокоен и хочу убедиться, что он не прерывает только цикл и возвращается в раздел return true. Я хочу убедиться, что истинное значение не вызывается ложным значением, закрывающим цикл и возвращающимся к общему методу (а не просто сообщающим ложное и останавливающим метод).

Ответы [ 2 ]

0 голосов
/ 28 августа 2018

Nadnerb , return завершит любое дальнейшее продолжение кода, тогда как break выйдет из текущего цикла и перейдет к следующему набору инструкций.

0 голосов
/ 28 августа 2018

Я обеспокоен (и хочу убедиться), что [это работает].

Это работает (почти). С небольшой ошибкой, которую вы написали < 100 вместо <= 100.

return немедленно выходит из метода. Ключевое слово break, с другой стороны, будет выходить только из цикла.

Но не просто поверьте мне на слово. (И спрашивать кого-то в StackOverflow, работает ли ваш код, не эффективный способ его протестировать!) Давайте напишем несколько тестов для вашего кода:

require 'rspec'

RSpec.describe 'number_validator' do
  subject { number_validator(*input) }

  context 'integers only (valid input)' do
    let(:input) { [1, 5, 80, 100] }
    it { is_expected.to eq true }
  end

  context 'non positive integer' do
    let(:input) { [1, 5, 0] }
    it { is_expected.to eq false }
  end

  context 'integer greater than 100' do
    let(:input) { [1, 5, 101] }
    it { is_expected.to eq false }
  end

  context 'non integer' do
    let(:input) { [1, 5, 'BAD'] }
    it { is_expected.to eq false }
  end
end

Вы также можете написать больше крайних случаев, если хотите, например. Что делать, если не указан ввод данных (number_validator()), или отрицательное число (number_validator(-1)), или нецелое число (number_validator(3.5)), ...

Теперь, когда у нас есть несколько тестов, давайте попробуем немного переписать этот метод к чему-то более элегантному. Мы можем быть уверены, что это все еще работает, потому что тесты все еще должны пройти!

Вместо использования Array#each с несколькими операторами return мы можем вместо этого использовать Enumerable#all?, чтобы сделать то же самое в гораздо меньшем количестве кода (если вы готовы отбросить puts заявления):

def number_validator(*numbers)
  numbers.all? { |number| number.is_a?(Integer) && number > 0 && number <= 100 }
end

Затем мы можем еще больше упростить это, используя Comparable#between?:

def number_validator(*numbers)
  numbers.all? { |number| number.is_a?(Integer) && number.between?(1, 100) }
end
...