Ruby学習まとめ
自販機をシミュレートしたコードを問題点を完全しながら、オブジェクト指向についての考え方を学ぶ。
名前は省略しない
引数にはiとkind_of_drinkが記載されており、このままだとiが何を指すのか分からない。
def buy(i, kind_of_drink) if i != 100 && i != 500 @change += i return nil end
名前は省略せずに、誰が見ても分かるようにする
def buy(payment, kind_of_drink) if payment != 100 && payment != 500 @change += payment return nil end
ValueObject
intやstringと言ったプリミティブ型(基本的な型)をラップする。
意味のある値に対して型を定義すること。
改善前のコードでは自販機クラス
のbuyメソッド
に、支払額として整数の数値をそのままと、Drinkクラスに直接記載されたドリンクの種類を渡していた(引数)。これを、それぞれCoinクラスとDrinkTypeクラスに分けて、enum型として定義しなおす。
一見面倒にしか思えなけれど、下記のメリットがある。
- コードの可読性を高める
- 変更に強い
- 拡張しやすい
https://codezine.jp/article/detail/10184
ファーストクラスコレクション
配列をラップしたクラスのことで、対象の配列に対する処理を全て集約したクラスになります。別名コレクションオブジェクトとも呼ばれるそうです。
メリット
- 配列の複雑さを専用の小さなクラスに集約できる
- これにより対象の配列に関する処理がプログラムのあちこちに散らばることなく管理ができる
- メンテナンス性の向上やプログラム自体の分かりやすさにつながる
GetterとSetter、プロパティを使用しない
GetterとSetter
【Ruby】「ゲッター」と「セッター」を理解する - Qiita
インスタンス変数そのものはクラス内からしか取得できない。これを外部でも取得できるように定義したのがゲッター。セッターも同様、更新はクラス内からしかできないため、外部から更新できるようにするためクラス内部に更新用のメソッドを定義する必要がある。
アクセスメソッド
ゲッター、セッターを定義しなくてもインスタンス変数の参照・更新を可能にする方法。
- attr_reader: 変数名…参照を可能にする。ゲッター。
- attr_writer: 変数名…更新を可能にする。セッター。
attr_accessor: 変数名…参照・更新の両方を可能にする。セッターとゲッターを一気に使える。
オブジェクト内部状態を使用した処理を実現したい場合は、オブジェクト内で処理し、その結果だけを返すようにする。
まとめ
- これらはオブジェクト指向のカプセル化を壊す不適切なメソッドになりやすい
- オブジェクト内部状態を使用した処理を実現したい場合は、オブジェクト内で処理し、その結果だけを返すようにする。(処理結果を返すメソッドをクラス内に定義すると言うこと)
- これにより、オブジェクトが管理する内容が変わっても、他のクラスやメソッドに影響することなく、クラスを変更することができる!
一つのクラスにつき、インスタンス変数は二つまで
※ あくまでもオブジェクト指向エクササイズの規約内容ではインスタンス変数を二つに絞るように書かれているが、同じ役割を一つのクラスにまとめることを考えること。
反対に、一つのクラスが複数の役割を担っている場合は、枠割ごとにクラスを分割することも検討する。
else句を使用しない
現状、自販機クラスのbuyメソッド内には「ジュース一本100円の時、投入された硬貨が100円ならば、お釣り管理オブジェクトに支払額を入れる。投入額が500円ならばお釣り管理から400円分のお釣りを取り出す処理をして、お釣り管理の在庫内を更新する。」みたいな処理が一緒くたに記載されている。
非効率で分かりづらいコード。
お釣り管理(coinmech)に対して、お支払額(payment)を渡すことで、後の内部処理はお釣り管理でするして、その結果のみ返すようにすれば、もっと見通しよく簡潔なコードが書ける。
「else句を使用しない」と言うのはそう言うこと。
関連が強いもの同士を同じパッケージにまとめる
お金関連ならmoneyディレクトリに、在庫関連なら在庫ディレクトリにまとめてファイルを見通し良く使おう。
アルゴリズムメモ
組み込み変数ARGV(argument vector)
【Rubyの基礎】コマンドラインからの実行で利用するARGVの基本 | ポテパンスタイル
Rubyプログラムを実行する際に、引数として指定したオプションをプログラムの中で利用するための仕組み。argumentは引数のことで、ARGVはプログラムを実行した際に指定された引数を格納する配列。
# sample.rb arg = ARGV[0].to_i
$ sample.rb 9
- sample.rbファイルをターミナルで実行。その際、引数として適当な数字を渡す
- 渡される引数はstring型になっているので、もし数値そして使いたいのであればto_iメソッドで変換する
times, upto, downtoメソッド
timesメソッド、uptoメソッド、downtoメソッド - 繰り返し - Ruby入門
いずれもIntegerクラスで用意されている
upto
# sample2.rb arg = ARGV[0].to_i 1.upto(arg) do |num| p num end
$ ruby sample2.rb 4 #=> 1 2 3 4
- uptoメソッドは
x.upto(y)
のように使用した場合に、xからyまでの数値を順にブロック内に代入していることがわかる