LoginSignup
1
0

More than 3 years have passed since last update.

【初心者向け】Rubyで超簡単ドリンク注文アプリケーション(リファクタリングver)

Last updated at Posted at 2020-01-15

@scivola さんよりアドバイスいただき、DRYな部分を整理しました。

こちらの記事は
https://qiita.com/pontarou194/items/9e91b40dcc2da608dd24
の続きです。

もともとは、メソッドが4つありました。。。。

otyaメソッド
coffeeメソッド
beerメソッド
saidaメソッド

これを一つにまとめられました。
もともとはこんな感じ。

これがメソッドの多いアプリケーション(進化前)

def otya(otya)
  puts "あなたが選んだのはお茶"
  puts "お茶の値段は100円です"
  puts "いくつ注文しますか?"
  order_quantity = gets.to_i
  total_price = order_quantity * otya
  puts "合計#{total_price}円です"
end

def coffee(coffee)
  puts "あなたが選んだのはコーヒー"
  puts "コーヒーの値段は200円です"
  puts "いくつ注文しますか?"
  order_quantity = gets.to_i
  total_price = order_quantity * coffee
  puts "合計#{total_price}円です"

end

def beer(beer)
  puts "あなたが選んだのはビール"
  puts "ビールの値段は300円です"
  puts "いくつ注文しますか?"
  order_quantity = gets.to_i
  total_price = order_quantity * beer
  puts "合計#{total_price}円です"
end

def saida(saida)
  puts "あなたが選んだのは三ツ矢サイダー"
  puts "サイダーの値段は300円です"
  puts "いくつ注文しますか?"
  order_quantity = gets.to_i
  total_price = order_quantity * saida
  puts "合計#{total_price}円です"
end

otya = 100
coffee = 200
beer = 300
saida = 400

  puts "何を飲みたいですか?"
    drink_menu = ["お茶","コーヒー","ビール","三ツ矢サイダー"]
    drink_menu.each.with_index(1) do |drink_name, number|
      puts "#{number}:#{drink_name}"
    end

  case gets.to_i
    when 1
      otya(otya)
    when 2
      coffee(coffee)
    when 3
      beer(beer)
    when 4
      saida(saida)
    else
      puts "無効な入力値です"
    end

結論、メソッドを一つにまとめると、下記のようなコードとなりました(進化後)

def order_drink(drink_name, drink_price)
  puts "あなたが選んだのは#{drink_name}"
  puts "#{drink_name}の値段は#{drink_price}円です"
  puts "いくつ注文しますか?"
  order_quantity = gets.to_i
  total_price = order_quantity * drink_price
  puts "合計#{total_price}円です"
end

otya = 100
coffee = 200
beer = 300
saida = 400

  puts "何を飲みたいですか?"
    drink_menu = ["お茶","コーヒー","ビール","三ツ矢サイダー"]
    drink_menu.each.with_index(1) do |drink_name, number|
      puts "#{number}:#{drink_name}"
    end

  case gets.to_i
    when 1
      order_drink("お茶", otya)
    when 2
      order_drink("コーヒー", coffee)
    when 3
      order_drink("ビール", beer)
    when 4
      order_drink("三ツ矢サイダー", saida)
    else
      puts "無効な入力値です"
    end

@scivola さん完璧です。アドバイスいただきありがとうございました。
なんと、36行もコードを圧縮できました!

@scivola さんがおっしゃるお通り、ポイントは以下の通りです。

・DRYの原則にあてこむ(繰り返しは避ける、似た表現が繰り返される場合もなるべく避ける)
・メソッド名をわかりやすく


(自分で見返したとき用に)もっとわかりやすくします。

擬似コードで書いててわかるように、

def 
①お茶が選ばれた場合、値段を表示
②注文数を入力
③合計額を表示
end

def 
①コーヒーが選ばれた場合、値段を表示
②注文数を入力
③合計額を表示
end

def 
①ビールが選ばれた場合、値段を表示
②注文数を入力
③合計額を表示
end

def
①サイダーが選ばれた場合、値段を表示
②注文数を入力
③合計額を表示
end

この①〜③とメソッド名がかなり似ている。
これ、まとめたほうがすっきりしてわかりやすい。

特に
①のあなたが選んだのは○○
→共通化できる

②○○の値段は○○円です
→共通化できる

③合計○○円です
→共通化できる

あとは、いくつ注文しますかとか、gets.to_iとかを一緒に入れて完成。

def order_drink(drink_name, drink_price)
  puts "あなたが選んだのは#{drink_name}"
  puts "#{drink_name}の値段は#{drink_price}円です"
  puts "いくつ注文しますか?"
  order_quantity = gets.to_i
  total_price = order_quantity * drink_price
  puts "合計#{total_price}円です"
end

otya = 100
coffee = 200
beer = 300
saida = 400

引数の使い方について

今回勉強になったポイントは、引数の使い方
複数の引数を使用するケースをあまり経験したことがなかった・・・・・・

なので、いざ自分でコードを組み立てていくとなると、

何がどうなってるのやら??
っという状況でした。

下記のコードでは、drink_nameが第一引数、drink_priceが第二引数ですね。
コードにポイントをコメントで記述します。


def order_drink(drink_name, drink_price) #このdrink_nameとdrink_priceが仮引数
  puts "あなたが選んだのは#{drink_name}"
  puts "#{drink_name}の値段は#{drink_price}円です"
  puts "いくつ注文しますか?"
  order_quantity = gets.to_i
  total_price = order_quantity * drink_price
  puts "合計#{total_price}円です"
end
  case gets.to_i
    when 1
      order_drink("お茶", otya) #お茶とotyaが実引数
    when 2
      order_drink("コーヒー", coffee) #上記に習って同じ
    when 3
      order_drink("ビール", beer) #上記に習って同じ
    when 4
      order_drink("三ツ矢サイダー", saida) #上記に習って同じ
    else
      puts "無効な入力値です"
    end

仮引数と実引数は一致しなくても良いというのがありましたね。なので
これでも下記のようにcase文の実引数をいじって、otya = 100 等の変数宣言を省略することもできます。


  case gets.to_i
    when 1
      order_drink("お茶", 100)
    when 2
      order_drink("コーヒー", 200)
    when 3
      order_drink("ビール", 300)
    when 4
      order_drink("三ツ矢サイダー", 400)
    else
      puts "無効な入力値です"
    end

メソッド名をわかりやすく。

order_drinkというメソッド名はドリンクをオーダーするためだけなのか、計算もしてくれるのかがわかりずらいですよね。
なので、注文管理メソッドという名前をつけてみました。
グーグル翻訳すると、order_managementとなってましたので、そのまま名付けました。

最後に、コードをまとめました、こんな感じです。

def order_management(drink_name, drink_price)
  puts "あなたが選んだのは#{drink_name}"
  puts "#{drink_name}の値段は#{drink_price}円です"
  puts "いくつ注文しますか?"
  order_quantity = gets.to_i
  total_price = order_quantity * drink_price
  puts "合計#{total_price}円です"
end

  puts "何を飲みたいですか?"
    drink_menu = ["お茶","コーヒー","ビール","三ツ矢サイダー"]
    drink_menu.each.with_index(1) do |drink_name, number|
      puts "#{number}:#{drink_name}"
    end

  case gets.to_i
    when 1
      order_management("お茶", 100)
    when 2
      order_management("コーヒー", 200)
    when 3
      order_management("ビール", 300)
    when 4
      order_management("三ツ矢サイダー", 400)
    else
      puts "無効な入力値です"
    end

引数や変数は便利だなぁと改めて感じました。
また、DRYを原則とすることで、「保守しやすっ!」っと思いました。

ヒアドキュメントはもう少し勉強必要でした、、、

@scivola さんありがとうございました。

@scivola から、さらにアドバイスいただきました。

二重配列を使用して、case文を省略し、コードを短くできるよう見直しました。


def order_management(drink_name, drink_price)
  puts "あなたが選んだのは#{drink_name}"
  puts "#{drink_name}の値段は#{drink_price}円です"
  puts "いくつ注文しますか?"
  order_quantity = gets.to_i
  total_price = order_quantity * drink_price
  puts "合計#{total_price}円です"
end

  puts "何を飲みたいですか?"
    drink_menu = ["お茶","コーヒー","ビール","三ツ矢サイダー"]
    drink_menu.each.with_index(1) do |drink_name, number|
      puts "#{number}:#{drink_name}"
    end

    drinks = [
      ["お茶", 100],
      ["コーヒー", 200],
      ["ビール", 300],
      ["三ツ矢サイダー", 400]
    ]

    input = gets.to_i
    drink_name = drinks[input - 1][0]
    drink_price = drinks[input -1][1]
  order_management(drink_name, drink_price)

(おそらく合っている?
動作は問題なく動きました)

2次元配列について参考とさせていただきました。
https://pikawaka.com/ruby/array

case文使わない方法があるとは・・・・
実際かいてみると、単純構造でした。

drinks_menuも省略し、配列で処理しました。


def order_management(drink_name, drink_price)
  puts "あなたが選んだのは#{drink_name}"
  puts "#{drink_name}の値段は#{drink_price}円です"
  puts "いくつ注文しますか?"
  order_quantity = gets.to_i
  total_price = order_quantity * drink_price
  puts "合計#{total_price}円です"
end

drinks = [
  ["お茶", 100],
  ["コーヒー", 200],
  ["ビール", 300],
  ["三ツ矢サイダー", 400]
]

  puts "何を飲みたいですか?"
    drinks.each.with_index(1) do |drink_name, number|
      puts "#{number}:#{drink_name[0]}"
    end

    input = gets.to_i
    drink_name = drinks[input - 1][0]
    drink_price = drinks[input -1][1]
  order_management(drink_name, drink_price)

やばい、配列に関する知見が深まりましたw
今まで時間がかかっていたものが、5分程で処理できるように・・・・。

@scivola さん、アドバイスいただきありがとうございます。

1
0
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0