自分の足を撃たない技術

[Battle Conference U30](https://battleconference-u30.connpass.com/event/49985/) での登壇資料です。

---------


自己紹介
=========

---------




だれこれ
=======


- Masataka Kuwabara(pocke)
- こないだ23歳になりました
- Actcat Inc. Engineer
- Ruby / RuboCop
    - 今日は Ruby での例が多くなります :gem: 
- Twitter: [@p_ck_](https://twitter.com/p_ck_)
- GitHub: [@pocke](https://github.com/pocke)

![minpocke.png](https://qiita-image-store.s3.amazonaws.com/0/33922/e43cbf9e-1df6-4557-6f1f-7e48de09dac8.png)






-----------

普段やってること
======

-----


SideCI
========

https://sideci.com


自動コードレビュー

![2017-03-08-213138_1198x616_scrot.png](https://qiita-image-store.s3.amazonaws.com/0/33922/6aa93532-631f-b613-3e47-3882363fe3d2.png)
![170311124738.png](https://qiita-image-store.s3.amazonaws.com/0/33922/0684a5c5-ab4b-9eee-e7fe-e8c7d6ed1f44.png)



------

Shibart
========


https://shibart.pocke.me

GitHub の芝を Tシャツにする

![1487946652.png](https://qiita-image-store.s3.amazonaws.com/0/33922/f98df526-c100-ebdd-ad89-e611f019096e.png)
![t-shirt.png](https://qiita-image-store.s3.amazonaws.com/0/33922/73b53a83-dc83-d910-ad84-81a11c892a02.png)


-------

本題
======


------


今日のテーマ
=====

- 挑戦
  - 私が挑戦していること
  - かつ、皆さんにも挑戦していただきたいこと

------



私は何に挑戦しているのか
=======

表題は「自分の足を撃たない技術」

- 自分の足を**2度**撃たない技術
- バグを再発させないこと

に挑戦



-----


突然ですが、バグを直す時何をしていますか？
===========

-------

バグを直す時の、よくある光景
========

- バグを直す
- 直っていることを確認するテストを書く
- (余力があれば)注意喚起の為にブログなどで記事を書く



--------


これはバグの再発防止に繋がっているのか？
=======

- テストを書く
    - 該当箇所の正しさは保証される
    - ただし、他の関数内 / 他のプロダクトではまた同じバグを生むかも知れない
- 記事を書く
    - 危ないコード例を広く知らせることが出来る
    - ただし、人間は忘れる生き物
        - また同じ様なバグを産んでしまわないとは限らない


これらの対策のみでは不十分！

--------


そこで Lint ！
========


------


Lint とは
=======


- プログラミング言語の静的解析ツール
- コンパイラ / インタプリタだけではチェックできない、バグの原因となるコードをチェックする


-----

たとえば Ruby での例
======




------------

バグのあるコード
===========

Ruby では Python や算数みたいに `0 < x < 20` のように書くことが出来ない



```rb
# A Ruby program
x = 3

# NoMethodError undefined method `<' for true:TrueClass
if 0 < x < 20
  puts x
end
```

```bash
$ ruby tset.rb
test.rb:5:in `<main>': undefined method `<' for true:TrueClass (NoMethodError)
```


--------


RuboCop を使うと
=====

RuboCop は Ruby 用の Lint


```bash
$ rubocop
Inspecting 1 file
W

Offenses:

test.rb:5:4: W: Use the && operator to compare multiple values.
if 0 < x < 20
   ^^^^^^^^^^

1 file inspected, 1 offenses detected

```

`0 < x < 20` ではなく `0 < x && x < 20` を使用するように指摘してくれる！


------


Lint のメリット
======

- テストと違い、全てのコードに対して適用可能
    - テスト: テスト対象にしか効果がない
    - Lint: テスト対象のコード以外にも、他のプロダクトのコードにも適用可能
- ブログを使用して情報発信した場合と違い、機械的に検査できる
    - ブログ: 人間が覚えてないと意味がない
    - Lint: 機械が検査するので忘れない！(CIを設定するのがオススメ)


---------

ここまでは Lint を使う話
========

-------

Lint を使う から 作る へ
======

- Lint を使うとバグを事前に防ぐことが出来る
    - テスト等とは違いとても広い範囲に有効
- それならば、Lint のルールをみんなで書けばみんなハッピーなのでは！






-------

作ってしまったバグをどんどん Lint のルールにしていこう！
=======

-----


RuboCop のルール(Cop)を書くのは意外と簡単
=============

さっきの `0 < x < 20` を検出する RuboCop のルールの実装は結構短い

```ruby
def_node_matcher :multiple_compare?, <<-PATTERN
  (send (send _ {:< :> :<= :>=} $_) {:< :> :<= :>=} _)
PATTERN
                                                       
def on_send(node)
  return unless multiple_compare?(node)
                                                       
  add_offense(node, :expression)
end
```

https://github.com/bbatsov/rubocop/blob/master/lib/rubocop/cop/lint/multiple_compare.rb


------


実装するための情報も豊富
=======


日本語の情報も充実しています

- [RuboCop の Cop の実装について](http://qiita.com/pocke/items/1ac1fbabb861f08c96e2)
- [実践!! RuboCopプラグイン開発入門](http://tech.sideci.com/entry/2016/06/09/111926)
- [rubocopでreversibleなmigrationかどうかチェックしたかったので作った](http://sue445.hatenablog.com/entry/2017/01/16/120405)
- 他多数

何かあったら Twitter で [@p_ck_](https://twitter.com/p_ck_) に聞けば :ok_woman: 

------

Feature Request の Issue を作るのもアリ
=======


- 「こういうルールがほしい」「作ろう！:+1:」のような流れもよくある
- 気兼ねなく Issue を建てよう
    - 全世界の他のプログラマが同じバグを作らないため

------

でも RuboCop だけじゃうまくいかない時も…
======

- バグの原因が社内特有で公開するものではない
    - 社内で定義されているメソッド起因とか
- RuboCop に Issue / PR 出すにはハードル高い

-------

そこで Querly！
========

Ruby 用の Lint ツール

[soutaro/querly](https://github.com/soutaro/querly)

- ルールを書くのが簡単
    - YAML で定義出来る
- 使う人がルールを定義出来る
    - ローカルルールについて検査出来る。
        - RuboCop には適さない項目も検査できる！

--------


Querly の例
--------

例えば社内では以下のようなルールを書いています(一部抜粋)。



```yaml
- id: com.sideci.oj
  pattern:
    - JSON.load
    - JSON.dump
  message: Oj を使ってください
- id: com.sideci.shallow_dig
  pattern: "dig(_)"
  before: "task.dig('id')"
  after: "task['id']"
  message: 階層が2以上でなければ、Hash#dig(_)よりもHash#[]を使ってください。
```

-------

Ruby 以外の言語の場合
=======

選択肢は沢山ある

- JavaScript: [ESLint](http://eslint.org/)
    - プラグインが活発な印象
- Golang: [Go Meta Linter](https://github.com/alecthomas/gometalinter)
    - 沢山の Linter の Wrapper
- CSS: [StyleLint](https://github.com/stylelint/stylelint)
- などなど








------


まとめ
=======


- バグを再発させない為に、Lint を整える挑戦をしよう :muscle: 
    - 同じ過ちを繰り返して(自分の|世界中のプログラマの)時間を無駄にしない為に
- Lint を整えるのは難しくない
    - Ruby なら [RuboCop](https://github.com/bbatsov/rubocop) や [Querly](https://github.com/soutaro/querly) がオススメ
    - 他の言語でもよく使われているものを見てみよう


ご清聴ありがとうございました。