【オンライン開催】04/14(火) Scala関西勉強会 - 2020年04月版 https://connpass.com/event/163551/
Scala関西Chatwork株式会社FUJII Yoshitakaコードをどまんなかに据えたモデリング - Scala版
View Slide
自己紹介- FUJII Yoshitaka- @yoshiyoshifujii- Chatwork株式会社- Scala関西- 登壇- ScalaMatsuri2019- 実践 Clean Architecture- 趣味- ⛰ ⛺ ♂ 庭DIY
アジェンダ1. 課題感2. JIG3. sbt-jig4. sbt-jig-tutorial5. コードへのフィードバック例3
01課題感
課題感- モデリングどうやりますか- ホワイトボードに書く- ツールを使う- astah- PlantUML- Miro5
課題感- 図に書いた通りに実装できていますか- 認識はズレていませんか- コードとドキュメントは同期されていますか- どうやって担保しますか6
課題感- 図とコードとテストの変更のリズムはどうですか- さくさく変更できますか- 図からコード、コードをテスト、コードを変更ってぐるぐるしてると、図は…あとで良いや ってなりがち7
02JIG
コードをどまんなかに- コードに軸足を置く- 最初はホワイトボードとかで認識合わせる(Miroはいいぞ )- 意図を込めてコードを書き、意図が表現されたドキュメントを見る9
コードをどまんなかに10https://speakerdeck.com/irof/kodowodomannakaniju-etashe-ji-apuroti
コードをどまんなかに- JIGJava Instant-document Gazer(ドキュメントは一時的に見るもの)- https://github.com/dddjava/jig- JIGは、バイトコードおよびソースコードから、一覧(Excel形式)やダイアグラム(SVG形式)を出力するツールです11
JIG三層+ドメインモデルのアーキテクチャで実装されたコードから分析・設計情報を出力するツール12
JIGのDiagramたち13https://jigzag.work/
03sbt-jig
Scalaに対応した- JIGにScalaのソースコードを解析できるように拡張部分を追加させていただいた- https://github.com/dddjava/jig/pull/424- https://irof-web.s3.amazonaws.com/jig/master/use-case-and-fellows.svg15
sbt-jigを作った- https://github.com/yoshiyoshifujii/sbt-jig- Scalaのソースから、Scaladocを読み取り、別名を扱えるようにした- JIGに追加したorg.dddjava.jig.domain.model.jigloaded.alias.ScalaSourceAliasReaderをsbt-jig側で実装- Scalametaを使って解析16
sbt-jig- JIGのプロパティをsbtにも用意17override 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")
sbt-jig- Scalaのバージョンを見たうえで、classesが出力されるディレクトリを導出18def makeClasses(): Initialize[String] =Def.setting {s"target/scala-${scalaBinaryVersion.value}/classes"}
04sbt-jig-tutorial
sbt-jig-tutorialを作った- https://github.com/yoshiyoshifujii/sbt-jig-tutorial- jig-tutorialがあったので、sbt-jig用を作った- ぜひお試しください20
05コードへのフィードバック例
Roleオブジェクト- DCIアーキテクチャ- https://digitalsoul.hatenadiary.org/entry/20100131/1264925022- オブジェクト指向の本質が人間のメンタルモデルを捉えることにあるとした上で、問題と解決方法を提示- 問題は、構造を捉えることに長けている反面、ふるまいを捉えることが苦手- 特定のふるまいをどのクラスにおくべきか- エンティティクラスが大量のメソッドで肥大化する- 今回は、 Factory Method について捉えた22
Roleオブジェクト23- グループチャットにメッセージを生成するFactory Methodを実装する- グループチャットは、メッセージを生成するうえで、集約由来の生成ロジックを保持しており、そのロジックを通してしか、メッセージの生成を許可しない- グループチャットのふるまいとして持たせることは、良さそうに思える
Roleオブジェクト24- グループチャットを通して生成する別の集約のエンティティとして、ファイルやタスク、ライブ…- グループチャットが持つFactoryとしてのメソッドが増え、肥大化する
Roleオブジェクト25- Factory Methodは、JIGでレポートすると相互の関連で出力されるpackage groupChatimport message.Messagetrait GroupChat {def createMessage(accountId: AccountId, body: String): Message = ???}package messageimport groupChat.RoomIdtrait Message {val roomId: RoomId}
Roleオブジェクト26- メッセージパッケージにRoleオブジェクトを作る- Scalaの場合、型クラスとして作成すると扱いやすいpackage messageimport groupChat.GroupChattrait 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)}}
働くをもっと楽しく、創造的に