規定数のリトライ成功失敗における反復「式」の効用

Rubyでは反復は文でなく式である.そのため,途中で中断した場合,反復式として戻り値を持てる.すると,規定数のリトライ処理を,成功した場合と失敗した場合で,論理的に整合するよううまく記述できる.

ネットワーク越しのデータ取得は,必ずしも成功せずタイムアウトする場合があるからね...

  json = nil
  if [1, 2, 3].each {|t|
      if t > 1
        LOG.info msg + "retry"
        sleep t
      end
      json = JSON.parse(`wget -q -t 2 #{uri} -O - | ./html2json.rb`)
      break if json["itemID"] > 0 # 在庫あり
    }.nil?

    LOG.debug msg + json["itemID"].to_s

  else # 在庫なし

    LOG.info msg + "no stock"
    
    row[0] = 'd' if opts.isRakuten
    puts CSV.generate_line(row, {force_quotes: true})
  end

もし,反復式であることを知らないと,例外構文使っちゃうかも.
あるいは,反復が文しかない言語であれば,例外構文を使わざるを得ない.
この場合,在庫なしが正常ケースで,在庫ありが例外ケースとなる.

これは論理的に正しいプログラムといえるだろうか?

こういう場合,いちいち例外にするのは,大仰すぎないだろうかと.
なんとなれば,外部へ通信する部分にはすべて,例外構文にするべきだろうか?
論理的には,在庫有りも在庫なしも,正常ケースとみなすのが仕様として妥当な気がする.

begin
  json = nil
  [1, 2, 3].each {|t|
      if t > 1
        LOG.info msg + "retry"
        sleep t
      end
      json = JSON.parse(`wget -q -t 2 #{uri} -O - | ./html2json.rb`)
      raise unless json["itemID"] > 0 # 在庫あり
  }

  LOG.debug msg + json["itemID"].to_s

rescue # 在庫なし
  LOG.info msg + "no stock"
  ...略
end

例外構文ではなく,フラグを使ってもよい.

  json = nil
  found = false
  [1, 2, 3].each {|t|
      if t > 1
        LOG.info msg + "retry"
        sleep t
      end
      json = JSON.parse(`wget -q -t 2 #{uri} -O - | ./html2json.rb`)
      if json["itemID"] > 0 # 在庫あり
        found = true
        break
      end
  }
  
  if found 

    LOG.debug msg + json["itemID"].to_s

  else # 在庫なし
    ... 略
  end

さらにフラグが気持ち悪い人は,フラグの代わりに番兵を使う人もいるかも.