takeda_san’s blog

KotlinとVRを頑張っていく方向。

JSUG勉強会 2019その2に行ってきました #jsug

きっかけ

JSUGの勉強会に行ってまいりました。

Spring BootベースのDDDサンプル徹底解説!
jsug.doorkeeper.jp

題材は、このリポジトリの解説とJIGというツールの紹介でした。
GitHub - system-sekkei/isolating-the-domain: architecture sample using : Spring Boot gradle, Spring MVC, Thymeleaf, and MyBatis

もともと発表者の増田さんの本は読んでいて、実際にギョームアプリに適用できるかは方針によるんだけどアプリケーションのあるべき方向性みたいなものの指針にはしていました。
(言い方があれなんだけれども結構、振り切った設計をしていて、アプリの方針によっては取捨選択が必要な感じ)
結構極端に思えるんだけど、設計方針にすべて明確な理由付けがあって、納得できるという感じ。

んで、ちょうどチーム内の勉強会の題材になっていたのでこれは運命!とおもいつつ参加いたしました。

到着

渋谷でバス乗り場に迷い。
会場の六本木ヒルズで受付を探して迷い、いい大人なのに迷子になりっぱなしなのが悲しくなりました。
そして、素敵で開放的な会場に到着…なにこのオシャレなオープンキッチン的な場所…すごい

資料はここ。

DDD sample code explained in Java

以下、感想。

導入(1~10ページ)

このリポジトリを作った動機と本日のもくじ。

実アプリケーション並みの具体例が欲しかった。

俺はこの作り方が良いと思っているゼ!、と考えを示したリポジトリを持っているのは良いなぁと最近思ってます。
名刺代わりというかなんというか…
考え方が変わるたびにアップデートされて行って自分の経験というか考え方の遷移が分かるのは、良い。
ちょっとそんな思いもありこの辺のリポジトリを作ったりしている。
こういうのを見ながらあーだこーだ言い合いたい。

github.com

github.com

あと、単純に 現場で役立つシステム設計の原則 のものを実践したらこうなるというのはとてもありがたいです。

型指向

このサンプルだと、これが特に徹底されているように感じる。
emailアドレスってStringに格納しがちだけど、ほんとうはそうじゃないよねッ!いろいろチェックが必要というやつ。
プリミティブ型とかStringって値を入れるものとしては制約がなさ過ぎて広すぎる。

これが私の場合だと、諸々のあきらめとか現実に阻まれてやり切れない。(悲しい)

モデル層(11~12ページ)

ドメインモデルと各型が格納されるモデル層。

時給ベースの給与計算

これ、最近同じような計算システムを作ったので、完成したものと、このサンプルの差分が結構あるのが楽しい。
データの前提を決めているが、それをコードに落とし込み切れていないところとかが一番の反省点かなぁ…(NULL可能とか値の範囲とかが暗黙的)
これは時給計算を前提としているが、月額でいくらみたいなパターンが増えたときにどう改修するか考えるのが楽しそう。

型志向プログラミング

あとでよむ 設計ガイドライン · masuda220/business-logic-patterns Wiki · GitHub

可読性 over Javaの習慣的な記法

読んで意図が分かるのであれば縛りは少なくて済む。
setter、getterの類は必須ではない。
個人的には開発のメンバーと開発の段階によるかなぁと、コア部分が多少できていて書き方が一通り決まっているというかある程度真似すればよい段階なら慣習に従わなくてもよいかなぁと。
(もちろん読んで意図を分かってもらえる程度の人のみでチームが構成されている前提だが…)
イチからよーいどんで多人数で開発みたいなのは、慣習に従ったほうがブレない気がする。

JavaString streamが変

Groovyと比べると変らしい…
JavaとKotlinしか使ってないので、あんまりピンとこなかった…
あとで考える。

【追記】
String -> stream
聞きまちがえ…
streamにしても、ちょっとお勉強が必要ですな

バリデーションの使い分け

ここが個人的には悩みどころ。
REST APIとかでPOSTのときはidはサーバで採番するので必須じゃないけど、PUTの時は必須みたいなIFによってバリデーションって変わると思うんですよね。
最悪、IFの分だけバリデーションの種類ができてくる気が。
こうしたときにIF(外部との境界)のところのバリデーションとドメインモデルでのバリデーションの2箇所に点在してしまうのが、ドメイン知識が漏れてる状態にならないのかがお悩みポイント。
今のところ結局、IF(外部との境界)のところだけでバリデーションを入れている。

同じようにDBの制約をキツキツに入れたときにこれってドメイン知識じゃなかろうか(桁数とか外部制約とか)とふと思うときがある。
DBについては、あとで出てきた話で解決しました。

アプリケーション層(13~14ページ)

いわゆるServiceクラスの層。

serviceクラスとcoordinatorクラスの使い分け

リポジトリとの1対1の関係のserviceクラスとそれを組み合わせて使うcoordinatorクラス。
確かにひとつのサービスで別のサービスを呼び出したりして、結局カオス状態みたいなことがあるので、階層的にして整理するのはよさそう。

データソース層(15~17ページ)

データの入出力の層。
計算モデルをつくることを優先する。
そのためにDB層のJOINで一発でとってこれるところも、計算モデルの単位で入出力できることを優先してつくる。
 →方針次第かなと思う、アプリケーションに仕事をさせるかかDBに仕事をさせるか…

Mybatis

僕はDomaを使うかな…
可読性低いのでなるべくXML書きたくないという気持ちが優先される。

イミュータブルデータモデル

最新が欲しいというユースケースが多いので、パフォーマンスが心配である。
これも設計方針によって変わるのかなと(監査要件とかアプリケーションの用途とか)
あと、台帳データベースも検討の余地があるのかなぁとぼんやり。

NOT NULL

すごい正規化してNULLが入る余地をなくしているなと。
これは 現場で役立つシステム設計の原則 を読んでたときもオワッと思った点。
あるべきはこうなんだけどINSERTとか取り出すときのJOINとか大変そうだなぁ…と。
これも何を優先している設計方針かということに依りそう。

DB設計と計算モデルは別としたい

別々にするためにSQLを生で書くということを重視している。
DB設計の制約とドメインモデルの制約は別で考えてそれぞれで最適をやるべき。

同じようにDBの制約をキツキツに入れたときにこれってドメイン知識じゃなかろうか(桁数とか外部制約とか)とふと思うときがある。

ここの答え。

日本語のメソッド名まで踏み込むとが複数系が表現しずらい件

確かに…命名の知見が英語前提なので、ほぼイチからの合意形成になりそうである。つらそう

外部とのAPIとのやりとり

  • IN
    Controllerで受け取るロジックを置く、またはインフラ層に置く
  • OUT
    インフラ層に置く
    個人的には外部とのやり取りとして一か所に隔離したい(腐敗防止層用のパッケージを切りたい)
    アプリケーション層には外部IFの都合を書かないのは重要ですね。
    APIの変更に振り回されたくない…

プレゼンテーション層とは計算モデルのビューである

ドメインオブジェクトをそのままviewとして出す(naked objectパターン)。
適切にモデルが切れていればユーザとしてもその単位で見たいはずというのは分かる。
ユーザが見たい単位がかわったならばそれはドメインモデルの変更であるといえるのかな。つよい。
とはいいつつ権限によっての表示制御や、画面の状態による表示制御があるので、これも方針によるって感じに思える。

JIG

コードによる設計活動ツール。
コードを設計活動の一部にする。設計→コード→設計書のループ。
どうしてもコードが先に進んでて設計書はおいてかれる傾向があるので、ループにコードを入れるのは大賛成。
Springfoxとか好き。

パッケージごとの依存関係が出せるのは便利そう。
個人的に依存関係からリファクタリングの糸口が見つかることが多い気がする。

ソースコードからビジネスルール用語集が出せる

クラスへのコメント、package-info.javaとかから抽出。
ユビキタス言語とはちょっと違うけど元ネタにはなりそう。

さいごに

参加者の質問がかなりハイレベルで震える勉強会でした。
もっと自分の意見とか設計の考え方をしっかり持たないとなと思った次第です。
あと形式手法…なんかいかチャレンジして死亡してるので、再びのチャレンジのしどきだなと思ってます。