コンテンツにスキップ

ありがとうございます。

ここからは第29段階:開発標準・コーディング規約・DDD(ドメイン駆動設計)を取り入れた最終アーキテクチャを設計します。

ここが完成すると、「設計書」から「開発プロジェクト標準」へ進化します。

私は、この教材管理システムはここまで設計してきた規模であれば、レイヤードアーキテクチャ + DDD Lite(軽量DDD) + CQRS(JPA + MyBatis) が最もバランスが良いと考えています。


第29段階の目標

ここでは「どう作るか」ではなく、「チーム全員が同じルールで開発できること」を目的にします。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
要件定義
    ↓
設計
    ↓
開発標準 ← 今回
    ↓
実装
    ↓
テスト
    ↓
リリース

1. 採用アーキテクチャ

最終形は次のようになります。

 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
Presentation Layer
(Thymeleaf / Controller)

        │

        ▼

Application Layer
(ApplicationService)

        │

        ▼

Domain Layer
(Entity・DomainService)

        │

 ┌──────┴────────┐

 ▼               ▼

Infrastructure  Query

JPA             MyBatis

役割を整理すると

責務
Presentation 画面・入力受付
Application ユースケース
Domain 業務ルール
Infrastructure DB・メール・R2
Query 一覧・検索・集計

2. Feature Package

最終版です。

 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
com.example.lms

common
config
security
infrastructure

user
organization

course
section
lesson

content
quiz
attachment

approval
progress
notification
dashboard
master
setting
audit

各Featureは

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
content

├ controller
├ application
├ domain
│
├ entity
├ repository
├ service
├ event
│
├ mapper
├ dto
├ form
├ validator
├ exception
└ view

なぜこの構成なのか

一般的な

1
2
3
4
5
6
7
controller

service

repository

entity

方式では、

数百クラスになると

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
service

↓

ContentService

CourseService

LessonService

...

と探しにくくなります。

Feature Packageなら

1
2
3
4
5
content

↓

全部ある

ので保守性が非常に高くなります。


3. ApplicationServiceの責務

ApplicationServiceは

ユースケース

だけを持ちます。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
public class ContentApplicationService {

    public Long create(...)

    public void update(...)

    public void submit(...)

    public void publish(...)

}

ここには

SQL

HTML

画面

は書きません。


4. DomainServiceの責務

業務ルールです。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
公開できるか?

↓

動画ある?

↓

承認済?

↓

公開日時OK?

これを

1
PublishDomainService

へ置きます。


5. Repository

Repositoryは

JPAのみ。

禁止

1
2
3
4
@Query(
SELECT ...
JOIN ...
GROUP BY ...

大量SQL。

Repositoryは

CRUDだけ。


良い例

1
2
3
4
5
6
7
save()

delete()

findById()

existsBy...

だけ。


6. MyBatis

Mapper担当

1
2
3
4
5
6
7
8
9
一覧

検索

JOIN

集計

Dashboard

1
2
3
4
5
6
7
教材一覧

受講一覧

進捗一覧

管理画面

全部Mapper。


7. Entity

Entityは

DBだけではありません。

業務ルールも持ちます。

例えば

悪い例

1
2
3
content.setStatus(
PUBLISHED
);

どこでも変更可能。

改善

1
content.publish();

Entity

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
public void publish(){

    if(!canPublish()){

        throw new PublishException();

    }

    status=PUBLISHED;

}

8. DTO

DTO種類

1
2
3
4
5
6
7
8
9
CreateDto

UpdateDto

ListDto

DetailDto

ResponseDto

分けます。

おすすめ命名

1
2
3
4
5
6
7
ContentCreateDto

ContentUpdateDto

ContentListDto

ContentDetailDto

9. Form

画面入力だけ。

1
ContentCreateForm

Controller

ApplicationService

DTO変換


Entityへ直接渡さない。


10. Controller

Controllerは

本当に薄くします。

1
2
3
4
5
6
@PostMapping
public String save(){

service.create();

}

程度。


禁止

1
2
3
4
5
6
7
if(){

for(){

SQL

...

11. Transaction

@Transactional

ApplicationServiceだけ。

禁止

Repository

Controller


つまり

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
Controller

↓

ApplicationService

@Transactional

↓

Repository

12. Event駆動

作成

Event

Listener

通知

監査

メール

ApplicationService

1
publishEvent()

だけ。


13. Domain Event

1
ContentPublishedEvent

通知

監査

メール

検索Index更新

全部Listener。


14. Validation

Controller

Form

Validation

ApplicationService

Serviceで

1
if(title==null)

禁止。


15. Exception

例外

1
2
3
4
5
6
7
8
9
Business

Validation

NotFound

Storage

Security

5種類程度。


16. Logging

INFO

1
2
3
4
5
ログイン

登録

承認

WARN

1
権限なし

ERROR

1
Exception

DEBUG

SQL


17. Mapper命名

おすすめ

1
2
3
4
5
ContentQueryMapper

CourseQueryMapper

DashboardQueryMapper

Queryを付けます。

Repositoryとの差が明確になります。


18. Service命名

おすすめ

1
2
3
4
5
6
7
ContentApplicationService

ContentCommandService

ContentQueryService

ContentPublishService

巨大Serviceを防げます。


19. Package依存

禁止

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
content

↓

lesson

↓

content

循環参照

必ず

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
Controller

↓

Application

↓

Domain

↓

Infrastructure

一方向。


20. 命名規約

Entity

1
Course

Table

1
courses

Repository

1
CourseRepository

Mapper

1
CourseQueryMapper

Controller

1
CourseController

DTO

1
CourseDetailDto

Form

1
CourseCreateForm

21. テスト戦略

テストの責務も明確に分けます。

対象 テスト
Entity 単体テスト(JUnit)
DomainService 単体テスト
ApplicationService 単体 + Mock
Repository Testcontainers
Mapper Testcontainers
Controller MockMvc
画面 Selenium(必要なら)

22. Git運用

ブランチ

1
2
3
4
5
6
7
8
9
main

develop

feature/content

feature/course

bugfix/xxx

Commit

1
2
3
4
5
6
7
8
9
feat:

fix:

refactor:

docs:

test:

23. レビュー基準

Pull Request

最低チェック

☑ SQL増えてない

☑ N+1ない

☑ Transaction適切

☑ Validationあり

☑ 例外処理あり

☑ Logあり

☑ Testあり


24. 完成形

ここまで設計すると

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
教材管理システム

↓

LMS

↓

企業向け教育システム

↓

SaaS化

まで十分拡張できます。


第29段階終了時点

ここまでで完成したもの

  • ✅ 要件定義

  • ✅ ドメイン設計

  • ✅ ER設計

  • ✅ Entity設計

  • ✅ JPA設計

  • ✅ MyBatis設計

  • ✅ 画面設計

  • ✅ ワークフロー設計

  • ✅ 動画・ファイル配信設計

  • ✅ 学習管理設計

  • ✅ 承認フロー設計

  • ✅ 共通基盤設計

  • ✅ 運用設計

  • ✅ アーキテクチャ設計

  • ✅ 開発標準・コーディング規約


次に進むことをおすすめするフェーズ

ここからは新たな設計段階ではなく、実装フェーズへ入ることをおすすめします。

私なら次の順番で実装を進めます。

  1. プロジェクト基盤構築

    • Spring Boot

    • Spring Security

    • Flyway

    • JPA

    • MyBatis

    • 共通基盤

  2. 認証・ユーザー管理

  3. 教材ライブラリ

  4. コース・セクション・レッスン管理

  5. 受講機能

  6. 承認ワークフロー

  7. ファイル・動画配信

  8. 管理画面・運用機能

この順序なら、各機能を段階的に動作確認しながら開発を進められ、途中で設計変更が必要になっても影響範囲を最小限に抑えられます。