Spring Bootアーキテクチャ ベストプラクティス

2017/04/12

Spring Bootアーキテクチャ ベストプラクティス

Spring Bootアーキテクチャ ベストプラクティスのついて記述する。

Spring io document

柔軟に機能の追加や修正をしたい

開発チームで柔軟(機能追加・修正・運用がしやすい)なソフトウェアを開発するためにはどのような構造が良いか?
チームメンバーのスキルセットにも依存せずに、なるべく開発しやすいようなアーキテクチャを思考する。

前提
- アーキテクチャに正解はない。
- ドメイン駆動設計を意識する。

パッケージアーキテクチャ

わかりやすくするために構成を図で示す。



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
Architecture
├── main
│   ├── java
│   │   └── com
│   │   └── bestpractice
│   │   └── api
│   │   ├── App.java
│   │   ├── common
│   │   │   ├── config
│   │   │   ├── filter
│   │   │   ├── property
│   │   │   └── util
│   │   │
│   │   ├── controller
│   │   │   ├── Advice.java
│   │   │   ├── v1
│   │   │   └── v2
│   │   │
│   │   ├── domain
│   │   │   ├── entity
│   │   │   ├── model
│   │   │   ├── repository
│   │   │   └── service
│   │   │
│   │   ├── exception
│   │   │
│ │ └── security
│ │ ├── filter
│ │ └── role
│   │
│   └── resources
│   ├── application-dev.yml
│   └── application-local.yml
└── test
├── java
│   └── com
│   └── bestpractice
│   └── api
│   ├── AppTests.java
│ │
│   ├── common
│ │
│   ├── controller
│   │
│   └── domain
   │      ├── entity
    │      ├── model
│ ├── service
   │      └── repository
   │     

└── resources
└── application-test.yml
  • controllerパッケージ

    • v1 - バージョン1のAPIを実装
    • v2 - バージョン2のAPIを実装
      @RestControllerを実装する。
      APIエンドポイントやHttpMethodを定義し、バージョンは適宜増やせるような構成にしておく。
  • domainパッケージ

    • entity - Entityクラス
      • データベースに関連するテーブル構造を扱う。
    • model - Modelクラス
      • メモリに保持したいデータ構造を扱う。
    • repository - データベースを扱うCURDクラス
      • データベースにアクセスして、結果を返却する。
    • service - ロジックを持つServiceクラス。
      • repositoryやEntity、modelを扱ってロジックを持つ。
  • common

    • config - Beanクラス
      • 独自@Beanクラスを保持する
    • property - Propertyクラス
      • Springの@Configurationをクラスを保持する。
    • util - Utilクラス
      • staticメソッドを保持し、共通して利用する計算処理を行う。
    • enum - Enum
      • entityにmodelに依存しない場合のenum。依存している場合は、インナークラスで定義し管理しやすくする。
  • exception

    • exception - エラーハンドリングクラス
      • @ControllerAdviceで利用する独自Exceptionクラス。
      • 独自なライブラリのExceptionクラス。
  • security

    • role - Roleクラス
      • Spring Security等でauthorityをコントロールする。
    • filter - Filterクラス
      • Spring PreAuthenticatedProcessingFilterの処理を行う。
  • task

    • task - Spring Sheduleクラス
      • Cronジョブの定期処理をする。

controllerについて

controllerパッケージは、domain内の@Component、@ServiceのBeanをInjectする。
controllerパッケージは@Controller、@RestControllerのクラスを格納する。
throwされてきた例外クラスを想定した構成にしておく。
Unitテストも同様にして、実装。

domainについて

domainパッケージは、domain内の@RepositoryクラスをInjectする。
propertyクラスもケースbyケースでInjectする可能性は十分にある。
また、例外のcatch処理をなるべく厳密に行う。
Unitテストも同様にして、実装。

commonについて

BeanクラスやPropertyやEnumを保持する。
BeanクラスやPropertyでない場合は、staticなアクセス制御にする。
Unitテストも同様にして、実装。

exceptionについて

例外クラス。
APIでSpring Bootを利用する場合は、APIエラーレスポンスクラスを定義する。APIであってもエラーレスポンス以外の例外クラスを定義したい場合にも、このパッケージで細かく実装していく。
Unitテストも同様にして、実装。

taskついて

Schedule処理するクラス。
Unitテストも同様にして、実装。

DIコンテナのアーキテクチャ

構成図。



Spring Bootでソフトウェア開発するときのDIコンテナのアーキテクチャを思考した。
パッケージ構成でもある程度DIコンテナの依存も想定できるかもしれないが、DIコンテナの思想も整理しておきたい。

@Controllerや@RestControllerは@ServiceクラスをInjectする。
@Serviceは@Componentや@RepositoryをInjectする。

また、独自実装したFactoryクラスやSingletonクラスがある場合は、@Component内でインスタンス生成を行いたい。
@Service側はあくまで@Componentを利用するだけにすることで、Unitテストも書きやすくなると考えられる。