プログラミング備忘録

プログラミングの学習状況をメモしています

31日目

今日の学習

Ruby

リファクタリング

昨日取り組んだ課題を、やんばるエキスパートのメンターの方に見ていただき、望ましいリファクタリングを色々と教えていただけたのでメモ。

全体的に、プログラムを動かす段階にたどり着いて安堵してしまい、細かいところまで気が回っていなかった。

完成できた!と思ったあとは、しっかり見直して整えたり、不要なものがないかを探す癖をつけたい。

不必要な改行を避ける

単純に隙間が空いていたら見やすいだろう等と考えていたり、完成させられたことに気を取られて最後に全体を整える作業を行なっていなかった。

フォーマッターに、勝手に揃えてくれる機能がありそうな気はするが、今回は手動で直してみると、確かに謎の改行部分があった。

  • 改行は基本的に一行にする
変数に複数のクラスインスタンスを配列として代入
monsters = [
monster1 = Monster.new(name: "モンスター", hp: 300, offense: 180, defense: 100),
monster2 = Monster.new(name: "ドラゴン", hp: 350, offense: 200, defense: 150)
]
monster = monsters.sample

このように、(2体しか設定していないが)モンスターをランダムで出現させるような形を取っていた。

変数に配列を代入していたのだが、中で割り振っているmonster1monster2は使用していないので、不要だ。なので、

monsters = [
  Monster.new(name: "モンスター", hp: 300, offense: 180, defense: 100),
  Monster.new(name: "ドラゴン", hp: 350, offense: 200, defense: 150)
]
monster = monsters.sample

このように書くことができる。

使わないものをわざわざ書かないようにしたい。

処理の中ではインデントをする

loop処理を使っていたが、その箇所のインデントができていなかった。

インデントされていない処理を改めて見てみると、かなり見にくいと感じた。インデント大事。

ただ、改行もそうなのだが、「適切な改行は?」「ここはどれくらいインデントをすればよいか?」というコーディングの決まりみたいなものを、そもそも知っておくべきなのではと強く感じた。

Rubyコーディング規約 - Qiita

Rubyコーディング規約

キレイで読みやすいRubyコードを書くために。RuboCopスタイルガイド レイアウト編 | よこのじ.work

これを機に、もっとRuboCopをうまく活用して、綺麗なコードが書けるようになりたい。

また、最近クイズプログラムのリファクタリングもしていただけたので、追々指摘していただいた部分を直しつつ、形になったらQiitaに制作過程を書いてみようかなと考えている。

クラスの継承

Ruby本で学習。サンプルプログラムといい、一気に内容が難しくなってきた...。

Progateで継承の存在や、簡単な使い方は学んだが、自発的に利用したことはないのでちゃんと考え方を叩き込んでおきたい。

継承元のクラスをスーパークラス、継承し新しく作成するクラスをサブクラスと呼ぶ。

これはis-aの関係というもので、違和感がないかどうかを確かめられる。

スーパークラスAnimalで、サブクラスがCatであれば 、Cat is an animalと言える。これがis-aの関係

initialize

スーパークラス、クラスどちらでも同じ値をinitializeメソッドで代入しているとき、superを使うとスーパークラスの同盟メソッドを呼び出すことができる。

class Animal
  def initialize(name)
    @name = name
  end
end

# ↓Catクラスに継承しても、nameを使用したい

class Cat < Animal
  def initialize(name, breed)
  # スーパークラスのinitializeメソッドを呼び出す
  super(name)
  @breed = breed
  end
end
オーバーライド

サブクラスで、スーパークラスと同名のメソッドを定義することで、スーパークラスの処理を上書きできる。

# 先ほどの内容のまま重要な部分だけ記載
class Animal
  def introduce
    puts "こんにちは、#{@name}です!"
  end
end

class Cat < Animal
  def introduce
    puts "こんにちは、#{@name}です! 猫種は#{@breed}です!"
  end
end

これで、introduceメソッドの中身が書き変わっている。

このメソッドは、「こんにちは、#{@name}です!」の部分が共通しているので、以下のようにスーパークラスのメソッドを活用することができる。

class Cat < Animal
  def introduce
    puts "#{super} 猫種は#{@breed}です!"
  end
end

メソッドの公開レベル

メソッドには、三つの公開レベルがある。

  • public
  • protected
  • private

initializeメソッド以外のインスタンスメソッドは、デフォルトでpublicメソッドになるため、自分がこれまでに何気なく使っていたメソッドの大半はpublicメソッドということになる。

privateメソッドに関しては、Railsでコントローラの一番下に書いたりはしているが、なぜprivateメソッドでなくてはならないのか?ということを深く考えていなかった。

クラス内でprivateと記述をすると、その位置から下に書かれたメソッドはprivateメソッドになる。

privateメソッドは、クラスの内部だけで使用できるメソッドで、外部から呼び出すことはできない。

レシーバを指定して呼び出すことができないメソッドということらしい。

レシーバとは、「メソッドを呼び出された側」という意味を持つ表現。

先ほどのコードを使ったcat.introduceというコードでは、「introduceメソッドのレシーバはcat」ということになる。

ただ、定義したクラス内だけではなく、サブクラス内でも呼び出すことができる。

そのため、スーパークラスのprivateメソッドをオーバーライドしてしまった!ということもあるので、サブクラスでメソッドを作成する場合はスーパークラスのメソッドもしっかり確認しておく。