Rubyコーディングスタイルの現状とStandard gemのご紹介

これは[Ruby Advent Calendar 2018](https://qiita.com/advent-calendar/2018/ruby)の4日目の記事になります。昨日は[pink_bangbi](https://qiita.com/pink_bangbi)さんの[あなたのしらない Refinements の世界](http://secret-garden.hatenablog.com/entry/2018/12/03/231925)でした。

# 一行まとめ

Rubyのコミュニティ共有コーディングスタイルを目論む[Standard gem](https://github.com/testdouble/standard)をJustin Searlsが作っているので、意見があれば[議論に参加](https://github.com/testdouble/standard/issues)しましょう！

# Rubyのコーディングスタイルについて

Rubyには公式のコーディングスタイルが決められていません。また公式のフォーマッターもありません。Ruby作者のまつもとさんは、コーディングスタイルについて、積極的には統一ルールを打ち出そうとはしていないようです。

まつもとさんの考えていることと、コーディング規約＆オートフォーマッタの現状については[Siderのインタビュー](https://blog-ja.sideci.com/entry/2018/03/02/120636)に詳しいです。ちょっと長いですが引用します。

> まつもと : コーディング規約を決めてくれないと仕事できないよ！っていうような人もいて、「君、本当に仕事してる？（笑）それは自分で考えようよ」と思っちゃう。ただ、インデントの幅とかスペースかタブかみたいな話は、修正するとdiffが大量に出てくるのでそれは事前に考えておいたほうがいいと思いますね。
> 
> 角 : オートフォーマットで触ってないところもガーッと変わってしまったりしますよね。
>
> まつもと : そうですね。それだけはよくないと思うんだけど、無駄なdiffが発生しないようにすればコーディング規約は特に必要ないんじゃないかなと思ってしまいます。例えば、変数名は必ず長い表現にしようとか。3回しか出てこない変数が長い名前だろうが、iだろうがどうでもよくない？と考えてしまうんです。
> 
> 角 : 3回だったら全く関係ないですね。もしi がグローバルでどこでも使われていたらそれは問題ですけど、そんな馬鹿げたコードは書かないと思います。
> 
> まつもと : それは普通に考えたらわかることですよね。仮にそう書いちゃったとしても、コードレビューの時にダメだっていう理由があるわけだから、「これだけじゃわからん」みたいに指摘されちゃえばいいわけです。そう考えるとコーディング規約はそこまで重要じゃないんじゃないかなと思ってるんですよね。
> Rubyコミュニティーの一部でもRuboCop万歳みたいな人たちが一定の割合でいて、でもRuboCopのデフォルトだと僕の好みとだいぶ違ったりして、どうして？となるようなルールも結構入ってる。もちろんRuboCopのような静的解析ツールの価値はわかるしRuboCopの人たちを尊敬してもいます。
> 
> 角 : デフォルトのRuboCopは私も苦手ですね。SideCI社内のSlackでもこのプルリクエストがRuboCop本体にマージされちゃうのかぁ。という苦言のようなコメントが出ることはありますね。
> 
> まつもと : 基本的にプログラマは自主的な側面があると思うので、自分の事は自分で決めたらいいんじゃないかな。赤ん坊を扱うみたいに1から10までこれに従っとけばいいんだというのは、プログラマとしてまともに扱われてないんじゃないかと思います。私はそう扱われなくないし、だからこそ、他の人に対してもそういう扱いをしたくないと考えています。
> 
> 角 : なるほど。
> まつもと : ただ、ツールの支援で色々面倒くさいことが減るという明確な理由があれば、それでチェックすればいいしそれに従えばいいんです。

( https://blog-ja.sideci.com/entry/2018/03/02/120636 より)

やっぱりそうですよねー、というまつもとさんらしいご意見です。

とはいえ、最近は最後にあるような、「ツールの支援で色々面倒くさいことが減るという明確な理由があれば、それでチェックすればいいしそれに従えばいい」というところが強く受け入れられているのか、積極的に規約を作ったり、オートフォーマッターを導入していたりしている傾向があります。

例えばPythonは、PEP 8で<del>言語の</del>Pythonのスタンダードライブラリにおける標準的なスタイルを定義しています。

* PEP 8 -- Style Guide for Python Code　(https://www.python.org/dev/peps/pep-0008/)
  * (日本語訳) https://pep8-ja.readthedocs.io/ja/latest/

Goは標準のフォーマッター`gofmt`を提供しています。

* Command gofmt　(https://golang.org/cmd/gofmt/)

またJavaScriptではJavaScript Standard Styleが作られたり、またprettierが良く使われているように見受けられます。

* JavaScript Standard Style (https://standardjs.com/)
* Prettier · Opinionated Code Formatter (https://prettier.io/)

Rubyにもこういうのがあると良いよね、ていうかなんでないの？　という意見が出てきても不思議ではありません。

Rubyで広く導入されているツールと言えば、上記インタビューでも触れられている通り、[RuboCop](https://github.com/rubocop-hq/rubocop)である、という見解は大方の賛同を得られるのではないでしょうか。一方で、RuboCopの特徴として挙げられるのはそのカスタマイズ性であり、多くの場合はそれなりのカスタマイズを施した上で使われているように思います。それはそれで重宝する反面、もうちょっと手頃で、そのまま使えるフォーマッタがあると良いのでは…？　という気持ちもあります。

そんなあなたにご紹介したいのが、この[Standard gem](https://github.com/testdouble/standard)です。

# Standard gemとは

[Standard](https://github.com/testdouble/standard)はRubyConf 2018のLightening Talksで紹介されていたものです（私のはこの発表で初めて知りました）。

LTの動画は公式リポジトリからもリンクされているので拝見できます。

[![Standard Ruby Style Guide - RubyConf 2018](http://img.youtube.com/vi/uLyV5hOqGQ8/0.jpg)](http://www.youtube.com/watch?v=uLyV5hOqGQ8)
Standard Ruby Style Guide - RubyConf 2018　(https://www.youtube.com/watch?v=uLyV5hOqGQ8)

作者はJustin Sealsです。Justinはオハイオ洲在住の関西人（以前滋賀に住んでいたことがあったと聞いています）の方で、[RubyKaigi 2016のキーノートスピーカー](http://rubykaigi.org/2016/presentations/searls.html)だったので覚えている方もいるかと思います。誰も知らない謎の人が提案したわけではありません。

コードを見ても、試しに実行してみても分かる通り、実装としてはRuboCopを使ったものです。`standard --help`を実行すると「`Usage: rubocop [options] [file1, file2, ...]`」と出てくるくらいにrubocopです（と思ったら最新版では出なくなってました）。rubocopとは違うStandardの特徴は、READMEによれば以下の3点です。

* **No configuration.** 設定なしでそのまま使う前提です（実際には対象外のディレクトリ指定等はできます）。
* **Automatically format code.** `standardrb --fix`で自動的に修正されます。
* **Catch style issues & programmer errors early.** 貴重なコードレビューのコストを減らして、レビュアーとコントリビューターとのやりとりを減らすためのものです。

……いやまあそうは言っても元はRuboCopなんだし、と思わないでもないですが、結局大きく違うのはデフォルトのcopの設定ということになります。

Standardで採用しているスタイルは以下になります。

* **インデントは2 spaces** 
* **文字列リテラルは原則`"`**
* **Hashは1.9以降の書き方`{hash: syntax}`**
* **ブロックは、戻り値を使う関数的ブロックは`{…}`、 副作用のある手続き的ブロックは`do…end`**
* **複数行のメソッドチェーンは行末に`.`を使う**

そんなに意外性はないですが、納得しない人は納得しなさそうというか、いかにも[バイク小屋](https://ja.wikipedia.org/wiki/%E3%83%91%E3%83%BC%E3%82%AD%E3%83%B3%E3%82%BD%E3%83%B3%E3%81%AE%E5%87%A1%E4%BF%97%E6%B3%95%E5%89%87)なところではあります。個人的にはブロックのスタイルはちょっと引っかかります（1行は`{...}`で複数行は`do..end`派）が、絶対に許せないというほどではありません。

## 使い方

`gem install standard`でインストールした後は、好きなレポジトリのrootディレクトリで、

```shell-session
standardrb --fix
```

と実行するだけです。もちろん、Gemfileに`gem "standard"`をつけて、`bundle exec standardrb --fix`でもOKです。`--fix`をつけなければ、警告のみが出力されます。

ちなみに現状では、警告の出力の最後に、

```
Notice: Disagree with these rules? While StandardRB is pre-1.0.0, feel free to submit suggestions to:
  https://github.com/testdouble/standard/issues/new
```
と表示されます。そういうことです。

で、どのくらいの警告が出るかですが、試しにsinatraで実行してみると以下のようになりました。

```
$ standardrb | wc
    8355  117083 1220614
$ standardrb --fix >/dev/null
$ git diff | wc
   25082   98534  821837
```

ざっとdiffを見たところ、`'`→`"`の修正が一番多く、次に多いのがHashキーの記法（hash rocket）の変更でした。


## 終わりに

以上、Standard gemについて紹介してきましたが、この記事は現時点ではStandardの積極導入を求めるものではありません。

最初に引用したように、まつもとさんがコーディングスタイル標準を決めようとしていない以上、Rubyの公式スタイルが用意されることはしばらくはないでしょう。なので、コミュニティによる（強制力のない）デファクトスタンダードができるかどうか、できたとしてどういうものになるか、どの程度（あなたにとって）うれしいものになるか、という程度の話です。自分の管理するリポジトリのスタイルについてはこれからも自分の好きな通りに設定できるでしょう。なので、Rubyのスタイル一般について興味ないのであれば、ここで話は終わります。

ですが、もし興味があるとか、変なのに決まるとうれしくないとか、むしろ積極的に提案したいことがあるという場合は、お早めに https://github.com/testdouble/standard/issues にissueを立てるなりpull requestを送るなりしてみると良いのではないか、というのがこの場を借りてお伝えしたかったことです。

一度決まってしまった後だとなかなか意見が通らない可能性もあるわけで（そうじゃないと決めた意味がない）、今が良い機会かと思います。ご健闘をお祈りします。

## 追記

この記事を書くために[qiitaのコーディング規約タグ](https://qiita.com/tags/%E3%82%B3%E3%83%BC%E3%83%87%E3%82%A3%E3%83%B3%E3%82%B0%E8%A6%8F%E7%B4%84)を見ていたら、ちょうど昨日公開された記事がJavaScript Standard Styleの話でした。これについては若干ネガティブな反応も強いようですね。まあJSでセミコロン禁止はバイク小屋議論が捗りそう……と思わないでもありません。

* JavaScript Standard Styleのススメ
 (https://qiita.com/munieru_jp/items/ca16cbfa859468137d2e)

明日は[shugo](https://shugo.net/jit/)さんになります。