Upgrade to Pro — share decks privately, control downloads, hide ads and more …

ソフトウェアアーキテクチャ研修【MIXI 25新卒技術研修】

ソフトウェアアーキテクチャ研修【MIXI 25新卒技術研修】

本スライドは、MIXIの2025年度新卒向け技術研修で使用された資料です。
 
MIXI 2025新卒技術研修
『ソフトウェアアーキテクチャ研修』
 
▼動画
https://youtu.be/u3HhiticY4o
 
───────────────────────────────
※皆様へのお願い※ 資料・動画・リポジトリのご利用について
───────────────────────────────
公開している資料や動画は、是非、勉強会や社内の研修などにご自由にお使いいただければと思いますが、以下のような場でのご利用はご遠慮ください。
- 受講者から参加費や授業料など金銭を集めるような場での利用
(会場費や飲食費など勉強会の運営に必要な実費を集める場合は問題ありません)
- 出典を削除または改変しての利用

Avatar for MIXI ENGINEERS

MIXI ENGINEERS PRO

April 25, 2025
Tweet

Video

More Decks by MIXI ENGINEERS

Other Decks in Technology

Transcript

  1. 22 ©MIXI 講師紹介 登内 雅人 とのうち まさと 2020 年度新卒入社 •

    業務:開発本部 たんぽぽ室 AIモデリング G • サッカー映像解析、アナリスト支援アプリ開発、 FC東京アプリ開発、みてねでの画像解析 • ML系の研究開発、MLOps、Backend、Frontend • Python、Go、Flutter • 趣味:サッカー観戦、格闘技、将棋、個人開発 Docbaseマイページ github pages: https://github.com/tonouchi510
  2. 4 ©MIXI ⽬次 • ソフトウェアアーキテクチャとは • アーキテクチャを学ぶ必要性 • モノリシックアーキテクチャ •

    マイクロサービスアーキテクチャ • モノリス vs マイクロサービス?? • 疎結合を実現するための⽅法論の紹介 • ドメイン駆動設計(DDD)の解説 • DDD実践演習
  3. 6 ©MIXI アーキテクチャとは 対象の構造や、対象を構成する部品と部品同⼠の関係を⽰す設計図。 システム全体のアーキテクチャ(インフラ構成)の場合 • Webサーバー • APIサーバー •

    認証基盤 • データベース • APIゲートウェイ • クラウドサービス • etc ソフトウェアアーキテクチャではこの部分の構造の設計⽅針を定義する
  4. 8 ©MIXI ソフトウェアアーキテクチャとは ソフトウェアアーキテクチャと聞いてよく出てくる⽤語 • クリーンアーキテクチャ • レイヤードアーキテクチャ • オニオンアーキテクチャ

    • ヘキサゴナルアーキテクチャ • モノリシックアーキテクチャ(モノリス) • マイクロサービスアーキテクチャ ※あとでまた触れます。
  5. 10 ©MIXI アーキテクチャを学ぶ必要性   ⾮機能要件を実現するため なぜソフトウェア開発において、アーキテクチャ‧設計が重要か? • 機能要件 ◦ ユーザやシステムが「何をできるか」に関する要件。機能そのもの。 •

    ⾮機能要件 ◦ システムが「どのように動作するか」など機能に限らない要件(品質や性能等)。 ◦ 実⾏時の品質:パフォーマンス‧スケーラビリティ、可⽤性‧信頼性、セキュリティ ◦ デプロイ時の品質:デプロイ‧ロールバックの容易性 ◦ 開発時の品質:保守性(メンテナンス‧機能改修、新機能開発の容易性) ソフトウェア開発では、単にエンジニアを増やせば 開発速度が上がるわけではないという現実がある 「ユーザアカウントを作成でき る」、「注文できる」など。
  6. 11 ©MIXI アーキテクチャを学ぶ必要性 https://www.oreilly.com/library/view/accelerate/9781457191435/ 実際、Accelerateという、2000社以上の開発組織の調査 結果をまとめた⽂献がある。 ‧横軸:エンジニアの数 ‧縦軸:1⽇のデプロイ数 エンジニアが単に増えるだけではパフォーマンス(⽣産 性)は上がらず、鈍化することさえある。

    High Performersは⼈数とデプロイ数をほぼ線形を維持。 => High Performance組織としての⼟台が必要。 パフォーマンス向上には、「プロセスの改善( DevOps的な話)」や「組織作り(心理的安全性)」なども重要。 ただし、それだけではどうにもならない問題もある => 技術での解決が必要
  7. 14 ©MIXI 密結合と疎結合 ソフトウェアアーキテクチャや設計の⽂脈においては、”ソフトウェアの構成要素同⼠ の結合度合い”が重要な設計の観点となる。 • 密結合(⼀般的に良くない状態) ◦ クラスやモジュールが互いの内部構造や具体的な実装に依存している状態 ▪

    例:他のクラスの変数を直接参照したり、インスタンス⾃体を変数に持つなど • 疎結合(⼀般的に良い状態) ◦ クラスやモジュールが互いの内部構造や具体的な実装に依存していない状態 ▪ 「インターフェースや抽象のみへの依存」、「集約」など
  8. 15 ©MIXI 密結合した実装の例 例:「家族アルバム みてね」のようなアルバムサービスを想定 仕様:アプリのユーザはアルバムの作成と参加が可能 => コード上では機能要件は満たしている UserクラスがAlbumクラスに依存している =>

    例えば Albumのコンストラクタが変更されたら `create_album` が壊れる可能性がある ※以降もあくまで疑似コードなので、プログラムとしての正しさは仮 定してません。
  9. 16 ©MIXI 密結合した実装の例 Albumの仕様変更:`follower_scope`を追加(参加者のアクセス権制御) • 定数定義が変わったら依存先が壊れる ◦ 1 がフル権限になったら`create_album`が壊れる •

    オブジェクトがどこでどう変更されるかが分からない ◦ UserがAlbumのインスタンスを持っていて、やろうと思えばメンバ変数にも直接アクセス‧変更できる ◦ バリデーション(整合性チェック)の実装が分散しやすい ▪ そうなると別の場所ではバリデーションをやり忘れたり、バリデーションの変更漏れも起きやすい ▪ ※本来はAlbumクラスにscope変更のメソッドを⽣やすなど、⼀箇所にできると良い
  10. 19 ©MIXI アーキテクチャを学ぶ必要性 規模が⼤きくなると遅くなる原因 • コード量‧機能量が多いことによる認知負荷増 ◦ どのコードや機能がどこに依存しているのかわからなくなる ◦ (メンバーの離職等により)誰も把握していないコードも増える

    ◦ => 時間とともに、もはやそのソフトウェアを⼗分に理解することが不可能になる • 障害やバグの数も増える ◦ つまり、本質的な機能改修に取り組める時間がどんどん失われていく • 組織の⼈数が増えることによるコミュニケーションコスト増 ◦ リリースなどの調整先が増える、コンフリクトも増える ※特に前スライドのように複雑なものに複雑なものを追加する時は顕著になる
  11. 20 ©MIXI アーキテクチャを学ぶ必要性 https://www.oreilly.com/library/view/accelerate/9781457191435/ 以上を踏まえると、このグラフが起こりうる現実 としておかしくないと理解してもらえるはず。 • 既存のエンジニア ◦ 勤務時間における会議や障害‧バグ対

    応、コンフリクトの割合が増える ◦ 本質的な業務に取り組めない • 新規参⼊エンジニア ◦ 読まなければいけないコードが多すぎ て把握しきれない ◦ ⼀⼈⽴ちできるまで時間を要する アーキテクチャを学ぶ必要性: • エンジニアの増加に対するパフォーマンスの最⼤化を⽬指す • 機能改修の速さはビジネス観点では ”競合優位性(参⼊障壁)” となる 要点
  12. 21 ©MIXI (再掲)⽬次 • ソフトウェアアーキテクチャとは • アーキテクチャを学ぶ必要性 <= ここまで終了 • モノリシックアーキテクチャ

    • マイクロサービスアーキテクチャ • モノリス vs マイクロサービス?? • 疎結合を実現するための⽅法論の紹介 • ドメイン駆動設計(DDD)の解説 • DDD実践演習 質問あれば受け付けます。
  13. 22 ©MIXI 補⾜:エンジニア組織のパフォーマンス計測 組織の開発のパフォーマンスを測るのは実際にはかなり難しい。 デプロイ数で計測するというのは⽅法の⼀つ。 有名なものとしては、Four Keysがある。 リファクタリング‧リアーキテクチャのKPIに設定し、そこの改善を⾒ると⾯⽩そう。 コードがコミットされてか ら本番環境で正常に機能す

    るまでの時間 リードタイム コードを本番環境にデプロ イまたはリリースした頻度 デプロイ頻度 変更失敗時にサービス復元 までにかかる時間 平均修復時間(MTTR) リリース後に障害や不具合 等により修正を⾏う必要が ⽣じた割合 変更失敗率
  14. 23 ©MIXI ソフトウェアアーキテクチャとは(再掲) ソフトウェアアーキテクチャと聞いてよく出てくる⽤語 • クリーンアーキテクチャ • レイヤードアーキテクチャ • オニオンアーキテクチャ

    • ヘキサゴナルアーキテクチャ • モノリシックアーキテクチャ(モノリス) • マイクロサービスアーキテクチャ ここから、まずマクロレベルの設計の話として、モノリスとマイクロサービスについ ての概要と、アーキテクチャ選定に関する考え⽅の解説をします。 こちらはあくまで⼀つの モノリス or サービスの 内部の構造の話 まずこちらを扱う
  15. 26 ©MIXI モノリシックアーキテクチャ ⼩規模アプリケーション開発の場合 • テストがしやすい ◦ サーバー間通信などもなく、E2Eテストも簡単 • デプロイしやすい

    ◦ 複雑なコンポーネントに分かれていない、シングルバイナリ • スケーリングが簡単 ◦ アプリケーションを複数インスタンスで実⾏するだけ • 開発もしやすい ◦ コードベースが単⼀(やろうと思えば全てのクラス‧メソッドにアクセスできる) ◦ DBも単⼀(全てのデータを参照できる、整合性の担保も簡単) 全てが⼀箇所であることからくる利点
  16. 27 ©MIXI モノリシックアーキテクチャ ⼤規模アプリケーション開発の場合 • テストが⾟い(実⾏時間等) ◦ ⼀部の機能を修正しただけなのに全体のテストが動く • デプロイが⾟い

    ◦ ⼤⼈数で同じコードベースを触るので競合が増える • スケーリングが⾟い ◦ 異なるリソース要件の機能が混在するため • 開発がしづらい ◦ コードベースがデカすぎて⼀⼈のエンジニアが理解できるキャパを超えてしまう ◦ 古い技術スタックに縛られる(依存する範囲が広いため) • 信頼性低下 ◦ バグや障害を起こしやすく、発⽣時に特定しづらくなる ◦ 依存箇所が多いライブラリのアプデ難易度も上がる メリットだった部分が 全て反転してくる アプリケーション開発において、規模が拡⼤するとあらゆる問題が出現してくる
  17. 30 ©MIXI マイクロサービスアーキテクチャ マイクロサービス(の理想状態)では、以下のような恩恵が受けられる。 • テストが効率的 ◦ 変更したサービスだけテストすれば良い • デプロイがしやすい

    ◦ 他のサービスの開発者の作業に影響されない • スケーリングが効率的 ◦ サービスごとに、リソース要件に合わせてスケーリングできる • 開発‧メンテナンスがしやすい(保守性) ◦ ⾃分の担当するサービスに関する知識だけあれば良いので、認知負荷が低い ◦ 依存範囲が狭いため、技術スタック‧ライブラリの更新がしやすい(サービスごとに可能) • 信頼性向上 ◦ コードベース、DB、インスタンス等が分かれているため、障害発⽣時の 影響を限定できる、原因の特定がしやすい あらゆる事柄を個別の サービス単位で考えらえる ようになる恩恵
  18. 32 ©MIXI マイクロサービスアーキテクチャ マイクロサービスアーキテクチャの⽋点 • マイクロサービスを理想通り実現するためには多くの専⾨知識が必要 ◦ 様々な設計パターンに関する知識 ◦ 分散システム特有の問題への対処

    • サービスへの適切な分割を考える難易度が⾼いこと ◦ 他サービスの開発に影響しない分割(疎結合)をする必要がある => 具体的にマイクロサービスの構築で考えなければいけないことをみていきます
  19. 33 ©MIXI マイクロサービスアーキテクチャ 「サービス間通信はどうするか?」 サービスに分かれることになるので、サービス間でやり取りが必要となることがある。 せっかくサービスで分かれているのに、これまで通り同期APIで呼び出していては可⽤性が 上がらない。 例えば「家族アルバム みて ね」の例でいうと、写真アップ

    ロード時に AIによる写真の解 析処理が動くが、解析処理の 遅延や失敗でアップロード機 能自体を利用不可にしたくな い。 => 非同期通信にする => (可⽤性を上げたければ)出来るだけ⾮同期のメッセージング基盤等でやり取りする設計   に変える必要がある。
  20. 36 ©MIXI 結果整合性の⾟み マイクロサービスではサービス間のデータ整合性は結果整合性を前提としているのでそれに伴う 問題の考慮は当然必要になってくる。 ⾮同期更新なので、DB研修で習ったような「ダーティリード」、「ノンリピータブルリー ド」、「ファントムリード」に類似するような問題が発⽣し放題。その他の問題も多い。 • 注⽂処理は成功しているのに在庫情報が変わっていない(更新遅延) •

    在庫確認してから注⽂処理を確定し、その後在庫を引き落とそうとしたらなかった • 決済で処理が失敗したが、在庫の修正前(確定前)の値を読んでしまう (対処できるものもあるが) これらが致命的になるデータの場合は、単⼀のサービスに含める必要がある。  多くの場⾯でトランザクションの分離性よりもパフォーマンスが重要視されるようになってきていると   はいえ、データの整合性は事業の存続に関わる重⼤な問題であり、正確に判断するための知⾒が必要。
  21. 40 ©MIXI マイクロサービスの失敗 ここまで聞くと、マイクロサービス化はかなり難易度が⾼いことがわかる => 実際、マイクロサービス化 / サービス切り出しの失敗例は数多くある 失敗例 •

    組織の構造にあっていない ◦ サービスごとに担当する⾃⽴したチームがいなければ、サービスだけ分かれていても効果が薄い • 内部構造をそのままにサービスへの分割を⾏ってしまっている ◦ 先ほども説明したように、モノリスに課題を感じているからといって、単にサービスに切り出すだ けでは問題は解決しない(それどころか悪化する可能性も) • マイクロサービス化が⽬的になってしまっている ◦ アーキテクチャはあくまで⾮機能要件を実現するための⼿段  失敗すると、頑張ってサービス分割してもメリットを享受できずにデメリットだけ追加される可能性も...  => しっかりとした⽬的と知識を持って進めることが⼤事。
  22. 43 ©MIXI 補⾜:コレオグラフィベース サーガ XXX サービス API YYY サービス API

    ZZZ サービス API ABC サービス API それぞれで非同期にローカルトランザクションが実行される(結果整合)。 XXX サービス API YYY サービス API ZZZ サービス API ABC サービス API ここで処理が失敗 補償トランザクションのパブリッシュ 補償トランザクション 打ち消すための トランザクション実行 打ち消すための トランザクション実行 • サーガの参加サービス⾃⾝が⾃律的に連携し合う • 失敗した場合の補償トランザクションのリクエストも各サービスが担う
  23. 44 ©MIXI 補⾜:オーケストレーションベース サーガ XXX サービス API YYY サービス API

    ZZZ サービス API サーガ オーケストレーター ABC サービス • サーガに参加する各サービスへの制御を中央集権的に担う • リクエストや補償トランザクションの管理
  24. 47 ©MIXI モノリス vs マイクロサービス?? そもそもどちらか⼀⽅ではなく、基本的には共存することが多い。どちらも活かす。 スケールするプロダクト開発では、以下のような流れになるのが⼀般的。 • 初期フェーズ: ◦

    まずは、⼩規模少⼈数で利点が多い”モノリス”で開発を始める • 組織規模拡⼤後: ◦ 必要に応じてマイクロサービスも検討するようになる ◦ 分割する必要のあるものからサービスに切り出されていく このように、モノリスとマイクロサービスが共存している状態になるはず。 特定のアーキテクチャスタイルやデザインパターンを採⽤した からといって、全てそれに従わなければいけないわけではない。
  25. 48 ©MIXI モノリス vs マイクロサービス?? 課題感(その1): • モノリス⾟いのでマイクロサービスにしたい。 • でもサービス間のデータ整合性の問題が⽣じるのは厳しいかも。

    対処法:  => データ整合性の重要度が低い部分だけ切り出せば良い • ここでも、マイクロサービスアーキテクチャを採⽤したら何でもかんでも細かく サービスに切り出さなければいけないわけではない • サービスに切り出してより⾟くなるのは本末転倒 • 利点が⽋点を上回ると判断した部分だけサービスに切り出せば良い
  26. 49 ©MIXI モノリス vs マイクロサービス?? 課題感(その2): • 他サービスのデータを参照したいが、毎回サービス間通信を挟むのは⾟い。 • パフォーマンスや可⽤性に問題が⽣じてしまう。

    対処法:  => データのコピーを持てば良い 他サービスの必要となるデータをあらかじめ⾃サービス内に同期しておき、そこを参照す るよう変更する。こうすることでサービス間通信が不要になる。 ※これ⾃体はマイクロサービスで⼀般的な設計パターン
  27. 50 ©MIXI モノリス vs マイクロサービス?? 課題感(その3): • 他サービスのデータを同期するのも同期遅延による不整合が怖い。 ◦ 例:注⽂管理サービスで在庫管理サービスのデータのコピーを同期しているが、同期

    遅延で在庫管理サービス側のDB(正規)が空なのに注⽂受付してしまった。 対処法:  => Read権限のみ許可して直接他サービスのデータを参照すれば良い 他サービスのDBに依存するのでもちろん可⽤性の観点では低下するが、同期遅延の⽅が問題に なると判断すれば検討の価値がある。マイクロサービスだからといって必ずしもDBを分離する 必要はない。 ※ロジックまで密結合になりすぎないように注意
  28. 51 ©MIXI モノリス vs マイクロサービス?? 課題感(その4) • マイクロサービスを⽬指すほどのモチベはないが、事業拡⼤に伴ってエンジニア を増やしても⽣産性が上がらないのは厳しい... 対処法:

     => コード上の疎結合さえ実現できていれば、上記⽬的は達成できる可能性が⾼い  => モノリスでも可(モジュラーモノリス) エンジニアの増加に対する⽣産性向上の観点でいえば、サービスまで分けずとも、モ ジュール分割によって分担したり認知負荷の軽減ができれば⽣産性向上は⾒込める。 そこを優先して他の要件‧サービス切り出しのメリットは妥協するとか。 どこを達成したいか、どこを優先するかという考え⽅が⼤事。
  29. 52 ©MIXI モノリス vs マイクロサービス?? ここまでまとめ: • ここまで話したように、モノリス/マイクロと⾔ってもやり⽅は⾊々あり、どっちが良 い悪いではなく、トレードオフであり、適宜使い分けるものです。 •

    特定のアーキテクチャスタイルやデザインパターンを採⽤するからといって、定義通 りに作る必要はなく、全ての箇所で従わなければいけないわけでもありません。 ◦ => そこを⽬指すと⼿段が⽬的化してしまう • アーキテクチャはあくまで⼿段であり、⾃分たちのチームの課題がどこにあって、何 を解決したいかが重要です。 ◦ 解決するための⼿段をみて、それを実⾏する利点が⽋点を上回れば実⾏すれば良い
  30. 53 ©MIXI (再掲)⽬次 • ソフトウェアアーキテクチャとは • アーキテクチャを学ぶ必要性 • モノリシックアーキテクチャ •

    マイクロサービスアーキテクチャ • モノリス vs マイクロサービス?? <= ここまで終了 • 疎結合を実現するための⽅法論の紹介 • ドメイン駆動設計(DDD)の解説 • DDD実践演習 質問あれば受け付けます。
  31. 54 ©MIXI 補⾜:マイクロサービスを検討する場⾯ モジュラーモノリスでも⼗分という話もしたが、例えば以下の場⾯など。他にもあるかも。 • 機械学習モデルを動かすモジュールなど、リソース要件が⼤きく異なるもの ◦ 元々ステートレスな処理でありサービスへの切り出しも容易 • 技術スタックを新しくしたい場合

    ◦ 例:Perlで作られた古いシステムに新しい機能を追加したいが、現在ではPerlのエンジニア は市場にほとんどいない。 ◦ => このような場合は致命的であるのである程度デメリットを許容してでも、別サービスとし て切り出し、既存の技術スタックに縛られずに作る⽅が良いかも • 横展開する汎⽤的なシステムを作る場合 ◦ 例えば、あるプロダクトにポイント機能を追加したいとして、社内の他のプロダクトにも同 様にポイント機能を提供する可能性がある場合、独⽴して動くサービスとして開発しておく と使いまわせて良いかも? • 外注する場合など。別組織なので独⽴して開発できるものを任せられると効率的
  32. 56 ©MIXI 設計に関する各種⽅法論 ここから、具体的に疎結合を実現するための⽅法について解説していきます。 本当に多くのものが提唱されてるので、その内⼀部を独断と偏⾒で以下に整理してみます。 カテゴリ 具体例 主な目的や役割 アーキテクチャスタイル クリーンアーキテクチャ,

    オニオン アーキテクチャ, マイクロサービス, モ ノリス ソフトウェア全体の構造・依存関係の流れ、分 割の方針を決める 設計思想・アプローチ オブジェクト指向, ドメイン駆動設計 (DDD), CQRS 設計や実装、分割に関する思想・指針。人間が 理解しやすい実装への指針。 設計原則 SOLID原則, DRY, YAGNI クラス・モジュールの内部構造や依存のあり方 に関するもの 設計指標 モジュール結合度, モジュール強度 (凝集度), LCOM 設計の品質を評価する軸、設計改善の指針に なる 設計パターン Repository, Factory, Saga, Entity 具体的な実装方法についてのテンプレート
  33. 59 ©MIXI 設計の⽅法論に関する注意点 これらの考え⽅を参考にするだけでも良い設計に近づける。ただし以下に注意。 • これらの指標や原則に従うことを⽬的化するべきではない ◦ 全てのモジュール強度最強‧結合度最弱にすることが必ずしも良いわけではない ◦ 必要以上にやりすぎてしまうとかえって書きづらく、読みづらくなり本末転倒

    • 設計の⽅法論はパターンやテンプレートとして使うべきではない ◦ 重要なのは⽂脈、背景、⽬的(これを知った上で使うと効果的) ◦ パターンにとらわれるとやりすぎという状態に陥ってしまいがち ▪ マイクロサービスで例えると、必要以上にサービスに切り出してしまっている状態 • 単にこれに従うだけでは良い疎結合が達成できるわけではない ◦ そもそも「単⼀機能‧責務」とは何?どれくらいの範囲か? ◦ これだけだとどういうまとまりで開発を分担すれば良いか分からない => まずは全体の構造やモジュール分割の⼤⽅針が必要。
  34. 61 ©MIXI オブジェクト指向 データ構造とそのデータに対する操作(振る舞い)を⼀つのまとまりとして扱い、それらの関係 からシステムを構築する⽅法論。 ある役割(機能)を持った”モノ”ごとにクラスを分割するという、モジュール分割に関する指針 の側⾯も。 => ⼈間が理解しやすい分割の概念が⼊る 概念

    説明 クラス オブジェクトの「設計図」に値するもの。プロパティ(属性)とメソッド(振る舞 い)を定義。 オブジェクト クラスから生成された「実体」。状態と振る舞いを持つ。 カプセル化 データと振る舞いを一つのクラスにまとめ、内部を隠蔽する。 継承 既存のクラスを元にして、共通処理を再利用・拡張できる。 ポリモーフィズム 同じインターフェースで異なる振る舞いを実現する。差し替え可能。
  35. 63 ©MIXI 設計パターン適⽤の失敗例 ここまで話した設計概念を”なんとなく取り⼊れる”だと失敗する。 • DRY(Don’t repeat yourself)やりすぎて逆に⾟い ◦ 重複を減らすためといって、なんでもかんでも共通化するべきというわけではない

    • 機能的強度を⽬指して、機能を細分化しすぎてしまい逆にコードを把握しづらい ◦ SNSの例:「フォローリクエストできる」「フォローリクエストを承認できる」を別 機能として別クラスで実装する? ◦ やりすぎると、ファイルやクラスが別れすぎて逆にコード追いづらいことも ◦ ⼈間が把握しやすいことが⼤事なので、その意図であえて下げる判断も⼤事 • 何らかのアーキテクチャスタイル採⽤しているのにドメイン層に知識が全くない ◦ データを持つクラスが定義されているだけ => ドメインモデル貧⾎症 ◦ ドメインルール、ビジネスロジックがドメイン層に集約させるべき => しっかりとした⽬的と設計概念への理解が重要
  36. 64 ©MIXI ここまでまとめ(前半) • これらのように、設計に関する⽅法論は数多く提唱されています。先駆者たちの これまでの研鑽が反映された指針として、⾮常に参考になるので、興味あると 思った部分はもっと深ぼって学んでみてください • ⼀⽅で、あくまで⽅法論の⼀つであり、それに従うことを⽬的にするべきでは ありません。⽬的はあくまで⾮機能要件であるべきです。

    • ほとんどの⾮機能要件の実現は、疎結合化によって達成できます ◦ ただし、必要な疎結合のレベルは⽬的の⾮機能要件によって変わる ◦ 加えて、「どこをどのレベルの疎結合にするべきか」は各々の開発チームごとに 異なるという認識が重要 ◦ ⽣産性向上のためには、⼈間にとって意味のあるまとまりを持った疎結合が⼤事
  37. 65 ©MIXI (再掲)⽬次 • ソフトウェアアーキテクチャとは • アーキテクチャを学ぶ必要性 • モノリシックアーキテクチャ •

    マイクロサービスアーキテクチャ • モノリス vs マイクロサービス?? • 疎結合を実現するための⽅法論の紹介 <= ここまで終了 • ドメイン駆動設計(DDD)の解説 • DDD実践演習 質問あれば受け付けます。その後休憩に⼊ります。
  38. 69 ©MIXI 演習問題1 問:あなたは密結合しているシステムのマイクロサービス化に着⼿しようとしています。 「システムのコアとなる機能やロジックが集約された”巨⼤クラス(密結合)”」から、「あまり 使われておらず他との依存が少ない⼩規模なクラス」まで様々な機能やクラスが存在します。 ここで、どちらのクラス‧機能からサービスの切り出しに取りかかるべきでしょうか? 回答例: • ⼩さく依存の少ないクラス(すでに疎結合)

    ◦ 切り出しやすい。ただし、更新頻度が少ないためそもそも開発効率を上げる意味がない ◦ 第⼀歩としての成功事例を作るためならあり • あらゆる機能改修に関わってくる巨⼤クラス(ゴッドクラス) ◦ 今後の開発の効率化に繋がり、切り出す効果は⾼い ◦ ただし、依存先が多いため、疎結合化するにも全体の把握と多くの調整が必要
  39. 73 ©MIXI 演習問題3 問:あなたの開発チームでは出前サービスを開発しています。 ここで、競合サービスを作っている他社のエンジニアから、出前サービスでは「注⽂管理」、 「配達」、「決済」で、ロジックを明確に分けて考えることが可能なのに、このシステムでは密 結合になっているためリファクタが必要と指摘されました。どうするべきでしょうか? 回答例: 競合他社と事情(組織構成‧技術スタックなど)が同じとは限らないため、⾃社でも分割が最適 とは限らない。

    例えばその競合他社とは類似していても強みとする機能が異なる場合、機能改修や更新頻度は変 わることになる。開発頻度が低いモジュールをあえて分割しても効果は薄い。 補⾜:外部の⼈から「このソフトウェアは密結合だ」と⾔われても、内部の⼈達が問題に感じて いないならその組織にとっては必要⼗分。あくまで開発を担当するチーム内で基準を持つべき。
  40. 76 ©MIXI (再掲)⽬次 • ソフトウェアアーキテクチャとは • アーキテクチャを学ぶ必要性 • モノリシックアーキテクチャ •

    マイクロサービスアーキテクチャ • モノリス vs マイクロサービス?? • 疎結合を実現するための⽅法論の紹介 • ドメイン駆動設計(DDD)の解説 • DDD実践演習 ⼀旦休憩を挟みます。
  41. 78 ©MIXI ドメイン駆動設計の背景 • ここまで話してきたように、ソフトウェア開発は複雑で⾊々な問題を抱える。 • ドメイン(業務領域‧問題領域)⾃体が本質的に複雑であることが要因の⼀つ。 ◦ ⼈間の⾏う⼊り組んだ業務や活動をプログラムに落とし込む作業なので、当然と⾔え ば当然。

    • 何もしないとソフトウェアはどんどん密結合し複雑になっていってしまう。 ◦ ビジネスルールがコードのいたるところに散在してしまう • そこからさらに複雑なドメインが現れたら、⼿も⾜も出せなくなる。 ◦ ※例えば、AI等による技術⾰新で業務フローやユーザ⾏動に重⼤な変化が起きたとし ても、そのレベルの変更をソフトウェアに反映させるのは不可能になっているかもし れない => 次から次に機能を満たすコードを作成するだけでなく、「ドメインに対する理解」と「モデ リング」にしっかりと取り組むことが重要
  42. 79 ©MIXI ドメイン駆動設計の⽤語集 • ドメイン(Domain) ◦ システムが解決しようとする業務領域‧問題領域のこと ◦ 例:ECサイト(注⽂管理‧在庫管理)、SNS(投稿、フォロー、リアクション)など •

    ドメインエキスパート ◦ その業務の専⾨家 ▪ 医療システムであれば医者、看護師、医療事務 ◦ ⼀般ユーザ向けアプリであれば、ユーザの⾏動や背景を深く理解している⼈ ▪ PO、PMなど • ユビキタス⾔語 ◦ 開発者とドメインエキスパートなどの参画者が共通して使う⾔葉 ▪ コミュニケーションにおける⾔語の認識のズレが起きるのを防ぐ ◦ モデル、クラス名、関数名など、コード上でもそのままその⾔語が使われる ※toBの業務システムとtoCのビジネスで若⼲解釈に違いはある。今回は主にtoC向けに解説。
  43. 80 ©MIXI ドメイン駆動設計の概要 (その名の通り) ドメインを深く理解し、それを中⼼にシステムを組み⽴てる設計思想。 ※開発プロセスやコミュニケーション等にまで踏み込んだ思想であるが今回は省略。 DDDを取り⼊れることにより、ソフトウェアは以下のように変わる • ドメインモデルに責務が集中する ◦

    プログラムで動作するドメインのルールや振る舞いが全て書かれている ◦ => つまり、コードがドキュメントになる(常に最新版を担保) • ドメインモデルによるモジュール分割 ◦ 変更に強く、意味のある単位での疎結合化
  44. 81 ©MIXI 基本的な流れ • ドメインモデリング • 実装 • レビュー‧ドメインの理解 これを繰り返していくことで、ドメイン

    モデルが洗練されていく。 ※今回は省略してますが、このサイクル ⾃体もDDDにおいてはかなり重要な側⾯ を持ちます。 ドメイン駆動設計の流れ ドメイン モデリング レビュー・ ドメインの理解 実装 イテレーション
  45. 82 ©MIXI ドメインモデリング ドメインエキスパートの中にある知識を、必要な性質を取捨選択して抽象化し、ソフ トウェアで扱えるようにするための作業(設計にあたる)。 モデリングの流れの例 • ドメインエキスパートと対話し、ドメインについて理解を深める ◦ どういった概念‧ルール‧関係があるのかを整理する

    • 名詞や動詞に注⽬しながら⽤語を洗い出す(ユビキタス⾔語) • UMLなどでモデルと関係を整理する • モデルをドメインオブジェクトと対応づける ◦ ドメインオブジェクト:モデルをソフトウェアで動作するモジュールとして表現 オブジェクトには、振る舞いと守るべきルールがある。単なるデータスキーマではな く、ドメインモデルにそういった知識を反映させていくことが重要。 なんとなくクラスを定義 するのではなく、こういっ たモデリングをしっかり やろうというのが DDDで す。
  46. 85 ©MIXI ドメイン駆動設計のパターン(構成要素) ドメインの知識を表現するための構成要素 エンティティ 値オブジェクト 集約 ドメイン サービス 仕様

    アプリケーションを実現するための構成要素 アプリケーション サービス リポジトリ ファクトリ 利用して 組み立てる • モデリングした知識を⼀箇所に集中させる • それを活⽤してアプリケーションを組み⽴てる
  47. 86 ©MIXI 値オブジェクト(Value Object) ライフサイクルのないオブジェクト。値に関する知識を表現する。 • こういった何らかのルールがあるものは、プログラミング⾔語のプリミティブ型(Int, Float, Stringなど)ではなく、独⾃の型として定義して知識を組み込むのが良い •

    必要に応じて、振る舞い(メソッド)を定義することもある 値オブジェクトの例 ルール 住所 都道府県・市区町村・番地など 名前 姓と名から成る メールアドレス 特定のフォーマットがある 座標 (x, y)の数値の組み合わせで表現される
  48. 88 ©MIXI 値オブジェクト(Value Object) 修正コード例(擬似コード): ※便宜上Go⾔語に変わってます。 • FollowerScope型を定義し、コンストラクタにルール(バリデーション)を記述 ◦ FollowerScopeのインスタンスが存在している時点でバリデーション通っていることが保証される

    ため、他の場所でバリデーションする必要がなくなる(※Goの場合は紳⼠協定が必要) • このように、値オブジェクトに意味‧ルールを持たせた⽅が⼀箇所にまとまり、把握しやすい
  49. 91 ©MIXI 集約(Aggregate) ⼀貫性を保つべきエンティティや値オブジェクトをひとまとめにしたもの。 • 集約パターンにおける実装上の制約 ◦ 集約ルート(Aggregate Root)を外部とのやりとりの唯⼀の窓⼝とする ▪

    内部のオブジェクトには直接外からアクセスさせない ◦ 他の集約のオブジェクトを直接参照することを禁⽌(IDのみ許可) ▪ 先ほどの例だと、UserクラスがAlbumクラスのコレクションを保持している が、これを禁⽌する • => 集約を境界としてモジュール分割される(疎結合化)
  50. 93 ©MIXI その他 • ドメインサービス(Domain Service) ◦ エンティティや値オブジェクトに属さないドメイン知識に関するロジック(関数)を表現 ◦ ※例えば、存在確認‧重複確認のメソッド(Exists)は、エンティティ⾃⾝の振る舞いとし

    て定義するのは違和感であるため、ドメインサービスとして実装する。 • リポジトリ(Repository) ◦ データの永続化や読み込みのためのインターフェース ◦ DDDにおいては「集約」を保存‧取得する役割 ◦ そのため集約単位で設計するのが基本 • ファクトリ(Factory) ◦ 複雑なドメインオブジェクトの⽣成処理をカプセル化するための要素 ◦ コンストラクタで記述するのでは重すぎる⽣成処理の場合はファクトリを使う • 仕様(Specification) ◦ 複雑なドメインオブジェクトのバリデーションルールをカプセル化するための要素
  51. 94 ©MIXI ドメインモデルを隔離するための⽅法 アーキテクチャスタイルを採⽤し、全体の構造と依存の⽅向を整理する => ここではオニオンアーキテクチャを採⽤(Domain層からInfra層への依存を無くせるため) • Domain層 ◦ ドメインオブジェクトを実装

    ◦ ドメイン知識がこの層に集中する ◦ リポジトリのインターフェースもここで定義 • Application層 ◦ ドメインオブジェクトとInfra層(DIP)を 活⽤し、ユースケースを組み⽴てる • Infrastructure層 ◦ ドメインオブジェクトの永続化‧取得を担う ▪ I/O両⽅ドメインオブジェクト(DAO返さないよう注意) ◦ リポジトリ、ファクトリなどの実装がある
  52. 95 ©MIXI オニオンアーキテクチャ どうやってコード上でオニオンアーキテクチャを実現するか?(Go⾔語の例) サンプルリポジトリ: => https://github.com/tonouchi510/golang-ddd-layout Go⾔語の特徴 • パッケージ単位のアクセス制御⽅式

    ◦ パッケージ外部では public のみアクセス可能で、パッケージ内部では他オブジェクト の private 変数‧メソッドにもアクセスできる => 集約の実装にも適している ◦ 各レイヤ(層)をパッケージで分けることで、他の層から内部データにアクセス不可 能にできる • 静的型付け⾔語である • => 設計上のルールを、紳⼠協定でなく、コード(仕組み)で担保できる
  53. 96 ©MIXI オニオンアーキテクチャ こういったアーキテクチャスタイルを採⽤した時には、各レイヤ(層)をまたぐ際に、データを 別のオブジェクトに詰め直す処理がある。 • リポジトリ(インフラ層) ◦ 内部では使⽤するORMライブラリのデータ構造を扱うことになるが、返却時はドメインオブ ジェクトに詰め直す

    => 他の層でDB操作をさせないため ◦ ⼊⼒もドメインオブジェクトにすることで保存前のバリデーションが不要に • アプリケーション層 ◦ 内部ではドメインオブジェクトを触っても良いが、上位層に返却する時にはDTO(ロジック を持たない構造体)に詰め直す必要がある ◦ 意図しない場⾯でドメインオブジェクトに対する操作が⾏われないため ⾯倒な部分で敬遠されがちだが、紳⼠協定でなく仕組みで防ぐために重要なこと。 今ならAIがほぼ⾃動⽣成してくれるはず。
  54. 97 ©MIXI オニオンアーキテクチャ オニオンアーキテクチャを利⽤することで得られる利点を以下に整理します。 • 依存が整理される、各層の責務も明確になる ◦ どんなユースケースがあるか知りたければアプリ ケーション層を、どんなドメインモデルが存在し てどういうルールや振る舞いがあるのか知りたけ

    ればドメイン層を⾒れば良い ◦ 実装の際にも、どこに実装すれば良いかを迷わず に済むようになる • ドメイン層が⼀番下でどこからも依存しない ◦ インフラ層への依存も取り除かれるため、純粋な ドメインモデルの実装に集中できる ◦ ドメインモデルのテストも容易になる
  55. 98 ©MIXI ドメインモデルで逆に困る場⾯ Userデータの取得に関するユースケースを考える。 ここで、参加アルバムのIDだけ取得しても表⽰に困るので、”JoinedAlbumIds”ごとに Albumデータも取得する。 => N+1問題 • DBに保存されているデータを取り出して返すだけなので、本来ドメインモデルの操作

    も、バリデーションも必要ない • ドメインモデルを経由していたら⾮効率 • => ドメイン層をスキップすれば良い(CQRS) (何度も話しているが)DDDを採⽤したからといって、全てDDDの原則に従わなければい けないわけではない。必要に応じてドメイン層はスキップしても良い。
  56. 99 ©MIXI CQRS Command Query Responsibility Segregation(CQRS)とは • Command(更新系の処理)とQuery(参照系の処理)で責務を分離するパターン ◦

    Command:複雑なビジネスロジックが絡み、整合性などの要件がある ◦ Query:パフォーマンス含め、更新系と異なる要件がある ▪ パフォーマンス、ページング、並べ替えなど ▪ 参照のみなのでドメインモデルの操作やバリデーションは本来不要 ◦ => Queryはドメインモデル介さずに実装する 補⾜:CQRSパターン採⽤する⽅はHasuraおすすめしときます。 • Query系APIは⾃動⽣成(ただしGraphQLに限る) • ⼈間はCommand系の実装に集中できる • 興味あれば調べてみてください
  57. 100 ©MIXI DDDも銀の弾丸ではない • DDDに限らず、設計の理論やパターンを学ぶと⼤きな期待感を抱いてもらえるかも。 • ⼀⽅で、実際のプロジェクトでやろうとするとひどい現実が降りかかってくることも ◦ 組織上の問題もあれば、技術的な問題も ▪

    技術への適合、時間の制約、ドメインに対する理解不⾜などで諦めが必要な場⾯も ◦ 指針が⽰されているとはいえ、どう実装するか悩む場⾯もまだ出てくるはず ▪ どこの層、どのオブジェクトが適切か?など ◦ => 経験も必要になってくる部分 • 結局リファクタリングは必要 ◦ 最初にしっかりドメインモデリングしてから実装するとはいえ、最初から完璧なドメ インモデルを得られることはほぼない。ドメインに対しては継続的な学習が必要。 ◦ ドメインモデルは開発のサイクルを通じて洗練させていくもの 銀の弾丸ではないが、設計やリファクタにおける⼤きな指針として活⽤してください。
  58. 102 ©MIXI (再掲)⽬次 • ソフトウェアアーキテクチャとは • アーキテクチャを学ぶ必要性 • モノリシックアーキテクチャ •

    マイクロサービスアーキテクチャ • モノリス vs マイクロサービス?? • 疎結合を実現するための⽅法論の紹介 • ドメイン駆動設計(DDD)の解説 <= ここまで終了 • DDD実践演習 質問あれば受け付けます。その後休憩に⼊ります。
  59. 111 ©MIXI まとめ ⾊々と幅広く解説しましたが、本研修では以下を持ち帰ってもらえると幸いです。 • スケールするプロダクト開発におけるアーキテクチャや設計の重要性 • 設計の⽅法論に対する向き合い⽅(何のためにやるかの⽬的が⼤事) ※特に今回の講義では⽣産性の観点からこれらを述べました また、今回話した各テーマについては、本研修ではあくまで概要を触れただけなの

    で、より深く知りたいと思った⽅は書籍などで体系的に学んでみてください。とにか く議論したり実践することで学べることも多いと思います。 各部署に配属後、既存機能のリファクタや、新機能開発の設計の際の指針として役⽴ ててもらえると幸いです。