本文へスキップ
BecomeCoder

Java MVVMコース · 第1章 MVVMとこのコースの進め方 · レッスン3

プロジェクトを分ける ― domain / repository / service / viewmodel

ローカル実施

導入

MVVMの3層は、Javaではパッケージとして表現します。パッケージを分けることで「この層はこの層しか使わない」という依存の向きが目に見えるようになり、うっかり逆向きに参照するミスに気づけます。

説明

このコースで作るタスク管理アプリは、次の構成になります。

flowchart TB
    APP["app<br/>(Composition Root / main)"]
    VIEW["app.view<br/>(FXML・Controller)"]
    VM["app.viewmodel<br/>(ViewModelBase・TaskListViewModel・Command)"]
    SVC["app.service<br/>(TaskService・TaskDto・TaskMapper)"]
    REPO["app.repository<br/>(TaskRepository・InMemoryTaskRepository)"]
    DOM["app.domain<br/>(TaskItem・TaskTitle・Priority・TaskFactory)"]
    SUP["app.support<br/>(IdGenerator・Clock)"]
    APP --> VIEW
    APP --> VM
    VIEW --> VM
    VM --> SVC
    SVC --> REPO
    SVC --> DOM
    REPO --> DOM
    DOM --> SUP

依存の向きは「内向き」に一方通行

矢印はすべて外側(画面に近い側)から内側(業務ロジック側)へ向いています。これが崩れないようにするのがこの構成の目的です。

  • app.domain誰も知らない。JavaFXも、Repositoryも、ViewModelも知らない
  • app.repositoryapp.domain だけを知る
  • app.serviceapp.repositoryapp.domain を知る
  • app.viewmodelapp.service を知る。JavaFXは知らない
  • app.view だけがJavaFXを知る

矢印が内向きなので、内側だけを取り出してテストできます。Entityのテストには何も要りませんし、Serviceのテストには偽物(Fake)のRepositoryを1つ渡せば十分です。

実務のGradleプロジェクトではどうなるか

実務では、これがそのままディレクトリ構成になります。

src/
  main/java/app/
    Main.java                 ← Composition Root(依存を組み立てる場所)
    domain/    TaskItem.java  TaskTitle.java  Priority.java  TaskFactory.java
    repository/TaskRepository.java  InMemoryTaskRepository.java
    service/   TaskService.java  TaskDto.java  TaskMapper.java
    viewmodel/ ViewModelBase.java  TaskListViewModel.java  RelayCommand.java
    view/      MainView.fxml  MainViewController.java
    support/   IdGenerator.java  Clock.java
  test/java/app/
    domain/    TaskItemTest.java  TaskTitleTest.java
    service/   TaskServiceTest.java
    viewmodel/ TaskListViewModelTest.java

src/main/java が本体、src/test/java がテストです。テストは本体と同じパッケージ名で置くのが慣習で、こうするとパッケージプライベートのクラスもテストから触れます。

このコースの実行エディタとの対応

このサイトの実行エディタは、上のタブがそのまま「ファイル」です。package 宣言は書いても書かなくても動きますが、実務の見た目に合わせて書く回もあります。テストのファイルには @Test の付いたメソッドを書き、実行するとテストメソッド単位で✅/❌が出ます。

まとめ

  • 3層はパッケージで表す。domain / repository / service / viewmodel / view / support
  • 依存の矢印は外→内の一方通行。domain は誰も知らない
  • 内向きだから、内側の層だけを切り出してテストできる

次回: 一番外側のView、JavaFXの最低限を押さえます。