Sider Blog

コードレビュー自動化サービス「Sider」を運営するSider株式会社のコーポレートブログです。



RuboCopコミッタ、Pockeが語るBatsov像とアドバイス -SideCI技術顧問就任記念インタビュー

SideCIでは、2018年4月より、RuboCopコミッタのPockeこと、桑原 仁雄氏を技術顧問に迎えることになりました!Pocke氏は、2015年9月にSideCIに入社して以来、SideCIが提供する解析器の拡充などに携わってきました。この4月よりクックパッド株式会社に転職し、同時にSideCIの技術顧問に就任しました。SideCIではこれを記念し、Pocke氏にインタビューを行いました。和やかな雰囲気の中、RuboCopから、Batsov氏のこと、そして未来のコミッタたちへのアドバイスなどを、ざっくばらんに話してくれました。ぜひご覧ください!

目次

f:id:sideci:20180308172024j:plain

RuboCop自体の話

- まずは、基本的な質問から始めましょう。RuboCopとは何でしょう?

RuboCopは一番括りの狭い言葉でいうとRubyの静的解析器なんです。それは何故かというと、静的解析器の中にスタイルチェッカーとLinterあとその他諸々がいっしょくたになったものだからです。その他諸々って言うのは、例えばメトリクスを測るようなものとかです。 特徴的なところでは、RuboCopのReadmeの一番最初に映画のロボコップのセリフが引用されているんです。「Role models are important.」

f:id:sideci:20180417115626p:plain 出典:http://rubocop.readthedocs.io/en/latest/

確かRuby Style Guideの方にも同じセリフが引用されているはずです。

RuboCopに関わり始めてからコミッタになるまで

-どういう経緯でRuboCopに関わるようになったんでしたっけ?

2015年の秋にSideCIに入ってからRuboCopに関わるようになりました。2016年に初めてプルリクを送ったんです。最初は割とどうでもいいプルリクを投げていたんですけど、そのうちRuboCopって結構バグがあって面白いって気がついて、ひたすらバグを直していた気がします。

- RuboCopでは主にどういう仕事をしていますか?

地味にバグを直していますね。

f:id:sideci:20180417115921p:plain Fix Style/RedundantReturn cop for empty if body #3607”(https://github.com/bbatsov/rubocop/pull/3607)

例えば、このPRでは、Rubyではifの中身が空のことがあるんですけど、そうするとRuboCopがクラッシュするっていう問題があって、それを直すものです。

他には、ちょっと前にRSpecをtest-queueで速くするっていうのをやりました。 https://github.com/bbatsov/rubocop/pull/4544

当時CIがめちゃくちゃ遅くて辛かったんですけど、結構速くできたので良かったですね。大体2〜3倍くらいは速くなりました。

-コミッタになったときの経緯とかは、なにかきっかけがあるんですか?

特にきっかけは無かったと思います。ある日突然Invitationが届いていたみたいな感じで。READMEのヒストリでPockeと検索すると出てくるのが、8ヶ月前ですね。 f:id:sideci:20180417120641p:plain なにか特別なことをやっていたわけでもありませんが、でも一番プルリクを送っていた時期だとは思います。

- コミッタになる前となった後で関わりかたになにか変わったところはありますか?

あまりないです。外に向けてコミッタやっているってことを言えるようになったっというのと、あとはIssueにラベルをつけられるようになったのが一番の違いです。

前に「5個ぐらい同じIssueが立っている」みたいなことがあって、それは辛かったですね。もちろん、一瞬でCloseできるので大きな問題ではないのですが。コミッタになったことで、Closeとかラベル付けとかできるようになってしまって、自分の問題になってしまった。ちょっと検索してみて欲しいって気持ちはあります。

Batsovの話

-Batsovはどんな人ですか?

ヨーロッパ圏でVPoEやってる方で、確か人材系の会社だった気がします。会ったことはないんですが、去年はEuRukoでトークしてましたね。今は積極的に自分でRuboCopのコードを書くということはしていなくて、でも別にRuboCopに興味を失ったということでもないみたいでレビューはがんがん来ます。プルリク等を見ていても反応は早い方で、帰ってこないときは旅行中とかそのような時だけ。そうでないときはこまめに返ってきてます。 全体的にマメで親切な人だという印象はありますね。レビューしてても、なにか言ったら、同じことを同じコードについて全部繰り返して書くとか。忘れなくて良いです。プルリクもほとんどマージしていて、そういう意味でも、寛容というか、全て受け入れてるなって気がしますね。大きすぎるとか、説明がないとか、そういうPRはどうしようもないので、pingを打って返ってこなかったらCloseするとかしますけど。

-RuboCopの名前とかさっきのREADMEの引用とか、ロボコップからの借用が多いような思いますが、誰の趣味なんでしょう?

Batsovの趣味だと思います。さっきの「Roll models are important.」はRubyStyleGuideにもありますし。あれもBatsovがやった仕事です。 面白かったのだと、RuboCopのルールのグループが分かれていますが、例えばStyleとかLintとか、あのグループのことを昔はcop_typeと言っていたんですけど、ある日突然departmentに変わったんですよ。 <<PR: Replace cop_type with department https://github.com/bbatsov/rubocop/pull/3842>>

これは、コップ(警察官)の部署という意味らしいんです。コミッショナー(所長)の下にteamがいたり、警察関連の言葉が用いられているんです。他にも、forceとかoffenceとか。forceってプログラミング用語とは関係がなくて、変数のトレースとかするものをさしています。構造を覚えるのが大変ですね。 (出典:2016/12/30 https://github.com/bbatsov/rubocop/pull/3837#issuecomment-269750599  この中でBatsovは” And I think we've strayed from our fun police references! cop_type? A cop should have a department, not a type! :-)”と述べている。

RuboCopの開発に参加するには

-RuboCop自体のコードレビューというのはどんな形で運用されているのですか?実際にレビューする人される人って側でのコメントを聞かせてください。

特に決められたレビュアーとかはいなくて、誰かが見るみたいな運用をしています。ただ、マージは基本的にBatsovがすることにはなっています。で、結構コミッタじゃない人もレビューしていて、活発な感じで動いています。

あんまり厳格なルールはないのですが、PRのテンプレートがリポジトリに入っているので、できるだけそれに沿って欲しいというところぐらいですね。Issueを上げてからPRを作る、みたいな作法のプロジェクトもありますが、RuboCopはそうではない。テストは追加して欲しいですけど。

レビューで気にするところは結構人によって異なっていて、結構コーディングスタイル的なところを突っ込む人もいます。名前とか英語とかも見られますね。私も、最初のころは全然英語ができなくって、Offenceのメッセージに「その英語おかしいよね」とか言われるのは結構ありました。

-新人コントリビュータへのアドバイスみたいなものはありますか?

私は、正しいRubyのコードで走らせた時にクラッシュしないかどうか、割と重視してみています。なので、一回作ったものをなるべく多くのコードで試した方がいいっていうのがアドバイスですね。私がきちんとやるときには、ruby/spec(github.com/ruby/spec)や、GitLab(github.com/gitlabhq/gitlabhq)とかの大きなRubyのプロジェクトで試すようにしていて、クラッシュしないかとある程度正しいオフェンスが出てるかを見るようにしています。

-「こういうのが手をつけやすそう」みたいなものはありますか?

RuboCopって、デフォルトの設定じゃないと簡単にクラッシュするので、ちょっと変わった設定をすると意外と簡単に問題が見つかります。RuboCop自体はRuboCopでチェックしてるんですが、ほぼデフォルトの設定になっていて、だからデフォルトの設定だとさすがになかなか問題は見つからない。

あとは、さっきのruby/specで、そこには結構面白いコードがたくさん入っているので、RuboCopにそこのコードを読ませると簡単にRuboCopが壊れます。

他にはこういうのがあります(#4910)。

f:id:sideci:20180417121108p:plain https://github.com/bbatsov/rubocop/issues/4910

これは「Documentationに例が欲しい」Issueを立てたら、結構みんなやってくれて。コメント足すだけなんで、簡単にできるといえば出来るんですけど。これがないと、テストケースを見ないと、そのコップが何をするかわからないという状況だったので。これなんか、手が付けやすかったんじゃないかと思います。

Issueはもうずっとつまっていて、まあ300件ぐらいオープンなものがあるんですけど、割とずっと積もっているままになっているのが多いです。なので丁寧に見ていけば、なにかやりやすいものがあるかもしれませんね。

- RuboCopの開発チームでこういうことをやっていきたいみたいなテーマはあったりしますか?

最近ですと「bump to 1.0」っていうIssueがあって、これ本当にスタートさせるのかな、と思ったりしています。

f:id:sideci:20180417121430p:plain bump to 1.0 のスクリーンショット

今は0.53.0なんですが、Batsovのコメントによると、まだ1.0にはしないって言ったりとかしている。これも品質が低いとしか言っていないのでなにをやっていきたいのかはっきりとはわからないんですが、まだまだ壊したいんじゃないですかね。そろそろ1.0を出して、壊れたら2.0を出すようにするとかしてもらいたいんですけど……

個人的に今やりたいのはオートコレクトですね。「ruby/specを入力にして、RuboCopでオートコレクトして、その結果がテストを通るかどうか」っていうのをやってみたいですね。現状はruby/specを入力しても全然ちゃんと動かないので。

後はちょっと使いにくいところがあって、「ソースコードの一部だけを選択的にオートコレクトしたい」みたいな要望があるんですけど、そういうのをサポートしたいですね。

- RuboCopの開発者って多分日本にも何人かいると思うんですけど、その人たちと何かオフラインで会って話したりしますか?

割と会うことがあります。最近プルリク投げているkoicさん (github.com/koic)、結構よくあっていて、RuboCopの話をすることがあります。懇親会とかが多いんですが、去年のRubyKaigiの時は、こういうの作ろうと思ってるんだけど、どう?みたいな相談をされて、一緒に話しながらプルリクを見ていったことがありました。

RuboCop利用者へ

-どういう風にRuboCopを使ってもらいたいみたいとか、こうやって風に使ってみたらいいよみたいとか、アドバイスはありますか?

RuboCopに期待しすぎないで欲しいっていうのはあります。銀の弾丸だと思っている人がいて。で、とりあえず入れたらコードがよくなるって思っている人がいると思うんですけど、そうではなくて、RuboCopにどうさせたいか、っていう目的がないと、ちゃんと使いづらいっていうのがあると思います。

例えば、RuboCopでコーディングスタイルを統一したいという目的があるんだったら、それ用のコーディングスタイルを作るとこから始めるか、RuboCopのコーディングをそのまま受け入れるみたいな選択が必要になります。なので、入れただけだと、警告が大量に出て失敗するっていう状況だけになるかなと思います。

RuboCopを使って何をやりたいのかというのをまず考えて、その上でちゃんと設定しないといけない。

-具体的には、それぞれどうやって設定を詰めて行ったらいいのでしょうか?

WEB+DB PRESSに「Rubyドキドキ探検隊」という連載を2017年からしているんですが、Vol.102で解説を書いたので、読んでいただければと(笑)。

ざっくりというなら、まずスタイルの方は、ひたすら頑張って直していくしかありません。.rubocop_todo.yml (http://rubocop.readthedocs.io/en/stable/configuration/#automatically-generated-configuration) っていう仕組みがあるので、それを使えば良いと思います。 これは、一回、今のソースコードで出る警告をToDoとして書き出した上で、警告は出ないようにするという仕組みで、まずはじめに出た警告を一旦見なかったことにして、少しずつ自分たちのルールを作って行きながら、適用をしていくということができる。結局その作業をしなければいけないのでいけないので、どこかで自力で頑張らなきゃいけないということになります。

バグを見つけるというのはもっと簡単で、単にDisabledByDefaultってオプションがあるので、一旦全部バッて無効にしてバグを見つける系のLint系のルールだけを有効に設定するのがいいです。 ruby/specの設定がちょうどこの使い方なので、参考になるかもしれません。

- 逆にRuboCop利用者にお願いしたい事はありますか?重複してバグを報告しない、以外で(笑)

バグは出来れば報告してほしいですね。日本人向けのことを言えば、rubocop-jp(github.com/rubocop-jp/issues)というorganizationを作ったので、そちらにバグを報告していただいても良いです。 これはvim-jp(github.com/vim-jp)を参考にしていて、rubocop-jpに上がってきたものを英語化して本家に投げるところまでできれば、理想的なんじゃないかと思います。

私がそもそも英語を書きたくないっていう思いがあって、でも英語でやらないと本家のIssueにあげられないじゃないですか。で、そうすると自分の中だけに溜まっていくIssueっていうのが大量に増えてきて、それを管理するのが嫌になってきたので、rubocop-jpを作ったというのも側面にあります。

SideCIについて

-SideCIでRuboCopを使うと便利だと思うんですが、その辺りを少し話していただけますか?

現状で言えば、割とLint系ってどうしてもfalse positiveが出るものだと思うんですけど、SideCIで動かしていると、そういうものでも割と気軽に有効にしていけるっていうのは、あると思います。

SideCIがない場合には、ローカルで動かすかCIの中で実行するかしかないんですが、ローカルでいちいち実行するのは面倒なのでCIでやろうかっていう話になると思います。ところが、それだと1か0かみたいな所があって、RuboCopがコケるかコケないかの二つの状態しか持てない。これは、不便なことが結構あるんじゃないかなと思います。SideCIがあると、RuboCopが出した指摘をCloseするかしないか選択できるので、「この警告は許容しておく」っていう状態が出来るので柔軟性が高くて、使いやすい状態になると思います。

(編集者注:SideCIではRuboCopなどのLINTツールに検出された問題を修正するのか、それとも今回は対応せずに見送るのかを、個々に設定することができます。実際に検出された問題を確認しながら、それぞれを修正するかしないか決められるので、より積極的にツールの検査を有効にすることができます。)

あとは今は実装できていない未来の話をすると、オートコレクトももっと上手くできると思っていて、自動で修正したいんだけどどう修正したら良いのかは自明ではなかったりするときに、インタラクティブに修正していけるようなUIがあると良いのかなと思います。

f:id:sideci:20180308172951j:plain

インタビューの最後には、SideCIのCTOの松本とPocke氏で記念撮影をしました。 Pockeさん、これからもどうぞよろしくお願いします!