軽めのgemをコードリーディングしてみた w/ wataridori
はじめに
この記事で紹介されているgemにとてもても親近感を覚えたので、コードリーディングの練習としてcommit logを最初から読んでみました。
最近esaの記事移行を試したり、API書いたりしていて、そのあたりの所作を学びたいというのがモチベーションです。
メモ
メモはコミット順に沿っています。
gemspecの記述
gemで使いたいgemの情報はGemfileでなく.gemspecに書く。
add_dependency "hoge", "0.0.1"
リファレンス https://guides.rubygems.org/specification-reference/
参考記事 gemライブラリの依存はGemfileではなくgemspecに記述する理由
テストしやすい書き方をする
以下ではtoken, from, toを渡す先をnewからfrom_teamnameに切り出すことで、 クライアントの差し替えを行い易くしている。
https://github.com/misoca/wataridori/commit/82faabb727bcd94e76542d898f6071cd4acdc83a
CI
ツールが小さいうちに導入するの良さそう
Circle CIの導入 https://github.com/misoca/wataridori/commit/97db850fd19447299248659fcb608d33ac641e52
RuboCopの導入 https://github.com/misoca/wataridori/commit/dc248d23bb71e07054c50ff411465d8dd5a8e946
ラッパークラスの導入
ラップしておくと今後の実装で便利らしい →レート制御、リトライ制御 https://github.com/misoca/wataridori/commit/c3dbba1caa916ae9a82cc1e37fdce05b94aaeef7
method_missingもここで用意している(メタプロ感)
ガード節という書き方(リファクタ)
普段使ってるけど名前があったのか。 処理の冒頭に条件判断とreturnを入れて例外処理を完結させる。 ネストが深くなるのを防止できる。
https://github.com/misoca/wataridori/commit/d55361632ea3f3e5ca320409ef7a2e5bb451e20d
参考記事 初心者向け。覚えておきたい 「ガード節」という書き方。
インスタンス変数へのアクセサをきちんと書く
今回はattr_readerだがこんな感じのセット
- attr_reader: 読み込み
- attr_writer: 書き込み
- attr_accessor: 読み込み&書き込み
https://github.com/misoca/wataridori/commit/2a229be5ad7185669c77334f9494679b28ef5fa2
リファレンス https://ref.xaio.jp/ruby/classes/module/attr_accessor
APIのRate Limit (利用制限)
結構最初の方に仕込んでるのでAPI利用時に注意することとしては高めぽい。
esa APIのRatelimitを表すクラスを追加 https://github.com/misoca/wataridori/commit/81ad20c8188891146de51f2683207497f0069f0a
Wataridori::Esa::ClientでRatelimitを考慮するよう機能追加 https://github.com/misoca/wataridori/commit/d22862b254798fbc7a2a7439c2a1af7d06faf141
例) GitHub https://developer.github.com/v3/rate_limit/
参考記事 APIとは?API Rate Limitってなに? WebAPIを設計するうえでの利用制限(Rate Limit)について調べた
テストの可読性を上げる
https://github.com/misoca/wataridori/commit/2cc1ba07a1e80a285f17182e59a477d56a8d61d9
ページネーションへの対応
https://github.com/misoca/wataridori/commit/8ebf6a70f3ddf76ea8a03b04eb1514d35b879314
なるほどこういう書き方をするのね 仕様としてnext_pageがないとnullが返ってくるのでそこでloopが終わる(loop処理はあとでリファクタされてました)。
def list_posts(category, per_page) posts = [] page = 1 loop do res = from_client.posts(posts_params(category, page, per_page)) posts += res.body['posts'] page = res.body['next_page'] break unless page end posts end
Hashie gemの導入
ハッシュをより便利に。 https://github.com/intridea/hashie
参考記事 ぼくのおすすめGem その2
ロガーでスクリプト実行内容を標準出力
何をやっているかをわかるようにする。 https://github.com/misoca/wataridori/commit/68f8f8d0158647e15a1e5fd44b6f159bd07ead47
コマンド追加とREAD ME追記
処理の改善
- コピー処理をページごとに実施することでメモリ効率を改善
- yieldの使い方要復習
https://github.com/misoca/wataridori/commit/23d7a0a93b38687d4ba9a7332d8a0768834a367f
データのまとまりは構造体にする
ここでもhashieが活躍 https://github.com/misoca/wataridori/commit/637553181956be2b678fcbfca9945cc5781961ad
参考記事 構造体を使ったプログラム
共用体というのもあるらしい。
リンクの書き換え用にnokogiriを導入
https://github.com/misoca/wataridori/commit/b255e92817c55fe085b95ba900ba8777bc5804af
https://github.com/misoca/wataridori/commit/80a2c018dabb4ca1a2b217e2d8ae7dfc4bf5ba76
こんちゃんさんが言ってたprivate accessorや↓
複数コマンド対応の書き方
https://github.com/misoca/wataridori/commit/448973083708bc87b44cd9ea20483bbaf4548db6
retry処理の導入
https://github.com/misoca/wataridori/commit/dea92a14e7b44ceec415bb764555a893bd305027
まとめ
普段はある程度形ができたリポジトリのコードを読むことが多いのですが、公開されるまでの流れを把握できる規模のコードを読むのはひよっこエンジニア的にかなり勉強になりました。
たまたま「名前に親近感を持った」という興味で読み始めたのですが、こういうOSS貢献しているMisocaさん素敵だなぁと思いました。