コードをどまんなかに据えたモデリング-Scala版 / Modeling with code in the middle-Scala version

コードをどまんなかに据えたモデリング-Scala版 / Modeling with code in the middle-Scala version

【オンライン開催】04/14(火) Scala関西勉強会 - 2020年04月版
https://connpass.com/event/163551/

C952d9f90c7ec6cb1b5513c05d3db536?s=128

yoshiyoshifujii

April 14, 2020
Tweet

Transcript

  1. Scala関西 Chatwork株式会社 FUJII Yoshitaka コードをどまんなかに据えた モデリング - Scala版

  2. 自己紹介 - FUJII Yoshitaka - @yoshiyoshifujii - Chatwork株式会社 - Scala関西

    - 登壇 - ScalaMatsuri2019 - 実践 Clean Architecture - 趣味 - ⛰ ⛺ ‍♂ 庭DIY
  3. アジェンダ 1. 課題感 2. JIG 3. sbt-jig 4. sbt-jig-tutorial 5.

    コードへのフィードバック例 3
  4. 01 課題感

  5. 課題感 - モデリングどうやりますか - ホワイトボードに書く - ツールを使う - astah -

    PlantUML - Miro 5
  6. 課題感 - 図に書いた通りに実装できていますか - 認識はズレていませんか - コードとドキュメントは同期されていま すか - どうやって担保しますか

    6
  7. 課題感 - 図とコードとテストの変更のリズムは どうですか - さくさく変更できますか - 図からコード、コードをテスト、 コードを変更ってぐるぐるしてると、 図は…あとで良いや

    ってなりがち 7
  8. 02 JIG

  9. コードをどまんなかに - コードに軸足を置く - 最初はホワイトボードとかで認識合わせ る(Miroはいいぞ  ) - 意図を込めてコードを書き、意図が表現 されたドキュメントを見る

    9
  10. コードをどまんなかに 10 https://speakerdeck.com/irof/kodowodomannakaniju-etashe-ji-apuroti

  11. コードをどまんなかに - JIG Java Instant-document Gazer (ドキュメントは一時的に見るもの) - https://github.com/dddjava/jig -

    JIGは、バイトコードおよびソースコードから、 一覧(Excel形式)やダイアグラム(SVG形式)を 出力するツールです 11
  12. JIG 三層+ドメインモデル のアーキテクチャで実 装されたコードから分 析・設計情報を出力す るツール 12

  13. JIGのDiagramたち 13 https://jigzag.work/

  14. 03 sbt-jig

  15. Scalaに対応した - JIGにScalaのソースコードを解析できるように拡張部 分を追加させていただいた - https://github.com/dddjava/jig/pull/424 - https://irof-web.s3.amazonaws.com/jig/master/use-case- and-fellows.svg 15

  16. sbt-jigを作った - https://github.com/yoshiyoshifujii/sbt-jig - Scalaのソースから、Scaladocを読み取り、別名を扱え るようにした - JIGに追加した org.dddjava.jig.domain.model.jigloaded.alias.ScalaSourceAliasReader をsbt-jig側で実装

    - Scalametaを使って解析 16
  17. sbt-jig - JIGのプロパティをsbtにも用意 17 override lazy val projectSettings = Seq(

    jigReports := Jig.jigReportsTask(jig).value, jigDocumentTypeText in jig := "", jigOutputDirectoryText in jig := "./target/jig", jigOutputOmitPrefix in jig := ".+\\.(service|domain\\.(model|type))\\.", jigModelPattern in jig := ".+\\.domain\\.(model|type)\\..+", jigProjectPath in jig := "./", jigDirectoryClasses in jig := Jig.makeClasses().value, jigDirectoryResources in jig := Jig.makeClasses().value, jigDirectorySources in jig := "src/main/scala" )
  18. sbt-jig - Scalaのバージョンを見たうえで、classesが出力される ディレクトリを導出 18 def makeClasses(): Initialize[String] = Def.setting

    { s"target/scala-${scalaBinaryVersion.value}/classes" }
  19. 04 sbt-jig-tutorial

  20. sbt-jig-tutorialを作った - https://github.com/yoshiyoshifujii/sbt-jig-tutorial - jig-tutorialがあったので、sbt-jig用を作った - ぜひお試しください 20

  21. 05 コードへの フィードバック例

  22. Roleオブジェクト - DCIアーキテクチャ - https://digitalsoul.hatenadiary.org/entry/20100131/1264925022 - オブジェクト指向の本質が人間のメンタルモデルを捉え ることにあるとした上で、問題と解決方法を提示 - 問題は、構造を捉えることに長けている反面、ふるまい

    を捉えることが苦手 - 特定のふるまいをどのクラスにおくべきか - エンティティクラスが大量のメソッドで肥大化する - 今回は、 Factory Method について捉えた 22
  23. Roleオブジェクト 23 - グループチャットにメッセージを生成する Factory Methodを実装する - グループチャットは、メッセージを生成す るうえで、集約由来の生成ロジックを保持 しており、そのロジックを通してしか、

    メッセージの生成を許可しない - グループチャットのふるまいとして持たせ ることは、良さそうに思える
  24. Roleオブジェクト 24 - グループチャットを通して生成 する別の集約のエンティティと して、ファイルやタスク、ライ ブ… - グループチャットが持つ Factoryとしてのメソッドが増

    え、肥大化する
  25. Roleオブジェクト 25 - Factory Methodは、JIGでレポートすると相互の 関連で出力される package groupChat import message.Message

    trait GroupChat { def createMessage(accountId: AccountId, body: String): Message = ??? } package message import groupChat.RoomId trait Message { val roomId: RoomId }
  26. Roleオブジェクト 26 - メッセージパッケージにRoleオブジェクトを作る - Scalaの場合、型クラスとして作成すると扱いやすい package message import groupChat.GroupChat

    trait MessageRole[A] { def createMessage(self: A)(accountId: AccountId, body: String): Message } object MessageRole { implicit val groupChatMessageRole = new MessageRole[GroupChat] { override def createMessage(self: GroupChat)(accountId: AccountId, body: String): Message = ??? } implicit def toMessageRoleOps[A: MessageRole](self: A) = new { def createMessage(accountId: AccountId, body: String): Message = implicitly[MessageRole[A]].createMessage(self)(accountId, body) } }
  27. 働くをもっと楽しく、創造的に