コーディング規約の全体像
コーディング規約は「チーム全体でコードの見た目と書き方を揃えるための約束事」です。読みやすさ、保守性、バグ回避、ツール連携を高めます。Javaでは命名、インデント、改行、波括弧の位置、importの扱い、例外処理、コメント/JavaDocなどを統一するのが基本です。重要なのは「論理は自由、表現は統一」。規約を守るとレビュー効率と学習コストが大幅に下がります。
スタイルの基本(命名・インデント・括弧・改行)
命名規約(クラス・メソッド・変数・定数)
- クラス名: UpperCamelCase(例:OrderService, UserRepository)
- メソッド名/変数名: lowerCamelCase(例:calculateTotal, maxRetryCount)
- 定数: 全大文字+アンダースコア(例:DEFAULT_TIMEOUT_MS, MAX_ITEMS)
- 真偽値: 質問文の接頭辞(例:isActive, hasError, shouldRetry, canSubmit)
public final class OrderService {
private static final int MAX_RETRY = 3;
public boolean hasValidStatus(String status) { ... }
}
Javaインデントと行長
- インデント幅: 4スペース(タブではなくスペース推奨)
- 最大行長: 100〜120桁を目安に折り返し(長すぎる式は分解)
// 長い呼び出しは改行して揃える
var result = client
.withTimeout(Duration.ofSeconds(2))
.withRetry(MAX_RETRY)
.execute(request);
Java波括弧の位置と空白
- 括弧スタイル: メソッド・クラスの開き括弧は改行して同列、制御構文は同行(K&R 系)
- 空白: 演算子の前後、カンマ後に入れる
if (count > 0) {
total += count;
} else {
total += 1;
}
Java空行で意味の塊を分ける
- 意味のまとまり: フィールド宣言、コンストラクタ、公開メソッドの間に1行空けて区切る
import とパッケージ、可視性の指針(重要ポイントの深掘り)
import の扱い
- 個別 import: ワイルドカード(*)は原則避ける(衝突を防ぐ)
- 不要 import: IDEで削除、整形ツールで自動化
import java.util.List; // 個別
// import java.util.*; // 原則避ける
Javaパッケージ構成
- 逆ドメイン+機能: com.example.app.user, com.example.app.order
- 役割分離: model/service/controller/infra など層で分ける
アクセス修飾子の最小化
- 最小公開: 必要最小限だけ public、内部は package-private を活用
- 不変設計: 変更が外へ漏れない境界を保つ
class InternalHelper { /* 同パッケージ内のみ */ }
public class PublicApi { /* 公開 */ }
Java例外処理とエラーハンドリング(重要ポイントの深掘り)
チェック例外と実行時例外の使い分け
- チェック例外: 呼び出し側で回復可能な状況(IO, SQL)
- 実行時例外: バグや契約違反(IllegalArgumentException, IllegalStateException)
public void load(Path p) throws IOException {
try (var br = Files.newBufferedReader(p)) { ... }
}
Javaメッセージと原因例外の連鎖
- 原因の保持: new XxxException(“説明”, cause) でラップ
- メッセージの具体化: 入力値・状態・期待値を含める
try {
service.process(req);
} catch (SQLException e) {
throw new IllegalStateException("DB処理失敗: reqId=" + req.id(), e);
}
Java早期 return とガード節
- 前提違反は早期に弾く: requireNonNull、範囲チェックで分岐を浅く
Objects.requireNonNull(name, "name must not be null");
if (name.isBlank()) return;
Javaコメントと JavaDoc、テスト可能性のための設計
コメント/JavaDocの方針
- 「なぜ」を書く: コードが語る「何」を繰り返さない
- JavaDoc: 公開メソッドは契約(前提・戻り値・例外)を明記
/**
* 税込金額を計算する。
* @param subtotal 税抜金額(0以上)
* @param taxRate 税率(0〜1)
* @return 税込金額
*/
public int taxed(int subtotal, double taxRate) { ... }
Javaテストしやすさを規約で担保
- 副作用の分離: 計算ロジックとI/Oを分ける
- 小さなメソッド: 1つの責務、短い引数リスト
int calcTaxed(int price, double rate) { ... } // 純粋関数に近くする
Javaクラス設計と不変性、equals/hashCode/toString
不変オブジェクトの推奨
- final フィールド: コンストラクタで初期化、セッター不要
- レコード活用: Java 16+ の record で不変値オブジェクトを簡潔に
public record User(String id, String name) { }
Javaequals/hashCode の一貫性
- 契約に基づき実装: 同値なら同じ hashCode
- **IDE生成/Objects.equals/Objects.hash を使用
@Override public boolean equals(Object o) { ... }
@Override public int hashCode() { return Objects.hash(id, name); }
JavatoString はデバッグに有用
- 短く要点: 主要フィールドのみ、機密情報は含めない
@Override public String toString() { return "User{id=" + id + ", name=" + name + "}"; }
Javaログ、フォーマット、定数・列挙の扱い(重要ポイントの深掘り)
ログの書き方
- レベル選択: info=業務進捗、warn=要注意、error=失敗、debug=詳細
- 構造化: キー=値で出力、後で検索しやすく
logger.info("order_created id={} user={}", orderId, userId);
Javaフォーマットと国際化
- 書式化: String.format / printf を使用、小数/桁区切りは Locale 指定
- 日時: DateTimeFormatter(ISO かロケール適合)
var s = String.format(Locale.JAPAN, "%,d円", 1234567);
Java定数と enum
- 魔法の数値を排除: static final へ
- 区分値は enum: 安全な型で表現
public enum Status { NEW, PROCESSING, DONE }
Java自動整形と静的解析、チーム運用
ツールを前提にした規約
- フォーマッタ: Spotless/Google Java Format/IDEのCode Styleで自動整形
- Lint: Checkstyle, PMD, Error Prone で規約違反やバグの芽を検出
PR レビューの役割分担
- 形式はツールに任せる: レビューは設計・命名・契約に集中
- 規約の例外は明文化: 性能・互換性のために外れる場合はコメントで理由を残す
例題で身につける
例 1: 規約に沿ったメソッドの形
public final class PriceCalculator {
private static final double TAX_RATE = 0.1;
/**
* 税込金額を返す。
* @param subtotal 税抜金額(0以上)
* @return 税込金額
* @throws IllegalArgumentException 引数が負の場合
*/
public static int calc(int subtotal) {
if (subtotal < 0) throw new IllegalArgumentException("subtotal must be >= 0");
return (int) Math.round(subtotal * (1 + TAX_RATE));
}
}
Java例 2: import と命名を整えたコレクション操作
import java.util.ArrayList;
import java.util.List;
public class Users {
public static List<String> activeUserNames(List<String> userNames) {
List<String> result = new ArrayList<>();
for (String name : userNames) {
if (name != null && !name.isBlank()) result.add(name.trim());
}
return result;
}
}
Java例 3: 例外連鎖とログの一貫性
public class Repository {
private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(Repository.class);
public User find(String id) {
try {
// DBアクセス...
return new User(id, "Sato");
} catch (Exception e) {
log.error("find_failed id={}", id, e);
throw new IllegalStateException("find failed id=" + id, e);
}
}
}
Java仕上げのアドバイス(重要部分のまとめ)
- 命名は「意味・単位・状態」を含め、スタイルは camelCase/定数は大文字スネークに統一。
- インデントは4スペース、行長は100〜120桁目安、括弧と空白は規約どおりに。
- import は個別指定、可視性は最小限、例外は原因を連鎖させメッセージを具体化。
- コメントは「なぜ」を、JavaDocは契約を。テストしやすい純粋なロジックに寄せる。
- 不変設計、equals/hashCode/toStringの一貫性、enumと定数で魔法値を排除。
- 形式はツールで自動化し、レビューは設計と意味へ集中する。
