導入
ここまでの9章で、タスク管理アプリは「テストだけを頼りに動くものを積み上げる」というやり方で完成に近づきました。仕上げに入る前に、一度立ち止まって全体を見渡しましょう。バラバラに見えていたEntity・Repository・Service・ViewModel・Viewが、実は1つの一貫した依存の向きのルールでつながっていたことに気づけるはずです。
説明
flowchart LR
subgraph SUP["app.support(何にも依存しない)"]
ID["IdGenerator / Clock(抽象)"]
end
subgraph DOM["app.domain"]
TT["TaskTitle / Priority<br/>(値オブジェクト)"]
TI["TaskItem<br/>(Entity)"]
FAC["TaskFactory"]
end
subgraph REPO["app.repository"]
ITR["TaskRepository(抽象)"]
IMR["InMemoryTaskRepository(実装)"]
end
subgraph SVC["app.service"]
TS["TaskService"]
DTO["TaskDto / TaskMapper"]
end
subgraph VM["app.viewmodel"]
TLV["TaskListViewModel"]
CMD["Command / RelayCommand"]
end
subgraph VIEW["app.view / app(Composition Root)"]
FXML["FXML + Controller"]
MAIN["Main(依存を組み立てる場所)"]
end
FAC --> TI --> TT
TI --> ID
FAC --> ID
IMR -.実装.-> ITR
TS -->|使う| ITR
TS --> DTO
TLV -->|使う| TS
TLV --> CMD
FXML <-->|バインディング| TLV
MAIN -.配線.-> IMR
MAIN -.配線.-> TS
MAIN -.配線.-> TLV
- support(第1章):
IdGenerator・Clock。何にも依存しない、最も外部技術に近い抽象 - Entity/ValueObject(第2章):
TaskItem・TaskTitle・Priority。業務データそのものと、それが必ず守るべきルールを持つ - Factory(第3章):
TaskFactory。生成のルールを1箇所にまとめ、IdGeneratorを注入される - Repository(第4章):
TaskRepository(抽象)とInMemoryTaskRepository(実装)。データの出し入れだけを担当し、業務ルールは持たない - Service(第5章):
TaskService。複数のデータを見比べる業務ルールを担当する - ViewModel(第6章):
TaskListViewModel。画面の状態(newTitle・tasks)と操作(Command)を、JavaFXに依存しない普通のJavaのクラスとして表現する - View(第7章): FXML+Controller。
fx:idとバインディングでViewModelとつながるだけで、ロジックは持たない - DI/Composition Root(第8章): どの実装をどこに注入するかを、アプリ起動時の
Mainでまとめて決める - テスト(第9章): 各層は自分より内側(support/domain寄り)のインターフェースにしか依存しないため、外側をFakeやMockitoのモックに差し替えるだけで高速なテストが書けた
矢印の向きに注目してください。どの層も、自分より業務の核に近い層にしか依存していません。ViewはViewModelを知っていますが、ViewModelはViewの存在を知りません。ServiceはRepositoryのインターフェースを知っていますが、Repositoryの具体的な実装(InMemoryかDBか)は知りません。この「依存の向きを常に核へ集める」という1つのルールが、第1章のパッケージ分割からテストのしやすさまで、コース全体を貫いていました。
まとめ
- support→domain→repository→service→viewmodel→viewは、すべて「自分より内側にしか依存しない」という1つのルールでつながっている
- このルール(依存性逆転)のおかげで、外側(Repository・Service・View)をFakeや別実装に差し替えても、内側のコードは変更不要になる
- 次のレッスンから、この構造を保ったまま新機能を2つ追加する
次回: 「期限切れ強調表示」機能をTDDで追加します。