さいどうにっき

趣味や日常などを不定期で書いていきます

面倒なことはlinterにやらせよう

OB枠のコーヤ・ロードアゲイン(@ringoh72)です。

昨日のアドベントカレンダーはかかおくんでした。 軽く探したけどリンク見つからなかったのでそのうち貼ります。 // FIXME: ここに後で埋め込む

お前誰?

情報システム工学科10期生、OB枠のコーヤ・ロードアゲイン(@ringoh72)です。本名です。 りんぱんまんの兄を20年ほどしています。 10期生では一番後輩に構ってもらっていた人です。

5年のときに構ってもらっていた14期生もついに3年生、弟に至ってはもう卒業する学年だということを思い出し、時の流れの速さを実感しています。

卒業してからは、東京で色々なオタクをやる傍らエンジニアとして働いています。

最近にじさんじのライブに行ったらアリーナの真ん中前列でした。死んで蘇りました。

ところで主に2人ほどオタクにアドバイスしたのですが、東京23区ほどオタクをやるのに適した地域はありません。

  1. コミケの開催地である東京ビッグサイト、オタク街の秋葉原や池袋、どちらにもアクセスが容易です。
  2. TOKYO MXが映ります。リアタイできないことに怯える生活はもう来ません。
  3. Twitterでトレンド入りする「設営完了」を見てから準備して買いに行けます。
  4. 電車や飛行機へのアクセスも良く、気軽に遠征できます。

閑話休題

今回はlinterで楽しようぜという話をします

はじめに

在学中、こんなコードをとあるテストの解答でよく目にしました。 僕はこのテスト受けてませんけど。

for(i=0;i<10;i++){
    printf("%d\n",i);
}

往々にしてこういったコードは「空白が足りない」という攻撃を受けてあえなく減点されてしまいますが、これはテストという取り返しのつかない場だからこそ起こってしまう問題です。

実際のコードだと、(時間や能力の都合はありますが)理論上は100点を取るまでコンティニューできますよね。 とはいえ自分で直したりそれを意識したコードを書くのって面倒です。あなたもそう思いませんか?

ところで今の時代にはlinterという便利なものがあり、小手先のコードスタイル程度なら勝手に100点を取らせてくれます。 いやはや良い時代に生まれたものです。

ツールに頼るのが甘えという考え方は石を叩いて武器を作っていた時代に置いていきます。 今は洗濯板と桶ではなく、全自動洗濯機を使う時代です。 面倒なことはlinterにやらせよう。

linterとはなんぞや

あえて語弊を恐れずに言うと 「AIってやつでコードを良くしてくれるツール」 です。

とはいえいわゆる ましんらあにんぐ ではありません。 あいつらただのマクロでもAIって言うし

もうちょっと踏み込んだ話をすると、 「コードを静的解析*1して、ルール違反の箇所を検知・修正*2するツール」 です。 先程のコードの場合、空白が足りない箇所を検知して自動で直してくれます。

それだけでなく、「実はこのコード無限ループするんじゃない?」みたいなことも教えてくれます。 例えばこんなコードはアウトです。

char i;
for (i = 0; i < 256; i++) {
    // 255からオーバーフローして0に戻るので無限ループする
    printf("%d\n", i);
}

かしこい。

細かい定義はWikipediaを見てください。

ともかく、linterを使うことで面倒なコードスタイルの指摘から解放されます! だってlinterがやって直してくれるから!

ちなみにここから先は主にJSのlinterであるeslintの話をしますが、よく使われる言語の場合基本的にlinterがあると考えていいと思います。

linterのルールを設定しよう

ルールを設定するのは誰か

linterを使う上で最も忘れてはいけないことが一つあります。

ルールを設定するのは人間である

という点です。

linterにおいて、真逆のルールからどちらかを選ぶことは珍しくありません。

例えばeslintにはsemiというルールがあり、セミコロンの有無を設定できます*3。 この選択肢には「常につける」「常につけない」の両方があるのです。 実際のところセミコロンの有無によって些細な違いはあります*4が、ルールを決めるのはあくまで人間です。

linterはあくまで「ルールに基づいて動く」ツールで、ルールを決めることは人間の責務です。 どのようなルールにするのか、チームのみんな(もしくは俺の中の俺)と話し合って決めてください。

linterおすすめの提供するルールを使おう

なにジョジョ? ルールを決めるのが面倒? ジョジョ、それは全部自力で作ろうとするからだよ。 逆に考えるんだ、「linterに支配されちゃってもいいさ」と考えるんだ。

eslintは全部で294ものルールがあります。 その上モダンなコードを書こうとすると欲しいプラグインが増えて、ルールもどんどん増えていきます。 全部設定するの辛いです。というか無理です。

でも大丈夫! linterには予めルールが設定されていたり、おすすめのルール一覧を提供してくれたりすることが多いです。 要はスターターパックですね。 たとえばeslintは、 eslint:recommended というスターターパックを提供しています。

でも気に入らないルールがあったら? その時は変えてしまえばいいのです。 ルールの変更はあっても構いません。 かのソクラテスが遺した「悪法もまた法なり」という言葉がありますが、今の我々は悪法を変える力があります。

自分たちのルールは自分たちで決められる、なんともデモクラシィを感じさせる良いツールです。 実際のところ「大まかな流れはスターターパックに任せて細部だけ編集する」というのがよくある設定だと思います。

linterを自動実行しよう

さて、ここまでlinterそのものについて書いてきましたが、ここからはちょっと視野を広げます。

linterという革命的なツールを知ってしまった今、commitごと、いえ1タイプごとに実行したくなっている頃だと思います。 しかしホモ・サピエンスというのはサボり癖という致命的な欠陥を抱えていて、「masterにマージするまでlinter実行してない」ということは十分起こりえるのです。 僕はやりました。

というか「面倒なことはlinterにやらせよう」なのに、面倒なlinterの実行を残していては話になりません。 ここでは「システム的に実行させる」こと2つの手段を紹介します。

エディタに実行してもらう

例えば僕はvscodeを主に使っているのですが、vscode-eslintというプラグインには非常に助けられています。 ルール違反の箇所がエディタ上で見えて、どのルールに違反したのかも見ることができます。

f:id:ringoh72:20191225231726p:plain
=の前後に空白がない場合の表示

またセーブすると自動で修正してくれるよう設定しているため、コードスタイルを考えずにコードを書いても保存するだけでキレイになります。

CIで実行する

githubなどへのpushに紐付いてビルドやテストを行える仕組みをCIと言います。 最近だとGitHub ActionsCircleCIが主でしょうか。

これらでlinterを実行することにより、開発者の環境に頼らずに自動実行する仕組みが整います。 CIのステータスをPull Requestと紐付けることで、linterが通るまでマージさせないようにすることも可能です。

理由は後述しますが、CIで実行する場合はルール違反の検知のみに留めて修正させないのが吉です。

どちらが良いのか?

両方やりましょう。

一応CIに編集権限を持たせるとローカルでの修正はいらなくなりますが、本当にやめた方がいいです。 編集権限を与えるのは面倒ですし、コードの編集結果に責任を持つのがcommit authorではなくCIの設定管理者になりますから。 現場猫も草葉の陰で泣いてしまうでしょう。

責任を押し付けたい気持ちはめちゃめちゃよく分かりますが、どうかこらえてください。 何も責任という言葉は悪いことだけでなく、功績も合わせて表裏一体です。 「このキレイなコードを書いたのは自分です」という証明のためにも、commitは自分でしましょう。

3行まとめ

  1. CIはコードルールの警察
  2. ルールを設定するのは人間だけど、膨大過ぎる場合はスターターパックに頼ろう
  3. 人間は実行を忘れる生き物なので、エディタのプラグインやCIを活用して自動実行しよう

おまけ

先輩がいる場所(主に東京)に来たらガンガン先輩にたかりましょう。 どうせ暇なので相手してくれますし、大抵あなた方より稼いでるのでご飯も奢ってくれます。 断られたらおとなしく引いて欲しいけど、多分快諾してくれると思います。多分。

そして卒業したら、今度は快くたかられてくれるといいな、と僕は思っています。

たかられたくない人は…まあ、ごめんね。許して。

*1:コードを実行せずに解析すること

*2:全てのlinterが自動修正を備えているわけではありません、あしからず

*3:JSではセミコロンがあってもなくてもokです

*4:詳しくは「JS セミコロン」とかでググってください