【Ruby】puts病の私がメソッド化を少しできるようになった話


できないことができるようになるって最高です!(ガッツポーズ) 

f:id:yskmtg:20201209012926p:plain

昔から、松岡修造さんに似ているとよく言われますが、決して熱くはないです(笑)
さて前置きです。

前置き

こちらは、フィヨルドブートキャンプ Part 1 Advent Calendar 2020 adventar.org

の9日目の記事です。8日目の記事は@altoさんによるTyporaのススメでした。
Part2 もありますのでぜひご覧ください。
 フィヨルドブートキャンプ Part 2 Advent Calendar 2020 - Adventar

概要

今年の8月からフィヨルドブートキャンプでプログラミング学習しているYusukeです。
初心者レベルの記事で恐縮ですが、今回Ruby学習を通じて学んだメソッド化(自分でメソッドを定義する)について書いていきます。

1. メソッドとは

オブジェクト指向言語において、オブジェクトに対する操作のこと。

Wkipediaから引用

まだ、オブジェクト指向でコードを書けない私としては下記の理解です。
メソッドは色々な処理を一つにまとめて定義したもの。処理を一つにまとめることで共同利用することができる。

2. メソッドの種類

Rubyには、メソッドの種類が2種類あります。
※一般のプログラミング言語でいう標準で入っている「組み込み関数」とユーザが自分で定義する「ユーザ定義関数」のことです。インスタンスメソッドやクラスメソッド、関数的メソッドのことではありません。

  • Rubyが用意してくれているメソッド(puts,p,each,uniq,sumなどなど)

  • ユーザーが自分で定義するメソッド

この記事では、ユーザーが自分で定義するメソッドに当たる方を説明します。

3. メソッドの定義

Rubyのメソッド定義は、defendの間に、実行したい処理を入れます。
defとは define(定義する)の略です。

定義の方法

def メソッド名
  メソッドが呼ばれたときの処理
end

4. puts病とは?

@jnchitoさんのきみたちは今まで何のためにRailsでMVCパターンを勉強してきたのか を読んでまさに自分はputs病だ…と反省しました。
puts 病とは上記の記事にあるのですが、ひとつひとつの処理を逐一、putsprintで出力してしまうことです。

コード例:自分で定義したメソッドなし

puts 'Hello, Ruby.'

result = 0
(1..5).each do |number|
  result += number
end
puts result

puts 'Goodbye, Ruby.'

# Hello, Ruby.
15
Goodbye, Ruby.

コード例:自分で定義したメソッドあり

def output_practice
  rows = practice
  puts rows
end

def practice
  rows = []
  rows << 'Hello, Ruby.'
  result = 0
  (1..5).each do |number|
    result += number
  end
  rows << result
  rows << 'Goodbye, Ruby.'
end

if __FILE__ == $0
  output_practice
end

# Hello, Ruby.
15
Goodbye, Ruby.


5. puts 病では何がだめなのか?

逐一結果を出力してコードを書くと下記のようなデメリットがあると考えました。

  • コードが長くなると読みにくい(同じ処理が重複してさらにコードが長くなる)

  • 変更する箇所が出てきた場合、全ての値を修正しないといけない (メソッドにしていれば値も使いまわせる)

  • 追加したい処理が出てきた場合に修正が大変 (ロジック本体と画面出力が密結合しているため)

  • putsで出力してしまうと、テストコードを書きづらい

6. なぜメソッドを定義できなかったのか?

メソッドを定義してどう呼び出すのかわからず、putsやprintを使った方が早く結果を知ることができ、次に進めたからだと思います。
今思い返せば、テストもせずロジックも組まずコードを書いていたことでより時間がかかってしまっていたと反省してます。。。

7. 自分で定義するメソッドを使えるようになったきっかけは?

きっかけはRubyの課題途中でいただいたアドバイスです。
LinuxのlsコマンドをRubyで実装する課題のとき、lオプションの表示では、ファイルの種類、許可属性などなど多数の項目を出力する必要があります。
私はそのlオプションのコードをmapの中に全て詰め込みループでひとつひとつをprintで出力していました。
ですが、rubocopにmapの中が長すぎると注意を受け、どう修正すればよいかわからず質問しました。そのときに「項目ひとつひとつをメソッド化して最後に出力してみたら?」というアドバイスをいただきコードを修正してみるとコードがスッキリ⭐︎それ以降メソッド化を考えるようになりました。

l_option.each do |file|
  print ファイルの種類
  print ファイルの許可属性
  print ハードリンク数
  print 所有者と所有グループ
  print ファイルサイズ
  print タイムスタンプ
  print ファイル名
end
# mapでループしてprintで出力していました。
  • 修正後のイメージ
def ファイルの種類 end
def ファイルの許可属性 end
def ハードリンク数 end
def 所有者と所有グループ end
def ファイルサイズ end
def タイムスタンプ end
def ファイル名 end

def output_with_l_options
  puts ファイルtotal

  file_names.each do |file_name|
    ファイルの種類
    ファイルの許可属性
    ハードリンク数
    所有者と所有グループ
   ファイルサイズ
   タイムスタンプ 
   ファイル名
  end
end

# 最後にオプションlであれば、output_with_l_optionsメソッドを呼び出すようにしました。

上記は修正後のイメージの方が長くなってしまっていますが、実際のコードは修正後の方がコードの重複がなく、コード数も短くスッキリしていて読みやすくなっています。

8. メソッドを定義するようになると

  • ロジックが組みやすく、どこでメソッドを呼び出せば良いか考えるようになりました。

  • 同じ処理を書かなくて済むのでコードもスッキリして読みやすくなすくなりました。   

9. まとめ

まだまだRubyのコードを書く際に同じ処理を使ってしまうことや、ロジックがきれいになっていないこともあるので、引き続き学習してオブジェクト指向でコードが書けるよう精進していきます!

最後までご覧いただきありがとうございました。


参考資料
ゼロからわかる Ruby 超入門
プロを目指す人のためのRuby入門
きみたちは今まで何のためにRailsでMVCパターンを勉強してきたのか
【Ruby入門】Rubyにおけるメソッド(関数)の使い方
Let'sプログラミング
Rubyのメソッドについて