本文へスキップ
BecomeCoder

C# MVVMコース · 第10章 仕上げ ― アプリを完成させる · レッスン38

全層を振り返る ― 依存の向きをもう一度確認する

ローカル実施

導入

ここまでの9章で、タスク管理アプリは「テストだけを頼りに動くものを積み上げる」というやり方で完成に近づきました。仕上げに入る前に、一度立ち止まって全体を見渡しましょう。バラバラに見えていたEntity・Repository・Service・ViewModel・Viewが、実は1つの一貫した依存の向きのルールでつながっていたことに気づけるはずです。

説明

flowchart LR
    subgraph Core["MyApp.Core(Model・外部技術に依存しない)"]
        TT["TaskTitle / Priority<br/>(ValueObject)"]
        TI["TaskItem<br/>(Entity)"]
        FAC["TaskFactory"]
        ITR["ITaskRepository(抽象)"]
        ITS["ITaskService(抽象)"]
        DTO["TaskDto / TaskMapper"]
    end
    subgraph Infra["MyApp.Infrastructure"]
        IMR["InMemoryTaskRepository"]
    end
    subgraph App["MyApp(実行可能・View/ViewModel)"]
        VM["TaskListViewModel"]
        VW["View(XAML)"]
        CR["Composition Root<br/>(起動時にDIを組み立てる)"]
    end
    FAC --> TI --> TT
    IMR -.実装.-> ITR
    TS["TaskService"] -.実装.-> ITS
    TS --> ITR
    VM --> ITS
    VM --> DTO
    VW <-->|"DataContext / {Binding}"| VM
    CR -.配線.-> IMR
    CR -.配線.-> TS
    CR -.配線.-> VM
  • Entity/ValueObject第2章): TaskItemTaskTitlePriority。業務データそのものと、それが必ず守るべきルールを持つ。何にも依存しない
  • Factory第3章): TaskFactory。生成のルールを1箇所にまとめる
  • Repository第4章): ITaskRepository(抽象)とInMemoryTaskRepository(実装)。データの出し入れだけを担当し、業務ルールは持たない
  • Service第5章): ITaskServiceTaskService。「重複タイトル禁止」のような、複数のデータを見比べる業務ルールを担当する
  • Mapper/DTOレッスン19): TaskDtoTaskMapper。業務データ(TaskTitleなど)を画面用のプレーンな値に変換する
  • ViewModel第6章): TaskListViewModel。画面の状態(TasksNewTaskTitle)と操作(AddCommand)を、UIフレームワークに依存しない普通のC#クラスとして表現する
  • View第7章): XAML。DataContext{Binding}でViewModelとつながるだけで、ロジックは持たない
  • DI/Composition Root第8章): どの実装をどこに注入するかを、アプリ起動時の1箇所(Composition Root)でまとめて決める
  • テスト第9章): 各層は自分より内側(Core寄り)のインターフェースにしか依存しないため、外側をFakeに差し替えるだけで高速なテストが書けた

矢印の向きに注目してください。どの層も、自分より業務の核(Core)に近い層にしか依存していません。ViewはViewModelを知っていますが、ViewModelはViewの存在を知りません。ServiceはRepositoryのインターフェースを知っていますが、Repositoryの具体的な実装(InMemoryかDBか)は知りません。この「依存の向きを常に核へ集める」という1つのルールが、レッスン3のプロジェクト分割からテストのしやすさまで、コース全体を貫いていました。

まとめ

  • Entity→Repository→Service→ViewModel→Viewは、すべて「自分より内側にしか依存しない」という1つのルールでつながっている
  • このルール(依存性逆転)のおかげで、外側(Repository・Service・View)をFakeや別実装に差し替えても、内側のコードは変更不要になる
  • 次のレッスンから、この構造を保ったまま新機能を2つ追加する

次回: 「期限切れ強調表示」機能をTDDで追加します。