Seeing is believing

いちエンジニアの日々の興味のあるところ、イベント参加記録、学びの共有を取止めなく※このblogは個人の見解であり所属する組織の見解ではありません

JSUG勉強会 2019その2 Spring BootベースのDDDサンプル徹底解説!に参加しました。

20190218JSUG勉強会 2019その2 Spring BootベースのDDDサンプル徹底解説!

Spring Bootベースのドメイン駆動設計のサンプルコード 徹底解説

  • いつもながら運営の皆さん、登壇者の皆さん、大変勉強になりました。ありがとうございました。

サマリ

  • 増田さん、irofさんによるDDDの設計、実装パターンのサンプル
  • 今はこれにチャレンジしているという話が多々あったので、日々改善を繰り返している。つまりこれ、という答えはない
  • 気づきは多い。現場の状況に応じて少しずつやり方変えていくべき。。

セッション中メモ

  • https://github.com/system-sekkei/isolating-the-domain
  • サンプルは設計、開発で1ヶ月ぐらい
  • 増田亨(有限会社システム設計)、irof(関西Javaエンジニアの会) さん
  • ソースコードはirofさんを始め、関西中心のコントリビュータの方々が書いている
  • DDDをコードで示すことがサンプルを作った目的
  • 質問が具体的になり、考え方の違いがはっきりしてきた
  • ソフトウェアの複雑性とはなんなのか?
    • ビジネスルールの複雑さに影響される
    • 計算をどうやって実現するか?-> 計算をモデリングする(データだけではない)
    • 型志向でプログラミング(Classにこだわる)
  • 詳細は3/22のDevLovePremiumで語る解説する予定
  • 計算(ビジネスルール)を実行するモジュール群とデータの入出力するモジュール群を分けることに拘る
  • 業務系のアプリはトランザクションスクリプトで実装されることが多い
    • ここにドメインモデルをモジュールとして組み合わせるのが良い
  • 開発(設計)の順番
  • POJO
    • BeanValidationは、有効な値の表明であり、自己署名化の一部
    • privete とか finalはこのサンプルでは書いてない。ルールはシンプルで読みやすいようにしている。(可読性 over Java)
    • No getter, no setter , no Lombok, JPA
  • プリミティブをなくす方向で整理したい。ただしパッケージ間の相互依存を無くすためにプリミティブで値のやりとりをしていたという背景もあり。ケースバイケース
  • StreamAPIを使いたいケースもあるが、業務としての表現が貧弱なケースもある。forのほうが読みやすい。
  • 増田さん個人的には、Haskellとかと比べるとStreamに違和感がある。。(Groovyとかでも比較対象として良いかも)
  • IntellJでforとStreamの相互変換はできるので、見比べながらバランスみて決めている
  • DBのDDLの内容とドメインのバリデーションの差異はどう考えたら良いか?マルチチェックすべき内容なので、それぞれで確認すべき
  • パッケージに閉じているのであれば、フィールド直接アクセスするもの良いのではないかと考え始めている
  • バリデーションが権限によって変わるというのは複雑さの一因となっている。Groupバリデーションを使うか、それぞれ分けてしまう
  • DTOはできれば使いたくないが、実際にはかなり大きいJSONを受け取って、ドメインをIFたくさん書いて組み立てるということは現実ありうる
  • オペレーションサービス 計算結果の記録と通知の指示 -> データソース層
  • Serviceクラスは単純1RepogitryへのCRUD。あまりビジネスロジックを描かない
  • coodinatorクラスは上記のserviceクラスを複合するサービス。IF文はこちらに持つ
  • どちらも@Service。パッケージを分ける
  • 増田さんはMyBatis一択派。irofさんはDomaにしたい。。。SQLを生で書くことを優先している。
  • テーブル設計は単独でよりよく見直されるようになるべき。データモデルへのマッピングについて橋渡ししているのがSQL。よってSQL書くのは大事。
  • データベースはイミュータブルデータモデル(川島さんが発表された内容を参照)
    • https://www.slideshare.net/kawasima/ss-40471672
    • 履歴+最新状態のレコード
    • 履歴:事実の記録ーInsertオンリー
    • 最新状態レコード:論理的には不要だが、Insert/Deleteで実現する
    • Update無くしが基本
    • スキーマ名、テーブル名、カラム名を日本語でやるチャレンジをしてみた
    • 外部APIを叩くときは、Transfer層(Outbound)、プレゼンテーション層(Inbound)で詰め替える。
    • DB,SQLでエラーが起きるのは基本はシステムエラーケースを想定。事前にドメインとしてチェックされているのがあるべき
    • トランザクションは意図的に組んでいない。今はやってない。履歴を事実として積み上げたい
  • JIGは自作ツール。以下が確認できて便利
    • 一覧表示での平仄確認
    • パッケージ間の相互依存の確認