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

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

昔から、松岡修造さんに似ているとよく言われますが、決して熱くはないです(笑)
さて前置きです。
前置き
こちらは、フィヨルドブートキャンプ 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のメソッド定義は、def
とend
の間に、実行したい処理を入れます。
defとは define(定義する)の略です。
定義の方法
def メソッド名 メソッドが呼ばれたときの処理 end
4. puts病とは?
@jnchitoさんのきみたちは今まで何のためにRailsでMVCパターンを勉強してきたのか
を読んでまさに自分はputs病だ…と反省しました。
puts 病とは上記の記事にあるのですが、ひとつひとつの処理を逐一、puts
やprint
で出力してしまうことです。
コード例:自分で定義したメソッドなし
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
の中が長すぎると注意を受け、どう修正すればよいかわからず質問しました。そのときに「項目ひとつひとつをメソッド化して最後に出力してみたら?」というアドバイスをいただきコードを修正してみるとコードがスッキリ⭐︎それ以降メソッド化を考えるようになりました。
lsコマンドlオプションの出力結果 「ls -l」コマンドの表示からファイルの属性を理解しようから引用
rubocopに注意を受けたコードのイメージ(mapからendまで実際は50行ほどコードがありました…)
※これから課題に取り組む方もいるのでコードイメージにしています。
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のメソッドについて