#ooc_2020 / ドメイン駆動設計を支えるアーキテクチャテスト / Object-Oriented Conference 2020

73560128b23de542e47a318145bc781a?s=47 Yu Kawanami
February 16, 2020

#ooc_2020 / ドメイン駆動設計を支えるアーキテクチャテスト / Object-Oriented Conference 2020

73560128b23de542e47a318145bc781a?s=128

Yu Kawanami

February 16, 2020
Tweet

Transcript

  1. ドメイン駆動設計を支える アーキテクチャテスト Object-Oriented Conference 2020 @kawanamiyuu

  2. 2 https://speakerdeck.com/kawanamiyuu/jjug-ccc-2019-spring アーキテクチャテストへの モチベーション、具体例を 紹介した入門編

  3. 自己紹介 • かわなみゆう • @kawanamiyuu • 株式会社ラクス / Lead Engineer

    • HR x SaaS の開発 • Java (Spring Boot, Doma) / Vue.js / Puppeteer • 自動テスト(が書きやすい設計を考えながらコード) を書くのがすき 3
  4. Context Map 4 https://www.infoq.com/articles/ddd-contextmapping/

  5. Context Map 5 https://www.infoq.com/articles/ddd-contextmapping/

  6. Layer Architecture (〇〇〇〇を逆転したレイヤードアーキテクチャ) 6 (一般的なレイヤードアーキテクチャ)

  7. Layer Architecture (〇〇〇〇を逆転したレイヤードアーキテクチャ) 7 (一般的なレイヤードアーキテクチャ)

  8. Clean Architecture 8

  9. Clean Architecture 9

  10. Domain Model Employee Procedure Report xxx yyy 10

  11. 依存関係 11

  12. アーキテクチャとは 「依存関係」のガイドライン 12

  13. アーキテクチャの正体 • アーキテクチャとはソフトウェアの構造についての取り決めで あり、 • 解像度を上げていくと、ソフトウェアを構成する責務や関心事 の「依存関係」についての取り決め 13

  14. アーキテクチャの視座 • 責務や関心事の粒度 ◦ 大きな粒度:コンテキスト、レイヤー ◦ 小さな粒度:パッケージ、クラス • それぞれの粒度で依存関係を注意深く設計する 14

  15. アーキテクチャとオブジェクト指向設計原則 • (乱暴に言うと)Layer Architecture も Clean Architecture も 、DDD のような設計論も、依存関係を適切に設計したいだ

    け • その礎としてのオブジェクト指向設計原則 ◦ 単一責任の原則(SRP) ◦ 依存関係逆転の原則(DIP) 15
  16. 「アーキテクチャ」の問題点 16

  17. 「ガイドライン」というものの性質 • ガイドラインとは「指針」「ルール」「マナー」 • 人が決めて、守る(守らせる) • 最初にルールをつくるのは、簡単 • ルール通りつくり始めるのも、簡単 17

  18. 「ガイドライン」というものの性質 • ガイドラインとは「指針」「ルール」「マナー」 • 人が決めて、守る(守らせる) • 最初にルールをつくるのは、簡単 • ルール通りつくり始めるのも、簡単  なにが難しいのか?

    18
  19. アーキテクチャの維持が難しい 19

  20. アーキテクチャの維持は難しい 人が決めたことであるがゆえに、壊れやすい。 時間が経つと「大きな泥団子(Big Ball of Mud)」に。 • よくある要因 ◦ 設計知識の属人化・暗黙知化

    ◦ 開発スキルのばらつき ◦ 納期優先、相次ぐメンバー増員 20
  21. どうすればよいか? 21

  22. 22 アーキテクチャをテストしたい

  23. 23 https://www.archunit.org/

  24. ArchUnit • GitHub ◦ https://github.com/TNG/ArchUnit ◦ https://github.com/TNG/ArchUnit-Examples • Twitter ◦

    https://twitter.com/archtests • Technology Radar ◦ https://www.thoughtworks.com/radar/tools/archunit ◦ 進化的アーキテクチャ x 適応度関数 24
  25. ArchUnit を一言でいうと • Java(や Kotlin, Scala)で書かれたアプリケーションのパッ ケージやクラスの依存関係を JUnit のテストコードとして表現 し、テストできるテストフレームワーク

    • 依存関係の他にも、そのアプリケーション固有の実装ルール もテストすることができる 25
  26. 他のプログラミング言語でのアーキテクチャテスト • TNG/ArchUnitNET(C#) • iternity/archlint.cs(C#) • BenMorris/NetArchTest(.Net) • sensiolabs-de/deptrac(PHP) •

    carlosas/phpat(PHP) • nazonohito51/dependency-analyzer(PHP) 26
  27. アーキテクチャテストの例 27

  28. 28 @Test void DIP_依存性逆転の原則_を適用したレイヤードアーキテクチャ () { layeredArchitecture() .layer("ui").definedBy("com.example.presentation..") .layer("app").definedBy("com.example.application..") .layer("domain").definedBy("com.example.domain..")

    .layer("infra").definedBy("com.example.infrastructure..") .whereLayer("ui").mayOnlyBeAccessedByLayers("infra") .whereLayer("app").mayOnlyBeAccessedByLayers("infra", "ui") .whereLayer("domain").mayOnlyBeAccessedByLayers("infra", "app") .whereLayer("infra").mayNotBeAccessedByAnyLayer() .check(CLASSES); }
  29. 29 @Test void DIP_依存性逆転の原則_を適用したレイヤードアーキテクチャ () { layeredArchitecture() .layer("ui").definedBy("com.example.presentation..") .layer("app").definedBy("com.example.application..") .layer("domain").definedBy("com.example.domain..")

    .layer("infra").definedBy("com.example.infrastructure..") .whereLayer("ui").mayOnlyBeAccessedByLayers("infra") .whereLayer("app").mayOnlyBeAccessedByLayers("infra", "ui") .whereLayer("domain").mayOnlyBeAccessedByLayers("infra", "app") .whereLayer("infra").mayNotBeAccessedByAnyLayer() .check(CLASSES); }
  30. 30 @Test void ReportドメインはProcedureドメインからのみ依存される () { classes().that().resideInAPackage("com.example.domain.report..") .should() .onlyBeAccessed().byAnyPackage("com.example.domain.procedure..") .check(CLASSES);

    }
  31. 31 @Test void ReportドメインはProcedureドメインからのみ依存される () { classes().that().resideInAPackage("com.example.domain.report..") .should() .onlyBeAccessed().byAnyPackage("com.example.domain.procedure..") .check(CLASSES);

    }
  32. 32 @Test void ドメイン層はWeb実行環境に依存しない () { noClasses().that().resideInAPackage("com.example.domain..") .should() .dependOnClassesThat().resideInAPackage("javax.servlet..") .check(CLASSES);

    } @Test void ドメイン層はWebアプリケーションフレームワークに依存しない () { noClasses().that().resideInAPackage("com.example.domain..") .should() .dependOnClassesThat().resideInAPackage("org.springframework..") .check(CLASSES); }
  33. 33 @Test void ドメイン層はWeb実行環境に依存しない () { noClasses().that().resideInAPackage("com.example.domain..") .should() .dependOnClassesThat().resideInAPackage("javax.servlet..") .check(CLASSES);

    } @Test void ドメイン層はWebアプリケーションフレームワークに依存しない () { noClasses().that().resideInAPackage("com.example.domain..") .should() .dependOnClassesThat().resideInAPackage("org.springframework..") .check(CLASSES); }
  34. ドメイン駆動設計にとっての アーキテクチャテスト 34

  35. ドメインが隔離されていることを担保する • ドメインと、他の詳細や関心との依存関係 ◦ ドメインと技術的詳細 ◦ ドメインと UI • ドメイン同士の依存関係

    これらが期待通りであることを自動テストによって担保し続けること ができる。 35
  36. アーキテクチャテストの失敗は悪か? • アーキテクチャテストはあるべき依存関係を表現したもの • アーキテクチャテストは失敗しないはずのテスト • アーキテクチャテストが失敗するとき ◦ 実装誤り ◦

      ◦ 36
  37. アーキテクチャテストの失敗は悪か? • アーキテクチャテストはあるべき依存関係を表現したもの • アーキテクチャテストは失敗しないはずのテスト • アーキテクチャテストが失敗するとき ◦ 実装誤り ◦

    アーキテクチャに対する発見のサイン ◦ アーキテクチャについて議論する始点 37
  38. ドメイン駆動設計が支えるアーキテクチャ • ドメイン駆動設計の真髄は、設計⇔実装のフィードバックルー プ • 実装で得た知識が設計にも反映される 38

  39. ドメイン駆動設計が支えるアーキテクチャ • ドメイン駆動設計の真髄は、設計⇔実装のフィードバックルー プ • 実装で得た知識が設計にも反映される • アーキテクチャも同じ • アーキテクチャも一度決めて終わりではない

    • アーキテクチャもシステムの成長とともに磨かれる 39
  40. アーキテクチャの目的 40

  41. 41

  42. この図は • モノリシックなアプリケーション内部の、ドメイン同士の依存関 係? • マイクロサービスアーキテクチャで実現されたアプリケーション の、サービス同士の依存関係? 42

  43. この図は • モノリシックなアプリケーション内部の、ドメイン同士の依存関 係? • マイクロサービスアーキテクチャで実現されたアプリケーション の、サービス同士の依存関係? どちらもありえる。 43

  44. ドメイン駆動設計という文脈で私たちが「ドメイン」と呼んでいるも のが、ありていに言えば、高凝集で疎結合な実装技術によって実 現されていれば、システムとしてもビジネスとしても多くの選択肢 が残される。 モノリスからマイクロサービスへ、アーキテクチャを進化させる可 能性も。 44

  45. ソフトウェアが「ソフト」であるための選択肢を残す。 それがアーキテクチャ。 そのアーキテクチャが意図する依存関係を維持し、ソフトウェアの 発展の可能性を支えるアーキテクチャテスト。 45

  46. Appendix. 46

  47. 参考資料 • Books ◦ エリック・エヴァンスのドメイン駆動設計( Eric Evans) ◦ Clean Architecture

    ―達人に学ぶソフトウェアの構造と設計( Robert C.Martin) ◦ 進化的アーキテクチャ ―絶え間ない変化を支える( Neal Ford, Rebecca Parsons, Patrick Kua) • Talk ◦ JJUG CCC 2019 Spring ▪ ArchUnit で Java / Kotlin アプリケーションのアーキテクチャを CI する ▪ https://speakerdeck.com/kawanamiyuu/jjug-ccc-2019-spring • Blog ◦ ドメイン駆動設計#1 Advent Calendar 2019 ▪ 6日目:ドメイン駆動設計を支えるアーキテクチャテスト ▪ https://tech-blog.rakus.co.jp/entry/20191206/java 47