目次
Linter
Linterとは
lint(linter)とは、コンピュータプログラムなどのソースコードを読み込んで内容を分析し、問題点を指摘してくれる静的解析ツール。また、そのようなツールで解析を行うこと。ツールを指す場合は "linter" (リンター)と呼ぶこともある。
https://e-words.jp/w/lint.html#:~:text=lint%EF%BC%88linter%EF%BC%89%E3%81%A8%E3%81%AF%E3%80%81,%E3%81%A8%E5%91%BC%E3%81%B6%E3%81%93%E3%81%A8%E3%82%82%E3%81%82%E3%82%8B%E3%80%82
Linterは、ソースコードを実行せずに解析して、潜在的なバグやルール違反を検出する静的解析ツールである。
コンパイラは「文法が壊れていて実行不可能なコード」しか検出できない。一方Linterは「実行はできるが、将来バグになりうるコード」を指摘してくれる。
たとえば以下のコードはPythonとして実行可能だが、問題を含んでいる。
def calculate_total(items):
total = 0
for item in items:
total += item.price
unused_variable = "この変数は使われない" # Linterが検出する
return total
print("ここには到達しない") # Linterが検出する(到達不能コード) Linterはこのような「動くけど怪しい」コードを機械的に見つけてくれる。
- 検出できる問題の例
- 宣言されたが一度も使われていない変数(未使用変数)
- return文の後に書かれた到達不能なコード
- 変数を初期化する前に参照している箇所
- import文の並び順がバラバラ(チームルール違反)
- なぜ使うのか(運用観点)
- 人間のコードレビューでスタイルの指摘をする手間がなくなる。レビューはロジックの議論に集中できる
- CI(後述)に組み込むことで、ルール違反があるコードはそもそもマージできなくなる。チーム全員のコードが自動的に統一される
- 「本番で動かして初めて気づくバグ」を開発段階で潰せる
Python
- pep8 → https://pycodestyle.pycqa.org/en/latest/
- Pythonの公式スタイルガイド
PEP8に準拠しているかをチェックするツール - PEP8は「インデントはスペース4つ」「1行は79文字以内」「import文の順序」などを定めている
- 昔はツール名も
pep8だったがpycodestyleにリネームされた
- Pythonの公式スタイルガイド
- https://pypi.org/project/flake8/
- 3つのチェックツールを1つにまとめたラッパー
-
pyflakes。未使用変数、未定義名の検出 -
pycodestyle。PEP8スタイルのチェック -
mccabe。コードの複雑度(入れ子が深すぎないか等)の計測
-
- プラグインで検査項目を追加できるのが特徴
- 長年Pythonの標準的Linterだったが、後述するruffに置き換わりつつある
- 3つのチェックツールを1つにまとめたラッパー
- https://docs.astral.sh/ruff/
- Rust製の超高速Linter。flake8と比較して10〜100倍高速
- flake8 + isort + pyupgrade など、従来は複数ツールを組み合わせていた機能を1ツールで全てカバーする
- 約800以上のルールを搭載し、ほとんどのPython Linterの機能を代替可能
-
pyproject.toml1ファイルで設定を管理。ツールごとに設定ファイルが散らばらない
[tool.ruff]
target-version = "py312"
line-length = 120
[tool.ruff.lint]
select = [
"E", # pycodestyle errors
"W", # pycodestyle warnings
"F", # pyflakes
"I", # isort(import順序)
"B", # flake8-bugbear(よくあるバグパターン)
"C4", # flake8-comprehensions(内包表記の改善)
"DTZ", # flake8-datetimez(タイムゾーン未指定の検出)
"T20", # flake8-print(print文の検出)
"C90", # mccabe(複雑度)
"UP", # pyupgrade(古い書き方の検出)
"PT", # pytest-style(テストの書き方)
"D", # pydocstyle(docstringの形式)
]
ignore = [
"D100", # Missing docstring in public module
"D104", # Missing docstring in public package
"D105", # Missing docstring in magic method
"D400", # First line should end with a period(日本語に不適)
"D415", # First line should end with a period, question mark, or exclamation point(日本語に不適)
] 使い方
# プロジェクトにruffを追加(開発用依存として)
uv add --dev ruff
# 全ファイルをチェック(問題の報告のみ)
uv run ruff check .
# 自動で直せる問題は直しつつチェック
uv run ruff check . --fix JavaScript / TypeScript
JS/TS用のLinter。歴史的なツールからモダンな統合ツール、新興ツールの順。
- https://eslint.org/
- 事実上の標準
- プラグインで好きにルールを足せる(TypeScript / React / a11y 等)
- 設定は
eslint.config.js(Flat Config)で管理
- https://biomejs.dev/ja/
- Rust製のall-in-one(Lint + Format + Import整列を1ツールでカバー)
- ESLint + Prettier を置き換える流れ
- 設定は
biome.json1ファイル
- https://oxc.rs/
- Rust製の爆速Linter。Biomeよりさらに高速
- ESLint互換ルールを実装中
- ruff / Biome / Oxc という「Rust製linter/formatterの波」の最前線
Formatter
Formatterとは
フォーマッター(formatter)とは、整形や区画付けといった意味を持つ「フォーマット」(format)操作を行うためのソフトウェアや機能などのこと。
https://e-words.jp/w/%E3%83%95%E3%82%A9%E3%83%BC%E3%83%9E%E3%83%83%E3%82%BF%E3%83%BC.html
Formatterは、コードの意味を変えずに見た目(スタイル)を自動で統一するツールである。
Linterとの違いを整理すると以下の通り。
- Linter → 「このコードにはバグがあるかもしれない」と指摘する(修正は人間がやる)
- Formatter → 「このコードの見た目を統一する」と自動で書き換える(ロジックは変えない)
たとえば以下の2つのコードは動作が全く同じだが、見た目が異なる。
# 整形前(人によってバラバラ)
def greet( name:str,age :int)->str:
return f"Hello {name}, you are {age} years old"
# 整形後(Formatterが自動で揃える)
def greet(name: str, age: int) -> str:
return f"Hello {name}, you are {age} years old" - 整形される内容の例
- スペースの位置(
name:str→name: str) - インデントの深さ、改行位置
- クォートの統一(
'or") - 一行の最大文字数を超えた場合の自動折り返し
- 末尾カンマの追加・削除
- スペースの位置(
- なぜ使うのか(運用観点)
- 「タブ vs スペース」「シングルクォート vs ダブルクォート」というスタイル論争が消滅する。チームで議論する時間がゼロになる
- git diff にスタイル変更が混ざらなくなる。レビュー時に「ロジックの変更だけ」が見えるようになる
- ファイル保存時やCI上で自動実行すれば、開発者が意識しなくても常にコードが整っている状態を維持できる
Python
- https://pypi.org/project/autopep8/
- PEP 8 違反を自動修正するツール
- 修正範囲が限定的で、現在では Black や Ruff に置き換えられている
- https://black.readthedocs.io/en/stable/
- 「意見の強いフォーマッター(opinionated formatter)」として登場
- 設定オプションをあえて極端に絞ることで、「どう整形するか」の議論自体を排除する設計思想
- 「Black に従う or 従わない」の二択。チームで揉めることがなくなる
- Python公式(PSF)も採用しており、事実上の標準だった
- https://docs.astral.sh/ruff/
- Linterとして紹介したruffがフォーマット機能も搭載している
- Black と99%以上互換の整形結果を出力するため、Blackからの乗り換えがスムーズ
- Lint + Format を1ツールで完結できるのが最大の利点
- 設定も
pyproject.tomlに集約される
[tool.ruff.format] quote-style = "double" indent-style = "space" line-ending = "auto"
使い方
pip install ruff
# 全ファイルを整形する(実際に書き換わる)
uv run ruff format .
# 整形が必要なファイルがないかチェックのみ(CIで使う)
uv run ruff format --check . JavaScript / TypeScript
JS/TS用のFormatter。Linterと同じく歴史的なツールからモダンな統合ツール、新興ツールの順。
- https://prettier.io/
- 事実上の標準
- 設定は
.prettierrcで最低限だけ書く
- https://biomejs.dev/ja/
- Linterとして紹介したBiomeがフォーマット機能も搭載
- Prettier互換の整形結果
- Lint + Format を1ツールで完結できるのが強み
- https://oxc.rs/docs/guide/usage/formatter.html
- Oxc プロジェクト発のRust製formatter。Prettier比30倍・Biome比2〜3倍速い
- Prettier互換を狙うが現状はBeta(2026/5時点)
- Oxlintと統合される方向。本番採用はまだ早い
型チェッカー
なぜ型チェッカーが必要なのか
Pythonは「動的型付け言語」なので、型を書かなくてもコードは動く。しかしチーム開発や長期運用では以下のような問題が起きる。
def get_user_name(user):
return user.name # userに何が来るのか、コードを読むだけではわからない
# 半年後、別の開発者がこう呼んでしまう
result = get_user_name(None) # 実行時にAttributeErrorで落ちる 型アノテーションを書き、型チェッカーで検証することで、実行する前にこの手のバグを検出できる。
from dataclasses import dataclass
@dataclass
class User:
name: str
age: int
def get_user_name(user: User) -> str:
return user.name
result = get_user_name(None) # 型チェッカーがエラーを出す(実行前に検出) Mypy
- Python公式の型チェックツール。最も広く使われている
- 型アノテーション(
def func(x: int) -> str:)を読み取り、矛盾がないかを静的にチェックする - Python自体は型アノテーションを完全に無視する(実行時にはコメントと同じ扱い)ため、型チェッカーがないとアノテーションを書いても意味がない
- チェック項目
機能 説明 関数の引数・戻り値 型アノテーションと実際に渡される値の型が一致しているか クラスの属性 正しい型が使われているか、未定義の属性を参照していないか Union, Optional 複数の型が混在する変数の安全な取り扱いができているか ジェネリクス list[str],dict[str, int]などの型パラメータが正しいかカスタム型エイリアス UserId = NewType("UserId", int)などの型定義が正しく使われているか
使い方
uv add --dev mypy
# プロジェクト全体の型チェック
uv run mypy . パッケージ マネージャ
パッケージマネージャとは
アプリケーションを作るとき、全てをゼロから書くことはない。「HTTPリクエストを送る」「JSONを扱う」「DBに接続する」といった汎用的な処理はライブラリ(パッケージ)として公開されており、それを取り込んで使う。
パッケージマネージャは、これらのライブラリを追加・削除・バージョン管理するためのツールである。
おおまかに2種類に分けられる。
- OSレベル
- OS全体にソフトウェアをインストールする
-
apt(Ubuntu),brew(macOS)など
- プロジェクトレベル
- 特定のプロジェクト内でのみ使うライブラリを管理する
-
npm(JavaScript),cargo(Rust)など - → 今回扱うのはこちら
参考:https://www.hitachi-solutions.co.jp/sbom/blog/2023033101/
主な機能
- インストール・アンインストール
- コマンド1つでライブラリを追加・削除できる
- バージョン固定(ロックファイル)
- チーム全員が「同じバージョン」のライブラリを使うことを保証する。「自分の環境では動くのに本番で動かない」を防ぐ
- 依存関係の自動解決
- ライブラリAがライブラリBを必要とし、BがCを必要とする…という連鎖を自動で追跡・解決してくれる
Python
poetry
- Pythonの依存関係管理とパッケージングを統合的に行うツール
- 社内での使用事例が多い
-
pyproject.toml(直接使いたいパッケージ)とpoetry.lock(全依存の正確なバージョン)の2ファイルで管理する-
poetry.lockをGitにコミットすることで、チーム全員・CI・本番環境が同一のライブラリバージョンを使う
-
- 導入方法
# インストール(pipx経由が公式推奨) pipx install poetry # パッケージ追加 poetry add package-name # 開発用パッケージ追加(本番には含めない) poetry add --group dev pytest ruff
uv
- Rust製の高速パッケージマネージャ。ruffと同じAstral社が開発している
- poetryと比較して依存解決・インストールが10〜100倍高速
- Python自体のバージョン管理も行える(
.python-versionファイルで指定) -
pyproject.toml+uv.lockで管理する構造はpoetryと同じ - 新規プロジェクトではuvを使用する
- 導入方法
# インストール(公式推奨) curl -LsSf https://astral.sh/uv/install.sh | sh # または brew install uv # プロジェクト初期化(pyproject.tomlが作られる) uv init # パッケージ追加 uv add fastapi # 開発用依存の追加(本番には含まれない) uv add --dev ruff mypy pytest # 実行(仮想環境を自動で作成・有効化して実行する) uv run python app.py
JavaScript / TypeScript
Node.js環境でのライブラリ(パッケージ)はnpmパッケージという形式になっている。
この使用するパッケージやそのバージョンを管理するもの。
- https://www.npmjs.com/
- Node.jsにデフォルトで付属する
- 機能不足・速度の遅さが目立つ
- https://yarnpkg.com/
- npm代替として開発されたもの
- https://pnpm.io/ja/
- 高速性が売り(pnpm = performant npm)
ランタイム
ChromeのJavaScriptエンジン(v8)を元に、ブラウザ以外でも実行できるようにしたもの。
サーバや開発環境で使う環境は基本これ一択。
代替環境
過去のTech Talk資料
ビルドツール
- https://webpack.js.org/
- 2022年頃までの主流
- 現在は機能開発が終了し、バグ修正のみとなっている
- Next.jsで採用
- https://nextjs.org/docs/app/api-reference/turbopack
- Next.js向けに開発されているRust製のバンドラー
- webpackの後継として開発が進んでいる
- 開発サーバやビルドの高速化が主な目的
- https://ja.vitejs.dev/
- webpack以後の主流
- Next.js以外のほとんどのフレームワークが採用
補足: 開発フローの中での位置づけ
ツールが使われるタイミング
ここまで紹介したツール群は、実際の開発ではどのタイミングで使われるのか。典型的なチーム開発のフローに当てはめると以下のようになる。
- コードを書く
- ファイル保存時にFormatterが自動整形(エディタ設定)
- git commit 前にLinter + 型チェッカーを実行(手動 or pre-commit hook)
- Pull Requestを出す
- CI(GitHub Actions等)がLint / Format / 型チェック / テストを自動実行 → 1つでも失敗したらマージ不可
- コードレビュー(人間はロジックだけを見ればよい)
- マージ → デプロイ
運用上のポイント:
- これらのツールは「開発者の手間を減らす」ためではなく、「チームのコード品質を自動で維持する仕組み」として導入される
- ツールの設定は
pyproject.tomlに集約し、全員が同じルールで開発する - CIで強制することで、「ルールを知らない新メンバー」が入っても品質が下がらない
なぜVSCode拡張だけでなくツール本体を使うのか:
VSCodeにはruffやmypyの拡張機能があり、エディタ上でリアルタイムに指摘を表示してくれる。便利だが、拡張機能だけに頼るのは運用上危険である。
- 個人の環境に依存する
- 拡張の有無・バージョン・設定はメンバーごとに異なる。「Aさんの環境では指摘されるがBさんの環境ではスルーされる」という状態が起きうる
- AIはVSCode拡張を読めない
- AIが書いたコードに対しても適用する場合、CLIで実行することが必須
- 入れ忘れ・無効化を防げない
- 新メンバーが拡張をインストールし忘れたり、指摘がうるさくて無効化しても誰も気づかない
- CIで実行するにはツール本体が必要
- CI(GitHub Actions等)上にVSCodeは存在しない。チームとして品質を担保するには、コマンドラインで実行できるツール本体をCIに組み込み、全員のコードに対して同じチェックを強制する必要がある
用途 使うもの 役割 開発中のリアルタイム指摘 VSCode拡張 書きながらすぐ気づける(補助) チームとしての品質保証 ツール本体(CLI) CIで全員に強制する(本丸)
拡張機能は「早く気づくための補助輪」、ツール本体は「品質を保証するゲート」と捉えるとよい。
