はじめに
プロジェクトの .eslintrc.json を開いたら、no-restricted-imports というルールで特定のimportが禁止されていました。認証チェックが自動で行われない関数を直接使わせないようにする設定で、overrides で基盤ファイルだけ例外的に許可している、という構成です。
正直、最初は何をしているのかよくわからなかったんですよね。
仕組みを調べればすぐわかるんでしょうけど、ふと思ったのは 「そもそもなぜLintでimportを禁止するんだろう?」 ということでした。コードレビューで指摘すればよくない?と。
この記事では、仕組みではなく 設計思想 の方を掘り下げてみます。
仮説
最初に自分の頭だけで考えた仮説はこうでした。
セキュリティ的に危ないモジュールを使うことを避けるため。
抽象化すると、何らかのベストプラクティスではないものの使用を避けるため?
Lintでやる理由:機械的に防げるリスクを除去するため?
根拠は設定ファイルのエラーメッセージに認証に関する注意が書いてあったこと。セキュリティ系の話だろうな、と。なんとなくそうだろうという感覚で、自信があったわけではないです。
検証:Lintで防ぐのに「向いている問題」と「向いていない問題」
仕組みをコードで動かす検証ではなく、思考実験 をしてみました。5つのケースを「Lintで防ぐのに向いているか?」で分類します。
| # | ケース | 自分の判定 |
|---|---|---|
| 1 | 認証チェックなしの関数を誤って使う | 向いている |
| 2 | APIのレスポンス設計がRESTの慣習に沿っていない | 向いている |
| 3 | 本番に console.log が残る |
向いている |
| 4 | 変数名が意味不明で可読性が低い | 向いていない |
| 5 | 非推奨ライブラリをimportしている | 向いている |
最初は5問中4問を「向いている」にしたんですが、2番で引っかかりました。
「RESTの慣習を定義して、外れていたら防げるでしょ」と思ったんですよね。でも考えてみると、DELETEエンドポイントが204を返すべきか200を返すべきか——これをESLintのルールとしてどう書く?コードのどこをパターンマッチすればいい?
書けないんですよね。 慣習は人やチームによって微妙に違うし、コードの構文だけでは判断できない。
ここで、4番を「向いていない」と判断した時の自分の理由と同じだと気づきました。「基準がない」から向いていない。
境界線が見えた
向いているものと向いていないものを並べ直すと、こうなりました。
-
向いている: 特定importの禁止、
console.logの検出、非推奨ライブラリの検出 - 向いていない: 変数名の意味、RESTの慣習
共通点を言語化すると——
- 向いている: ルールとして明確に定義できる
- 向いていない: 人によって判断が変わり、ルールとして定義できない
最初の仮説「機械的に防げるリスク」の正体が見えました。「ルールとして明確に定義できるかどうか」 が境界線だったんですね。
学び:なぜコードレビューではなくLintなのか
ここまでで「どんな問題がLint向きか」はわかりました。でも、ルールが定義できる問題でも、コードレビューで人間が指摘すればいいのでは?
この問いに対して、最初は「見落としが起こるから」と答えたんですが、それだけだとレビュアーを2人にすればいい話です。
決定的な違いは フィードバックのタイミング でした。
| Lint | コードレビュー | |
|---|---|---|
| いつ | コードを書いた瞬間〜コミット前 | PR出した後、レビュアーが見た時 |
| 誰が | 機械(100%検出) | 人間(見落としあり) |
| 修正コスト | その場で直す(数秒) | コンテキストを思い出して修正(数分〜数時間) |
Lintはエディタ上でリアルタイムに赤線を出す。PRを出して、レビュアーの時間を待って、指摘を受けて、修正して、再レビュー……この往復が丸ごと消えるんですよね。
つまり「機械的に防げる」の意味は 2つの軸 に分解できました。
- 定義可能性: ルールとして書けるか
- タイミング: 書いた瞬間にフィードバックが返るか
おまけ:AIコードレビューがあればLintは不要になる?
検証中に「AIによるコードレビューをローカルで実行できるようになったら、Lintの利点は減るのでは?」という問いが浮かびました。
結論としては、代替ではなく守備範囲が違う んですよね。
| ルールで定義可能な問題 | 文脈や判断が必要な問題 | |
|---|---|---|
| Lint | 得意(100%検出) | 無理 |
| AIレビュー | できるが過剰 | 得意 |
Lintは「このimportは禁止」と決めたら例外なく100%検出する。AIは「たぶんダメだと思います」になりうる。一方で、変数名の意味やRESTの慣習のような、Lintでは扱えない問題はAIレビューの守備範囲です。
使い分けるのが正解で、ルールで定義可能なものはLintで確実にブロックし、文脈が必要なものはAIレビューに任せるのが良さそうです。
まとめ
- Lintで防ぐべき問題 = ルールとして明確に定義でき、違反すると確実に問題になるもの
- Lintの優位性 = フィードバックが即座 + 検出率100%。コードレビューの往復コストを消せる
- プロジェクト独自ルールの追加タイミング = コードレビューで同じ指摘が2回出たら、Lintルール化を検討する
- LintとAIレビューは代替ではなく、守備範囲が異なる
最初は「ESLintの設定ファイルが読めない」から始まったんですが、仕組みではなく「なぜ」から考えたことで、どのプロジェクトでも使える判断基準が手に入りました。