こんにちは宮水です。
今回は仕事でより良いRubyコードを書くために、Effective Rubyを読みました。
この本の対象者
- Rubyの文法や構造をすでに理解している人
実はRubyで案件始めたてくらいの頃にもこの本を読もうとしたことがあったのですが、読めずに挫折して再挑戦です。あの頃からRubySilverを取得して、RubyGold(あと1問のところで落ちちゃった...)を勉強しましたが、かなり読める項目が増えていました。
この本が難しいなと感じる人は、RubyGoldの勉強をするとRubyを体系的に学べるのでおすすめです。
それでは1章づつ雑な感想を書きます。
第1章 Rubyに体をならす
ここではRuby特有の仕様を学びました。
Rubyでは0も真、とかオブジェクトがnilになることもある、定数はミュータブルとか...。Javaをやってた頃に読んでいたらカルチャーショックがすごかったんですけど、今は「これRubyの流儀なんだな...」という感想に変わってしまいました...。
第2章 クラス、オブジェクト、モジュール
RubyGoldの勉強をしてから大好きになったRubyのクラスとオブジェクトとモジュールについてです。RubyGoldででた問題の理解が深まる内容でした。
- superとsuper()は違うの意味がようやくわかった
- 継承を使うクラスでinitializeメソッドを書くときはsuperを使って親を初期化することができる
- Struct便利そう
第3章 コレクション
Rubyのコレクションクラスというと、コンテナだと思いたくなる。
この章を読む前に、コレクションクラスとコンテナは若干違うものだと意識して読む必要がありそうです。
コンテナという単語を簡単に調べてみたら、"オブジェクトの集まりを表現するデータ構造、抽象データ型またはクラスの総称である。" ですって。コレクションと呼ばれることもあるそうです。一緒なの?何もわからない...
- 値渡しと参照渡し
RubyGoldでやたらとdupとかcloneメソッドの話が出てて丸暗記していました。
Rubyのメソッド引数は値渡しじゃなくて参照渡しだから、引数として渡されたコレクションは書き換える前にコピーを作った方がいい場面があって、そのときにdupとかcloneが便利だからあんなに問題がたくさん出てたんですね。
そういえば、実務では参照渡しでハマるようなコード書いたことないなぁ...
- Array()がKernelクラスのメソッド
知らなかった。
- 要素が含まれているかどうかの高速チェックはSetを使うことを検討する
何かを比べて一致する...順番はどうでもいい!ってときはArrayやHashよりSetの方が高速みたいです。
そんな場面に出くわしたことは、まだないんですけどね...
- Hash.new(0)便利
- コレクションクラスからの継承よりも委譲を使うようにする
あんまり実務で馴染みのない書き方だったので、難しかったのですが、Forwardableモジュールを使うと他のクラスからメソッドがつまみ食いできるらしい。
これを委譲といって、デザインパターンとかオブジェクト指向でもよく単語が出てきますね。
他のクラスに似たような処理がいっぱいあるけど、別のクラスを作りたい!ってときに役に立つかもしれないので頭の片隅に入れておこうと思います。
第4章 例外
これもRubyGoldでよく(
- raiseには文字列じゃなくてカスタム例外を渡す
文字列を渡すだけだと、RuntimeErrorを継承しちゃうの知りませんでした。StanderdErrorもただのクラスに変わりない、って結構名言ですよね。
これからはちゃんとStanderdErrorを継承した例外を書けるか意識します...
- ensureは確保したリソースを解放するために書く
そもそも、ファイルを開くときにリソースを確保していることを知らなかった。
JavaとかRubyとかばっかりやっててメモリを確保/解放するって話よくわからないのでそこから別の本で勉強してみようかな。
- retryは条件をつける
はい
- raiseとthrowどっちを使うか検討する
rubyでthrow/catchってあんまり使わないかも...!
第5章 メタプログラミング
Rubyのメタプログラミングが強力な武器になるときと、弱点になるときがあるからRubistならそれを知っておこうぜという話だった。
難しすぎて全然わからなかったので、1項目ずつ別の記事でまとめようと思います。
第6章 テスティング
Rubyは標準ライブラリにテスティングフレームワークが組み込まれています。
それを使って、効果的なテストを書く方法が解説されていました。
- Rubyコミュニティのテスト
> ユニットテストとスペック(ビヘイビア)テストの2つに分かれている。
テストの種類って色々ありますよね。Java時代は、単体テストはJUnit、それ以外はテスト設計書を書いて手動!が当たり前だったので、Ruby界隈のテスト事情になれるのに時間がかかりました。。。
Rubyでは、ユニットテストとスペックテストができるんだなーと念頭に置いてテストの書き方(describeやitなど)を学んだ方がよかったです。
- 合格すべきでないときも合格を出してしまう機能テストは簡単に書ける
機能を書いているときにテストをする方が、あとでテストをするよりもずっと簡単。肝に命じておきます。
第7章 ツールとライブラリ
Rubyは、ツールとライブラリ(irb、rdoc、gem)などが豊富です。
7章では、そのツールの使い方について学びます。
- Bundler
今でこそ使い慣れているBundler、昔はさっぱり意味がわからなかったんですけどこの本に全部書いてあった...
gemのバージョン管理ツールであること、bundle updateはしてはいけないこと、Gemfile.lockはignoreしようとか、初めは言われるがままにやってたこと全部書いてた... 1年前に読みたかった...
第8章 メモリ管理とパフォーマンス
最初は好き放題書いて動いてたアプリも、どんどん大きくなるとぶち当たる壁がメモリ管理やパフォーマンスですよね。Rubyのメモリ管理とパフォーマンスについて記載されていました。
Rubyがどのようにガベージコレクションを実現しているのか
- プロファイリングツール
ruby-profがおすすめ。
どのメソッドが重いとか一覧で見ることができる。
- ループ内ではオブジェクトリテラルを避ける
オブジェクトが生成されるたびにGCが実行されてしまったりしてパフォーマンスが落ちる。オブジェクトリテラルは定数に昇格させた方がいい。
- メモ化
発注の例で、なんども倉庫の最新情報を取得しなくてもいい例をみた。
一方で、メソッドの結果をどのくらいキャッシングするべきか?なども考慮する必要がある。コードをプロファイリング(かかっている時間を計測する)して、本当に必要かどうか考えることも大事だということがわかった。
全体的な感想
文法、オブジェクト、例外、テスティング、ツール、メモリ管理...とRubyの技術書によくある構成でありながら、本書は「Rubyの意外な挙動」や「Rubyの役立つテクニック」にフォーカスを当てた内容になっていました。
全体的に、実務でコードを書くときに役に立ちそうなお話が多かったです。
「別の言語めっちゃ得意だけどRubyは初めて」という方や「動くコードは書けるようになったけど、パフォーマンスを意識した書き方は苦手」という人にぴったりの本でした。
そして、また新しく自分が勉強するべきことを知ることができました。
例えば、Ruby特有の機能は他の言語(特にJavaとかC#とか)をもっと経験しないと本当にRubyのいいところをちゃんと理解するのは難しいと思いました。
Rubyの本はJavaやC#と比べることが本当に多いと感じます。Rubyを理解するために、もう一回Javaの本を読もうと思います。
リソースの確保/解放などは全くピンと来なかったのでプログラミングのもっと大きな概念も学んだ方が良さそうだな...と思いました。以下のような本を読んだ方が良さそうです。
特に5章のメタプログラミングはさっぱりだったので、明日から1項目ずつゆっくり読んでブログにまとめていこうと思います。わからないところはさらっと飛ばして、別の本も読んでみてまた戻ってきたいと思います!
1年半実務でRuby使ってても知らないことが多かったので、読んでよかったです!
以上です!