はじめに
この記事は、Java で自作クラスが 10 個を超えてきた途端に「どこに置いたらよかったっけ?」と混乱し始めた中級者の方を対象にしています。
個人開発や小規模開発では「とりあえず src に放り込めば動く」でも、チーム開発や 6 ヶ月後の自分がメンテナンスするとなると話は別です。
この記事を読むと、クラスを「論理的に配置するための 3 つのルール」と「命名で迷わなくなる 5 パターン」をすぐに実践できるようになります。
さらに、GitHub で公開しているサンプルリポジトリを Eclipse/IntelliJ 両方でインポートして動かしながら、パッケージ分割のイメージを固められます。
前提知識
- Java のクラス・インタフェースの違いを理解している
- Maven もしくは Gradle のプロジェクト構成を一度は触ったことがある
- コマンドラインで
javac/javaが叩ける(サンプル動作確認用)
なぜ「クラス管理」が問題になるのか
Java はファイル名=クラス名の言語であり、 1 ファイルに複数の public クラスを書けません。
そのため「クラスが増える=ファイルが増える=見つけにくくなる」という問題が必ず発生します。
さらに、パッケージ名を適当に付けると
- 同じ用途のクラスが複数のパッケージに散在し、修正時にファイル探しで 5 分ロス
- 名前が被るため FQN(完全限定名)での記述が増え、読みづらいコードに
- デフォルトパッケージに置きっぱなしで、リフレクションやモジュールシステムで制限を受ける
といった「動くけど将来が怖いコード」が量産されます。
ここでは「論理単位でまとめ、命名規約で迷う時間をゼロにする」方法を考えます。
実践:パッケージ分割+命名規約を 30 分で終わらせる
ステップ1:ドメイン別 3 層パッケージを作る
- プロジェクトルートで
mvn archetype:generateからmyappプロジェクトを作成 -
src/main/javaの直下に以下を作成
-com.example.myapp.domain… エンティティ、値オブジェクト
-com.example.myapp.application… ユースケース、サービス
-com.example.myapp.infrastructure… DB アクセス、外部 API ラッパー -
各層の public クラスは「層を跨ぐ参照」を禁止(
Infrastructure → Domainのみ OK とする)
これだけで「どこに置くか」が 90 % 決まります。
ステップ2:クラス名を「接尾辞パターン」で統一
命名で悩む時間を減らすため、以下の 5 接尾辞をルール化します。
| 役割 | 接尾辞例 | 例 |
|---|---|---|
| エンティティ | なし(名詞) | User, Invoice |
| 値オブジェクト | Id, Date |
UserId, ExpiryDate |
| ファクトリ | Factory |
UserFactory |
| リポジトリ実装 | RepositoryImpl |
UserRepositoryImpl |
| インタフェース | なし(上位に) | UserRepository |
これを IDE のファイルテンプレートに登録しておけば、クラス作成時に「どんな接尾辞?」で悩む必要がありません。
ステップ3:プライベート実装は「内部クラス」で隠す
public にするほどでもないヘルパーは、上位クラスの private static class として定義し、同一ファイルに閉じ込めます。
これで「クラス数が増える=必ずしもファイル数が増える」ではなくなり、ファイルリストが見やすくなります。
ハマった点:循環参照エラー
application 層の OrderService が infrastructure 層の UserRepositoryImpl を直接 new していたところ、以下のコンパイルエラーが出ました。
error: package com.example.myapp.infrastructure does not exist
原因は、application の module-info.java で requires infrastructure; を書いていなかったこと。
ただし、クリーンアーキテクチャ的に「application が infrastructure を知ってはいけない」ため、根本解決として UserRepository インタフェースを domain 層に移動し、DI コンテナ(Spring や Dagger)で実装クラスを注入するようにしました。
解決策
- インタフェースを
domain層に移動 application側はインタフェースのみに依存- 実装クラスは
infrastructure層に残し、DI 設定クラス(AppConfig)で結びつける
これで「コンパイルエラー」+「依存の向き」が同時に解決します。
まとめ
本記事では、Java で自作クラスが増えたときの「配置戦略」と「命名で迷わないルール」を紹介しました。
- ドメイン別 3 層パッケージで「どこに置くか」を 90 % 自動化
- 接尾辞パターンで「どんな名前にするか」を即決
- 内部クラス & DI でファイル数と依存方向を整理
この記事を通して、クラスが 100 個を超えても「ファイル探し 5 分」が「即発見 5 秒」になるメリットを実感できるでしょう。
次回は、これらのパッケージを JPMS(Java Platform Module System)でモジュール化し、マルチモジュームビルド(Maven もしくは Gradle)を高速化する方法を紹介します。
参考資料
- Oracle 公式: Java パッケージの命名規約
- Clean Architecture 動画 日本語字幕
myappサンプルリポジトリ(MIT ライセンス)
https://github.com/Kousukei/java-package-sample
