浜松のWEBシステム開発・スマートフォンアプリ開発・RTK-GNSS関連の開発はお任せください
株式会社シーポイントラボ
TEL:053-543-9889
営業時間:9:00~18:00(月〜金)
住所:静岡県浜松市中区富塚町1933-1 佐鳴湖パークタウンサウス2F

【JavaScript】バグりやすいコードのコミットを自動で防ぐ

 やることはコミット時に自動で動作するツールであるhusky, lint-stagedとESLintルールにあるベストプラクティス系のルールをエラーレベルで設定することです。
 husky, lint-stagedはhuskyはGitのフックのほぼ全てをpackage.json上で定義できるパッケージです。これをnpm installして十行前後の定義をpackage.jsonに記述するだけでコミット時に自動でESLintを走らせられます。
【Git】package.json上でコマンドとGitを連携させるためのhusky, lint-staged – 株式会社シーポイントラボ | 浜松のシステム開発会社
 ESLintのルールにはインデントの様なコードの整形に関わるルール、非推奨やES6の様な言語バージョンのルールなど色々なカテゴリなルールがあります。その中の一つにベストプラクティス、より良いコーディングのためのルールがあります。
 List of available rules – ESLint – Pluggable JavaScript linter#Best Practices
 ESLint ルール 一覧 (日本語) – galife
 huskyはコミット時の自動実行コマンドでエラーが出力された場合、コミットを停止します。ESLintのルールではエラーレベル、ルールに違反した場合にエラーを出力するレベルが設定可能です。これらを組み合わせてESLintのベストプラクティス系のルールをエラーレベルで設定することによってベストプラクティスに従わないコードのコミットを自動で防ぎます。
 ベストプラクティスルールは上述のESLintルールのドキュメントから探すことができます。どこかしらで任意設定は必要になりますが、すべてを一つ一つ設定していくのはとても辛いです。何かしらの設定を継承することによって設定を始めます。
 自分が良く使うルールベースは天下のgoogle様のルールです。

// .eslintrc.json
// 最小構成
{
  "extends": [
    "eslint:recommended",
    "google"
  ],
  "env": {
    "es6": true
  }
}

 これに従うだけでも何もしていないコードより簡単にしっかりしたコードになるのですが、今回は更にベストプラクティスでコーダーを縛りつけます。ルールの改造のためにも、現在どのようなルールが設定されているか知る必要があります。知るためには次のコマンドが便利です。

eslint --print-config hoge > currentRules.json

 –print-configで対象のファイルにかけるルールを出力します。リダイレクトでファイルにダンプさせます。全体のルールが知りたいので雑に存在しないファイルhogeでも指定すればOKです。
 上記.eslintrc.jsonを出力すると、例えば次の様なルールが設定されていることがわかります。

{
  "rules": {
      "complexity": "off",
  }
}

complexity – Rules – ESLint – Pluggable JavaScript linter
 complexityは循環複雑度、簡単に言えばif文等によるプログラムの分岐の複雑度を表す指標です。これが大きなプログラムは潜在的なバグを含みやすくなります(パターンが多すぎて人間の頭で処理しきれなくなる、テストしきれなくなるなどが理由)。これを防ぐために.eslintrc.jsonにと記述できます。

    "complexity": ["error", 10], // 循環複雑度が10以上の関数はエラー

 このようにすると、複雑なjavascriptファイルをコミットしようとするとストップがかかる様になります。
 例えば、次のコードなら画像の様になります。

function hoge() {
    if (true) {
        if (true) {

        } else if (false) {
            if (true) {

            } else if (false) {

            }
        }
    } else if (false) {
        if (true) {
            if (true) {

            } else if (false) {

            }
        } else if (false) {
            if (true) {

            } else if (false) {

            }
        }
    }
}

  • この記事いいね! (0)