Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
コードをどまんなかに据えたモデリング-Scala版 / Modeling with code ...
Search
yoshiyoshifujii
April 14, 2020
Technology
0
140
コードをどまんなかに据えたモデリング-Scala版 / Modeling with code in the middle-Scala version
【オンライン開催】04/14(火) Scala関西勉強会 - 2020年04月版
https://connpass.com/event/163551/
yoshiyoshifujii
April 14, 2020
Tweet
Share
More Decks by yoshiyoshifujii
See All by yoshiyoshifujii
技術的負債と戦略的に戦わざるを得ない場合のオブザーバビリティ活用術 / Leveraging Observability When Strategically Dealing with Technical Debt
yoshiyoshifujii
0
190
プロダクトオーナーの視座から見た信頼性とオブザーバビリティ / Reliability and Observability from the Perspective of a Product Owner
yoshiyoshifujii
2
1.6k
プロダクトオーナーがFour Keys + 信頼性に思うところ / Product Owners Think of Four Keys + Reliability
yoshiyoshifujii
0
560
Recapping Chatwork Scala Journey - ScalaMatsuri2023
yoshiyoshifujii
0
2.8k
ここ数ヶ月でAkkaを勉強した方法について紹介 / I have studied Akka in the past few months
yoshiyoshifujii
1
280
Chatworkのドメインをモデリングした / Modeling Chatwork domain
yoshiyoshifujii
0
890
サマーインターンシップ2019で学生とDDDなScala開発に取り組んだ / Working on DDD and Scala development with students at Summer Internship 2019
yoshiyoshifujii
2
4.2k
Clean Architecture in Practice @ScalaMatsuri2019
yoshiyoshifujii
9
4.1k
実践 Clean Architecture
yoshiyoshifujii
13
10k
Other Decks in Technology
See All in Technology
本当に使える?AutoUpgrade の新機能を実践検証してみた
oracle4engineer
PRO
1
140
AIエージェント最前線! Amazon Bedrock、Amazon Q、そしてMCPを使いこなそう
minorun365
PRO
13
4.9k
Understanding_Thread_Tuning_for_Inference_Servers_of_Deep_Models.pdf
lycorptech_jp
PRO
0
110
Кто отправит outbox? Валентин Удальцов, автор канала Пых
lamodatech
0
330
Snowflake Summit 2025 データエンジニアリング関連新機能紹介 / Snowflake Summit 2025 What's New about Data Engineering
tiltmax3
0
300
AWS アーキテクチャ作図入門/aws-architecture-diagram-101
ma2shita
29
10k
Definition of Done
kawaguti
PRO
6
480
Claude Code Actionを使ったコード品質改善の取り組み
potix2
PRO
6
2.1k
Uniadex__公開版_20250617-AIxIoTビジネス共創ラボ_ツナガルチカラ_.pdf
iotcomjpadmin
0
160
Welcome to the LLM Club
koic
0
160
rubygem開発で鍛える設計力
joker1007
2
190
5min GuardDuty Extended Threat Detection EKS
takakuni
0
120
Featured
See All Featured
Thoughts on Productivity
jonyablonski
69
4.7k
Product Roadmaps are Hard
iamctodd
PRO
54
11k
個人開発の失敗を避けるイケてる考え方 / tips for indie hackers
panda_program
107
19k
Optimising Largest Contentful Paint
csswizardry
37
3.3k
Why You Should Never Use an ORM
jnunemaker
PRO
56
9.4k
Bash Introduction
62gerente
614
210k
Java REST API Framework Comparison - PWX 2021
mraible
31
8.6k
Into the Great Unknown - MozCon
thekraken
39
1.9k
Navigating Team Friction
lara
187
15k
Large-scale JavaScript Application Architecture
addyosmani
512
110k
The Invisible Side of Design
smashingmag
299
51k
Site-Speed That Sticks
csswizardry
10
660
Transcript
Scala関西 Chatwork株式会社 FUJII Yoshitaka コードをどまんなかに据えた モデリング - Scala版
自己紹介 - FUJII Yoshitaka - @yoshiyoshifujii - Chatwork株式会社 - Scala関西
- 登壇 - ScalaMatsuri2019 - 実践 Clean Architecture - 趣味 - ⛰ ⛺ ♂ 庭DIY
アジェンダ 1. 課題感 2. JIG 3. sbt-jig 4. sbt-jig-tutorial 5.
コードへのフィードバック例 3
01 課題感
課題感 - モデリングどうやりますか - ホワイトボードに書く - ツールを使う - astah -
PlantUML - Miro 5
課題感 - 図に書いた通りに実装できていますか - 認識はズレていませんか - コードとドキュメントは同期されていま すか - どうやって担保しますか
6
課題感 - 図とコードとテストの変更のリズムは どうですか - さくさく変更できますか - 図からコード、コードをテスト、 コードを変更ってぐるぐるしてると、 図は…あとで良いや
ってなりがち 7
02 JIG
コードをどまんなかに - コードに軸足を置く - 最初はホワイトボードとかで認識合わせ る(Miroはいいぞ ) - 意図を込めてコードを書き、意図が表現 されたドキュメントを見る
9
コードをどまんなかに 10 https://speakerdeck.com/irof/kodowodomannakaniju-etashe-ji-apuroti
コードをどまんなかに - JIG Java Instant-document Gazer (ドキュメントは一時的に見るもの) - https://github.com/dddjava/jig -
JIGは、バイトコードおよびソースコードから、 一覧(Excel形式)やダイアグラム(SVG形式)を 出力するツールです 11
JIG 三層+ドメインモデル のアーキテクチャで実 装されたコードから分 析・設計情報を出力す るツール 12
JIGのDiagramたち 13 https://jigzag.work/
03 sbt-jig
Scalaに対応した - JIGにScalaのソースコードを解析できるように拡張部 分を追加させていただいた - https://github.com/dddjava/jig/pull/424 - https://irof-web.s3.amazonaws.com/jig/master/use-case- and-fellows.svg 15
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にも用意 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" )
sbt-jig - Scalaのバージョンを見たうえで、classesが出力される ディレクトリを導出 18 def makeClasses(): Initialize[String] = Def.setting
{ s"target/scala-${scalaBinaryVersion.value}/classes" }
04 sbt-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 groupChat import message.Message
trait GroupChat { def createMessage(accountId: AccountId, body: String): Message = ??? } package message import groupChat.RoomId trait Message { val roomId: RoomId }
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) } }
働くをもっと楽しく、創造的に