JJUG CCC 2024 Fall
#エンジニアのキャリア #アプリケーションアーキテクチャ #モデリング #ドメイン駆動設計(DDD)
#共有する
Spring ModulithによるDDDとEvent-driven Architectureの実践
Naoya Sugawara
spring modulith はライブラリ
去年の夏にGA
コンセプトが面白い?
話者は巨大モノリス→MSAに取り組んでいたがモジュラモノリスもいいなと思い共有
なぜモジュラモノリスか
マイクロサービスの難しみ、複雑性へのアンチテーゼ的にモジュラモノリスが出てきたか
アーキテクチャごとの特徴を整理しているが、べき論や目標がなくて何を比較しているかわからん
きた「なぜ分割したいのか」
認知負荷を下げる
全体によって圧倒されることなくモジュール内部の詳細にフォーカスすることができる
内部の詳細を無視したうえで、モジュール間の関係性を見ることもできる
構造化ができているということ
つまり低結合・高凝集
例え話が微妙だな←モジュラー性
モジュールは制約
API経由での関係を強制する→低結合・高凝集を実現しやすい
そんなことより目的は「変更容易なアプリケーションを作りたい」←低結合・高凝集←モジュラー性は手段
MSAはシステムを独立管理できるが、そもそも「システムを独立管理したいか?」
開発メンバ数、sloc起因
開発言語を選択しやすくしたい、サービスごとに非機能要求レベルが大きく異なる
DDD x Spring Modulith開発において
SpringModulithとは、ドメイン駆動型のモジュール型アプリケーションを構築するためのライブラリ
モジュールの分割
イベント連携
ディレクトリ構成を決めてくれるのはよいね
テストはどこに置くんだろう
Modulithが「アーキテクチャ機能」として、非公開の機能にアクセスしていないか?など違反を検出してくれる
レイヤ間の依存関係はModulithのスコープ外(ArcUnitを使ってるそう)
APIテスト≒ユースケースのテストになるかな
難しいところ
モジュールの循環依存に悩まされる
イベント連携
同期イベント(通知イベント or 業務イベントかな)
依存関係が逆転する(payment -> notice だったのが、notice -> payment になった)
非同期にするとさらに低結合になる
だが使ってない!!!(SQS+SpringAWSで実現)
順序制御できないそう
イベントがテーブルに依存する?
スケールアウト(複数プロセス)の挙動が怪しい
現場で役立つモデリング超入門
masuda220
若手向け?
モデリングの考え方、こだわりポイントなど
コミューン株式会社の技術アドバイザ?
モデル:特定の様式に則った図を書くことではない
箇条書き / 図 / 表 / 式
わからない → わかる / 伝わらない → 伝わる / 見つからない → 見つかる
簡略化 → 捨象(詳細が必要な場面もあるが、それはモデリングではないところでやる)
目的を持ったモデル / ある視点に基づいた捨像
経済性(簡略に、省力的に、)
モデルが役立つ場面はそれぞれ(文脈次第)
雑なモデルでも十分なことが多い
言葉 / 囲み / 矢印 / 境界線
言葉探しと言葉選び
「流れ」を表現することば→流れの目的や意図を指す言葉?業務名とか?
思考と、書き起こすこと、発音することはそれぞれ脳の働きが異なる
さらに図にすることで表現力が広がる
状況別のモデリング
十分な知識がある時
一つ概念を与えれば勝手に連想が始まる
発散しないよう、シンプルに出力できるよう心がける
タイムボックスを区切る(経済性
視点を変えた複数のモデルを作り、モデル間の整合性を検証する
十分な資料がある時
資料を要約(箇条書き)→図解
図を元に再度読み解いてみる
そしてやはりタイムボックス
知識も情報も不足しているとき
「十分な資料があるとき」とアプローチは同じ。まず資料・情報を集めるところから
あるいは、まず進めてみて経験値を得てから戻ってもいい
タイムボックスを区切る・効果を確認する
一般化された方法は、どこかで誰かが有益だった方法が一般化されたもの
すべての場面で有効とは限らない
とはいえ利用することの経済性は高い
モデリングにより何を得たいのかを明確にする(特徴/要点/分類/流れ)
自分たちの活動に落とし込み、自分たちの「同じ言葉」で語ってみる
パッケージ図、スキーマ図(テーブルをまとめたDBスキーマの意)程度の粒度が経済性が高い
オブジェクト指向プログラミングの教え方・学び方
Masanobu Naruse
タイトルがやらしい
どう伝える?目的からでしょ
OOP>詳細を隠蔽することで保守性を向上させる、動的に振る舞いを変える
もはやドームは単位
再利用性、保守性、複雑さに対応、抽象化の促進(全体の構成や機能を考えられるようになる←詳細を無視できる)、モデリング(だからモデリングが必要)
カプセル化、ポリモーフィズム、継承
OOPは目的と機構が複雑に絡み合って実現している→だから難しい?
どのタイミングから、どの目的・機構を教えるか
実践OOP?
機械語→アセンブリ→手続き型(COBOL)→
レジスタ操作を抽象化したプログラミング言語(と命名の重要性)
じゃんけんを実装
だいたいif分でベタ書き
同じ目的のコードがいくつも出現
同じ目的のコードはまとめてカプセル化
詳細が隠蔽される→利用側は考慮する必要がなくなる→修正が楽になる
初期化・代入→インスタンス化
ポリモーフィズム
インタフェースの話しかしない
複雑さ=条件分岐に絞って確認する→アダプターが増えても対応できる
依存を注入→処理して結果を返す
異なるものを同じように扱える→インタフェース!(厳密には違う?)
拡張に備える(OCP)
プリミティブ型ではなくインタフェースを受け取る
コンストラクタ→初期化(初期値やデフォルトを設定)
隠蔽される実装の詳細も
メンバ変数とかprivateメソッドとか
その後、2つのオブジェクト思考
アランケイ(smalltalk)、ストルヴストルップ(C++)
データと振る舞いをひとつで扱うことで表現力が上がった
アプローチ
問題認知(聴講者にあった問題)
聞く→見る→手を動かす
スモールステップ(高すぎる目標は目標にならない
エビングハウスの忘却曲線→20分で半分
短期記憶は数十秒で消える
実践して定着させる
90/20/8
理解限界、記憶限界、興味を失う限界
ボトムラインを決めるが、習熟度別に別の課題を与える
目的と機構の複雑な絡みを読み解く
ポリモーフィズムの種類(多態性)*wikiに出てるそう
ユニバーサルポリモーフィズム→異なるデータ型に単一の接点を提供する(ダックタイピング)
インクルージョン(サブタイプ)
パラメトリック(ジェネリクス)
アドホックポリモーフィズム→異なる多重定義を一括で表現できる設定を提供する
オーバーローディング
型強制
継承のつかいどころ@現代
テンプレメソッドを作りたい
フレームワークの要件に対応する
型階層の実現
モデリングしていることと同義?
業務アプリケーションを扱うエンジニアは、ポリモーフィズムや継承はどこまで理解しておくべきだろうか?