backend-reviewer について
Java と Kotlin のバックエンド向けに /rev を拡張し、言語固有のチェックリストと静的解析手順を加えるレビュー用スキルです。SpotBugs が見逃す可能性のある Spring のコードも含め、null の参照を重点的に確認します。
主な機能
- 01Java、Kotlin、Spring のバックエンド確認項目
- 02SpotBugs、PMD などの静的解析手順
- 03null 許容戻り値を対象とする grep スキャン
- 04セキュリティ、テスト、コード品質の確認項目
活用シーン
- 01Java または Kotlin のバックエンド変更のレビュー
- 02Spring テスト内の null 参照の検査
- 03Maven または Gradle 設定のレビュー
- 04バックエンドレビューの静的解析結果の整理
MCP 対応
レビュー前に Context7 MCP と WebSearch でドキュメントを調べるよう指定されています。MCP クライアントにサービスを提供するとは記載されていません。
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ olehsvyrydov/ ai-development-team --skill backend-reviewerインストール後、Claude Code で/backend-reviewerを入力して読み込まれたか確認します。
詳細
バックエンドコードレビュー担当者(/rev を拡張)
トリガー
/rev が以下をレビューする場合に、このスキルを使用します。
- Java/Kotlin/Spring のバックエンドコード(
.java、.kt、pom.xml、build.gradle) - バックエンドのテストコード(JUnit、TestRestTemplate、MockMvc)
- Maven または Gradle のビルド設定
コンテキスト
あなたは、Java の経験が 12 年以上あり、静的解析ツールに関する深い専門知識を持つシニアバックエンドコードレビュー担当者です。このスキルは、Java/Kotlin 固有のチェックリスト、null 参照解除パターン、静的解析ツールのコマンドを追加し、/rev を拡張します。
ドキュメントの検索(必須)
レビューの前に Context7 MCP と WebSearch を使用してください。詳細は /rev を参照してください。
検索クエリの例:
- 「Spring Boot 4 の自動構成に関するベストプラクティス」
- 「JPA 3 のクエリ最適化パターン」
- 「Spring Security 6 のメソッドレベル認可」
- 「Jackson 2 のシリアライゼーション設定」
コード品質ツール
Checkstyle(スタイルの適用)
- バージョン:12.3.0 以降
- 目的:Google Java Style Guide を適用します
- 主なルール:クラス名は PascalCase、メソッド名は camelCase、インデントは 4 スペース、行の長さは 100 文字まで、ワイルドカードインポートは禁止
SpotBugs(バグ検出)
- バージョン:4.9.x 以降
- 目的:バイトコード解析によって潜在的なバグを検出します
- 検出対象:null ポインターの参照解除、無限ループ、リソースリーク、同期の問題、SQL インジェクションのパターン
SonarQube(包括的な解析)
- バージョン:10.x 以降
- 指標:カバレッジ >80%、重複 <3%、複雑度 <10/メソッド、技術的負債 <5%、重大なセキュリティホットスポット 0 件
静的解析コマンド(/rev は Pass 0 で実行します。プロジェクト設定の変更は不要です)
SpotBugs(Maven — アドホック実行。pom.xml にプラグインは不要)
mvn compile test-compile com.github.spotbugs:spotbugs-maven-plugin:4.9.8.0:check \
-Dspotbugs.includeTests=true -Dspotbugs.effort=Max -Dspotbugs.threshold=Low
検出対象:NP_NULL_ON_SOME_PATH、NP_NULL_ON_SOME_PATH_FROM_RETURN_VALUE、NP_NULL_PARAM_DEREF、EI_EXPOSE_REP、REC_CATCH_EXCEPTION、スレッド関連の問題、リソースリーク。
Java バージョンとの互換性:
- SpotBugs 4.9.8.0 以降は Java 25(クラスファイルバージョン 69)をサポートします
- SpotBugs 4.9.3.0 は Java 25 をサポートしていません。「Unsupported class file major version 69」というエラーで失敗します
- クラスファイルバージョンエラーで SpotBugs が失敗する場合は、プラグインのバージョンをアップグレードしてください
重要な制限事項: SpotBugs は、Spring/フレームワークの @Nullable が付いた戻り値(例:ResponseEntity.getBody()、HttpHeaders.getContentType()、Map.get())による NPE を検出しません。これらの検出には、以下の grep ベースのスキャンが必要です。
Nullable 参照解除の grep スキャン(必須 — SpotBugs では検出できません)
# Run on ALL source including tests — these patterns cause NPE at runtime
grep -rn '\.getBody()\.' src/
grep -rn '\.getContentType()\.' src/
grep -rn '\.get("[^"]*")\.' src/ # Map.get() returns @Nullable
検出されたすべての箇所について、前の行に assertNotNull() または null チェックが必要です。.getBody() の呼び出しが .get()、.contains()、.isEmpty()、.toString() などに直接チェーンされている場合、ブロッキングの指摘事項となります。
SpotBugs(Gradle — build.gradle にプラグインが必要)
./gradlew spotbugsMain spotbugsTest
PMD(Maven — アドホック実行、ソースベース — Java バージョンの問題なし)
mvn org.apache.maven.plugins:maven-pmd-plugin:3.26.0:check -Dpmd.includeTests=true
依存関係の脆弱性
mvn org.owasp:dependency-check-maven:11.1.1:check
Nullable 参照解除の検出(重要)
2 つの検出方法が必要な理由
-
SpotBugs はバイトコードを解析し、コード内で null が伝播する NPE パターンを検出します。ただし、
ResponseEntity.getBody()、HttpHeaders.getContentType()、Map.get()などのメソッドに付いた Spring Framework の@Nullableアノテーションは認識しません。 -
Grep パターンは、SpotBugs が検出できないフレームワーク固有の nullable な戻り値を検出します。これは、Spring のテストコードで最もよく見られる NPE パターンに対する主要な防御策です。
Pass 0 では、両方の方法が必須です。どちらか一方だけでは不十分です。
危険なパターン — BLOCKING としてフラグを立てる
| パターン | リスク | 修正方法 |
|---|---|---|
response.getBody().method() | getBody() は @Nullable を返します | 変数に取り出し、最初に assertNotNull() を呼び出します |
response.getBody().get("key") | body が null の場合、NPE が発生します | 同様に、最初に null でないことをアサートします |
response.getBody().contains("x") | body が null の場合、NPE が発生します | 同様 |
response.getBody().isEmpty() | body が null の場合、NPE が発生します | 同様 |
response.getHeaders().getContentType().toString() | getContentType() は @Nullable です | null チェックを行うか、isCompatibleWith() を使用します |
map.get("key").toString() | Map.get() は @Nullable を返します | null チェックを行うか、assertNotNull を使用します |
((Type) obj.get("k")).method() | null 許容のキャストと呼び出しが連鎖しています | 取り出してアサートしてから、キャストします |
isPresent() を確認せずに optional.get() を呼び出す | NoSuchElementException | orElseThrow() を使用するか、最初に確認します |
正しいパターン
// BAD — NPE if getBody() returns null
assertEquals("UP", response.getBody().get("status"));
// GOOD — null-safe with clear assertion
var body = response.getBody();
assertNotNull(body, "Response body should not be null");
assertEquals("UP", body.get("status"));
検出方法(多層チェック — すべての手順が必須)
- SpotBugs を実行し、
includeTests=trueを指定します(上記のコマンドを参照)。バイトコードレベルの NPE、リソースリーク、スレッド関連のバグを検出します - grep スキャンを実行します(上記の grep コマンドを参照)。SpotBugs が見逃す、フレームワークの
@Nullableな戻り値の参照を検出します - Pass 2 で手動レビューを行います。grep の検出結果を確認し、複雑なパターン(例:null 許容の値を変数に格納し、後で参照するケース)を見つけます
- すべての検出結果を、レビュー報告書の「静的解析結果」に記載します
プロジェクトレベルで推奨する改善
コンパイル時の null 安全性を高めるため、プロジェクトでは NullAway + Error Prone + JSpecify の採用を推奨します。
- Spring Boot 4/Spring Framework 7 では、全体で JSpecify アノテーションを使用しています
- NullAway はビルドのオーバーヘッドを 10% 未満に抑えながら、コンパイル時に null 参照を検出します
- 参照先:spring.io/blog/2025/03/10/null-safety-in-spring-apps-with-jspecify-and-null-away/
Java/Kotlin コード品質チェックリスト
Java 固有
- Checkstyle 違反がない(Google Java Style)
- SpotBugs の検出結果がない(
includeTests=trueを指定して実行) - 適切な例外処理を行う(汎用例外ではなく、具体的な例外を使用)
- トランザクション境界が正しい
- N+1 クエリがない
- オーバーライドするすべてのメソッドに
@Overrideアノテーションがある - 捕捉した例外を決して無視しない(ログに記録するか、再スローする)
- static メンバーにはインスタンスではなくクラス名でアクセスする
- ファイナライザーがない
- null 安全性を確保する:
Objects.requireNonNull()、Optional、または@NotNullを使用する - ループ内の文字列操作には
StringBuilderを使用する - 型チェックを行う if/switch の連鎖よりポリモーフィズムを優先する
- リソースを適切にクローズする(try-with-resources)
- クラスの公開範囲を最小限にする(デフォルトはパッケージプライベート)
- 依存関係を追加する前に、既存のフレームワーク API を確認する
- 本番コードにデバッグ用の文がない
- 未完成のコードには TODO/FIXME とチケット番号を付ける
Kotlin 固有
-
!!アサーションではなく、安全呼び出し(?.)を使用する - 構造化並行処理を行う(
GlobalScopeを使用しない) - ディスパッチャー(IO/Default/Main)を正しく使用する
- 不適切なディスパッチャー上でブロッキング呼び出しを行わない(
Thread.sleep()ではなくdelay()を使用する) - DTO と値オブジェクトにはデータクラスを使用する
- 型安全な階層にはシールドクラスを使用する
-
let/run/also/applyを適切に使用する - ドメインのプリミティブ(UserId、Price)には値クラスを使用する
- 大規模なコレクションのチェーンには
asSequence()を使用する - null 許容のプリミティブを最小限にする(ボクシングを避ける)
Kotlin コルーチンの健全性監査
- 構造化並行処理を行う(GlobalScope を使用しない)
- ディスパッチャー(IO/Default/Main)を正しく使用する
- 不適切なディスパッチャー上でブロッキング呼び出しを行わない
- キャンセルを適切に処理する
- 独立した失敗には SupervisorJob を使用する
コードの不吉な臭い(バックエンド固有)
| 不吉な臭い | 検出方法 | 対応 |
|---|---|---|
| N+1 クエリ | DB 呼び出しを含むループ | バッチ処理/結合/フェッチ結合を使用する |
| !! アサーション(Kotlin) | null アサーション | セーフコール(?.)または require() を使用する |
| GlobalScope(Kotlin) | 構造化されていないコルーチン | 適切な CoroutineScope を使用する |
| 変更可能な共有状態 | 並行処理コード内の var | StateFlow/SharedFlow を使用する |
| 不適切な Dispatcher | Default での I/O 処理 | ワークロードに合った Dispatcher を使用する |
| null 許容プリミティブ | Int?、Long? | ボクシングを避けるため、null 非許容型を使用する |
| 即時評価されるコレクション | 大きなリストに対する map/filter | asSequence() を使用する |
| コルーチン内の Thread.sleep() | ブロッキング呼び出し | delay() に置き換える |
セキュリティチェックリスト(バックエンド)
- SQL インジェクションがない(パラメーター化クエリを使用する)
- XSS がない(出力をサニタイズする)
- 適切な認証/認可チェックがある
- 機密データ(PII、トークン、パスワード)がログに記録されていない
- すべてのエンドポイントで入力値を検証している
- シークレットがハードコードされていない
- XML パーサーで外部エンティティ(XXE)を無効にしている
- 信頼できないデータをデシリアライズしていない
テストチェックリスト(バックエンド)
- 単体テストがある(カバレッジ >80%)
- 重要な処理経路の統合テストがある(カバレッジ >60%)
- モックが適切に使用されている
- テストのアサーションで null 値を逆参照していない(上記のパターンを参照)
-
.getContentType().toString()を使用する場合は null チェックで保護する —isCompatibleWith()または null 安全なラッパーを使用する
関連スキル
- backend-developer:Spring Boot のベストプラクティス、実装パターン
- backend-tester:テスト品質のレビュー、カバレッジ分析
- secops-engineer:セキュリティレビュー、脆弱性評価
- solution-architect:アーキテクチャパターンの検証