JSUG勉強会2019その2 に参加しました
2019年2月18日(月)、JSUG勉強会2019その2「JSUG勉強会 2019その2 Spring BootベースのDDDサンプル徹底解説!」に行ってきました。
DDDを実践できている身ではないのですが、以前マイクロサービスを学んだ際にDDDは併せて理解すべき概念と感じました。
DDDのサンプルとしてはCargo Trackerなどもありますが、今回はSpring Bootのサンプルコードを通じて学べる素晴らしい機会だったので参加しました。
印象に残った箇所、勉強になった箇所を中心にまとめています。
資料、サンプルコード
- 発表資料
- ドメイン層(ビジネスルール層)の設計ガイドライン
- サンプルコード
- 採用技術はSpring Boot, Spring MVC, MyBatis, Thymeleaf
ビジネスルールとデータ入出力の分離
ビジネスルール(計算)とデータ入出力は明確に分離する、ということでした。
これは意識している方も多いと思いますが、油断すると入り混じりがちだと思います。
MyBatisを使っている理由の一つは、これを実現するためと思われます。
仮にSpring Data JPAを使うと、RDBのレコードと対応するようにEntityを設計する必要がありますし、データ入出力のためのアノテーションがビジネスルールと入り交じることになりそうです。
設計の順序
まずドメイン層を作り込み、そのドメインモデルをやりとりするアプリケーション層を定義。
その後どのようにデータを入出力するかを定義し、最後にそれらを表示する画面を定義。
したがって、設計順序は以下の通り。
- ドメイン層(ビジネスルール層)
- アプリケーション層
- データソース層
- データベース
- プレゼンテーション層
ドメイン層
詳細なガイドラインはこちらにありますが、勉強会では主に以下の解説がありました。
- modelパッケージとtypeパッケージに分ける
- きれいに切り分けられるものではなく、行ったり来たりしている
- Bean Validationで有効な値の範囲を表現する
- getter/setter, private, final, Lombok, JPAなどは使っていない
一言で言うと「可読性の高いビジネスルールのドキュメントをJavaで記述する」という印象を受けました。
サンプルコードでは徹底的にビジネスルールと入出力を分離し、ModelのフィールドからはStringやプリミティブ型が排除されています。
確かにここまで徹底できれば、ゆくゆくは企画やサポートの人もこれを参照することができそうだと感じました。
また質疑応答ではStreamを使っていない理由について触れられていましたが、「JavaだとGroovyなどに比べて自然に書けない」とのことでした。
実際にはforとstreamのどちらを使ったほうが可読性が高いか、試行錯誤して採否を決めているそうです。
アプリケーション層
アプリケーション層は、機能的にどのような役割を果たすかによって、QueryサービスとOperationサービスの2種類に分けているようです。
- Queryサービス:計算結果を返す
- Operationサービス:計算結果の記録・通知を指示
またアプリケーション層の中でどのように構成されているかによって、serviceクラスとcoordinatorクラスの2種類に分けているようです。
- serviceクラス:単機能、単一repositoryから取得
- coordinatorクラス:複数のserviceを統合
Spring Bootには@Service
というアノテーションがあるのでserviceクラスは定義していたのですが、serviceクラスを複数使用するserviceクラスを作ってよいのかという点が気になっていました。
coordinatorクラスという考え方は一つの解だと思うので、今後選択肢の一つに入れたいと思います。
データソース層
ここではMyBatisを使って、データの入出力を実装します。
- SELECTを実行し、オブジェクトの生成
- オブジェクトの記録すべき事実について、INSERTを実行
ここは特筆すべきことはないかな、という印象です。
データベース
データベースの設計方針として、イミュータブルデータモデルを採用しているとのことでした。
- 基本はINSERTのみ
- UPDATEは使わず、トランザクションも排除
- スキーマ名、テーブル名、カラム名は日本語
日本語で設計するのはずいぶん思い切ったなぁ…と思いましたが、イミュータブルデータモデルはよいアプローチだと感じました。
もちろん採用できるかどうかはパフォーマンス等の要件次第でもありますが、メリットは大きいと感じました。
ちなみにイミュータブルデータモデルという考え方は認識していましたが、そういう名称があることをここで初めて知りました。(お恥ずかしい…)
よくよく考えれば、イミュータブルオブジェクトとかイミュータブルインフラストラクチャがあるのだから、あってもおかしくないですよね。
名前がわかればググれるようになるので、思いがけない収穫でした。。。
プレゼンテーション層
ドメインオブジェクトをそのまま渡して、Thymeleafで表示させる方針とのこと。
自分ならLombokでgetterを付けるなどしてしまいそうですが、「ビジネスロジックに意味のない記述はドメインモデルに含めない」という方針が徹底されていると感じました。
JIG
コードを元にドキュメントを生成するというのはとてもよいと感じました。
クラスやメソッドなどを俯瞰すると違和感に気付くことは多いので、こういったツールは重要ですね。
また新しくメンバーが入った時にも、JIGで生成されたドキュメントを見ると構成の理解が早そうです。
JIGのリポジトリはこちらですが、jig-coreの中身を見てみると…こちらもDDDで書かれているようです。
その他、印象に残った発言など
「過去形にしなくていいよ」
質疑応答の中で、irofさんの「○○だからこうなった」という言葉に対する、増田さんの言葉。
DDDではモデルは一度定義して終わりではなく、継続的に変更し、よいモデルを探求していくものと言われます。
何気ない一言でしたが、これはDDDの精神をよく表していて、いい言葉だなと思いました。
過去にとらわれず、本来どうあるべきかを常に意識すべきだと感じました。
「Javaは最もDDDに向いている」
最後の方の質疑応答で「Javaは最もDDDに向いている」という言葉がありました。
確かにフルスタック系のWebフレームワークというとRails, Django, Laravelがありますが、いずれも軽量プログラミング言語です。
DDDはドメインモデルをしっかり作り込むので、コンパイルエラーでのチェックもできる静的型付けの方が相性が良いのは同感です。
全体の所感
DDDについて実コードサンプルをベースにした勉強会というのが、非常に良かったです。
断片的なコードではなく、実際に動作する一つのサンプルとして公開されたこと自体にまず大きな意義があります。
また具体例を元に議論しているので質疑でもすれ違うことなく、とても時間効率のよい勉強会に感じられました。
DDDのサンプルを作るのには結構な試行錯誤しているというのを聞いて「ソフトウェアの設計や実装ってそういうもんなんだな」と実感しました。
普段「なかなかきれいに書けないなー」とソースコードを試行錯誤しつつ悩むこともありますが、「ソフトウェアの開発とはそういうものだ」と割り切ることにします。
いずれにせよDDDのサンプルコードから学べることはまだまだありそうなので、時間を作って眺めてみたいと思います。
余談ですが、冒頭の「ブログ書くかもという人いますか?」というアンケートがあったのですが、5人程度しか手が挙がらなかったことに驚きました。
内容的に自分用のメモレベルでしか書ける自信がなかったので、手を挙げられず自粛してしまいました…。
登壇者としては手を挙げてくれたほうが嬉しいはずですし、次からは堂々と挙げられるようにしたいです。
今回もJSUG勉強会の開催関係者の方々、ありがとうございました!