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

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

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

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

Avatar for MIXI ENGINEERS

MIXI ENGINEERS PRO

July 23, 2026

More Decks by MIXI ENGINEERS

Other Decks in Technology

Transcript

  1. 講師紹介 登内 雅人 とのうち まさと 2020 年度新卒入社 Docbaseマイページ github pages:

    https://github.com/tonouchi510 ©MIXI • 業務は、今は主にサッカー周りの技術支援をしてます • 静岡県浜松市からリモートワーク • 趣味はサッカー観戦、 格闘技、将棋、個人開発 22
  2. 講師紹介 加藤 大和(かとう やまと) 25新卒 TIPSTAR事業部 サーバーサイドエンジニア 【学生時代】 情報通信技術, Blockchain,

    分散型デジタルアイデンティティの仕組み を研究 toC向け金融スタートアップでシステム開発 【経歴】 2021年: 大学入学 2024年: スタートアップにて開発業務 2025年3月: 大学卒業 2025年4月: MIXI新卒入社 【現在】 ⚽ 🐕 🏎 🎰 公営競技×ソーシャルのサーバーサイド, インフラを少し 最近は外部SaaSの導入設計〜実装・運用まで担当 ©MIXI 3
  3. ⽬次 • • • • • • • • ©MIXI

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

    Webサーバー APIサーバー 認証基盤 データベース APIゲートウェイ クラウドサービス etc ソフトウェアアーキテクチャではこの部分の構造の設計⽅針を定義する ©MIXI 7
  5. ソフトウェアアーキテクチャとは ソフトウェアの構成要素とそれらの関係を定義したもの。 ソフトウェアの構成要素 • 各機能を実現するためのサービス‧モジュール‧クラス ◦ • • • •

    例:ユーザ管理、在庫管理、商品検索、決済 認証‧認可 DB操作 外部サービス連携 etc ソフトウェアを組み⽴てるときには様々な要素が必要となる ©MIXI 8
  6. アーキテクチャを学ぶ必要性 なぜソフトウェア開発において、アーキテクチャ‧設計が重要か? ⾮機能要件を実現するため • 機能要件 ◦ • 「ユーザアカウントを作成でき る」、「注文できる」など。 ユーザやシステムが「何をできるか」に関する要件。機能そのもの。

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

    High Performance組織としての⼟台が必要。 Nicole Forsgren, Jez Humble, & Gene Kim. (2018). Accelerate: The Science of Lean Software and DevOps: Building and Scaling High Performing Technology Organizations. IT Revolution Press. p.92. パフォーマンス向上には、「プロセスの改善(DevOps的な話)」や「組織作り(心理的安全性)」なども重要。 ただし、それだけではどうにもならない問題もある=> 技術での解決が必要 ©MIXI 12
  8. 密結合と疎結合 ソフトウェアアーキテクチャや設計の⽂脈においては、”ソフトウェアの構成要素同⼠ の結合度合い”が重要な設計の観点となる。 • 密結合(⼀般的に良くない状態) ◦ • 疎結合(⼀般的に良い状態) ◦ ©MIXI

    クラスやモジュールが互いの内部構造や具体的な実装に依存している状態 ▪ 例:他のクラスの変数を直接参照したり、インスタンス⾃体を変数に持つなど クラスやモジュールが互いの内部構造や具体的な実装に依存していない状態 ▪ 「インターフェースや抽象のみへの依存」、「集約」など 15
  9. 密結合した実装の例 Albumの仕様変更:`follower_scope`を追加(参加者のアクセス権制御) • 定数定義が変わったら依存先が壊れる ◦ • オブジェクトがどこでどう変更されるかが分からない ◦ ◦ ©MIXI

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

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

    本質的な業務に取り組めない 新規参⼊エンジニア ◦ 読まなければいけないコードが多すぎ て把握しきれない ◦ ⼀⼈⽴ちできるまで時間を要する Nicole Forsgren, Jez Humble, & Gene Kim. (2018). Accelerate: The Science of Lean Software and DevOps: Building and Scaling High Performing Technology Organizations. IT Revolution Press. p.92. アーキテクチャを学ぶ必要性: 要点 ©MIXI • • エンジニアの増加に対するパフォーマンスの最⼤化を⽬指す 機能改修の速さはビジネス観点では ”競合優位性(参⼊障壁)” となる 21
  12. (再掲)⽬次 • • • • • • • • ソフトウェアアーキテクチャとは

    アーキテクチャを学ぶ必要性 <= ここまで終了 モノリシックアーキテクチャ マイクロサービスアーキテクチャ モノリス vs マイクロサービス?? 疎結合を実現するための⽅法論の紹介 ドメイン駆動設計(DDD)の解説 DDD実践演習 質問あれば受け付けます。 ©MIXI 22
  13. 補⾜:エンジニア組織のパフォーマンス計測 組織の開発のパフォーマンスを測るのは実際にはかなり難しい。 デプロイ数で計測するというのは⽅法の⼀つ。 有名なものとしては、Four Keysがある。 リードタイム デプロイ頻度 変更失敗率 平均修復時間(MTTR) コードがコミットされてか

    ら本番環境で正常に機能す るまでの時間 コードを本番環境にデプロ イまたはリリースした頻度 リリース後に障害や不具合 等により修正を⾏う必要が ⽣じた割合 変更失敗時にサービス復元 までにかかる時間 リファクタリング‧リアーキテクチャのKPIに設定し、そこの改善を⾒ると⾯⽩そう。 ©MIXI 23
  14. ソフトウェアアーキテクチャとは(再掲) ソフトウェアアーキテクチャと聞いてよく出てくる⽤語 • • • • クリーンアーキテクチャ レイヤードアーキテクチャ オニオンアーキテクチャ ヘキサゴナルアーキテクチャ

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

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

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

    ⾃分の担当するサービスに関する知識だけあれば良いので、認知負荷が低い 依存範囲が狭いため、技術スタック‧ライブラリの更新がしやすい(サービスごとに可能) 信頼性向上 ◦ ©MIXI 他のサービスの開発者の作業に影響されない 開発‧メンテナンスがしやすい(保守性) ◦ ◦ • あらゆる事柄を個別の サービス単位で考えられ るようになる恩恵 スケーリングが効率的 ◦ • 変更したサービスだけテストすれば良い コードベース、DB、インスタンス等が分かれているため、障害発⽣時の 影響を限定できる、原因の特定がしやすい 31
  18. 結果整合性の⾟み マイクロサービスではサービス間のデータ整合性は結果整合性を前提としているのでそれに伴う 問題の考慮は当然必要になってくる。 ⾮同期更新なので、DB研修で習ったような「ダーティリード」、「ノンリピータブルリー ド」、「ファントムリード」に類似するような問題が発⽣し放題。その他の問題も多い。 • • • 注⽂処理は成功しているのに在庫情報が変わっていない(更新遅延) 在庫確認してから注⽂処理を確定し、その後在庫を引き落とそうとしたらなかった

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

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

    YYY サービス API ZZZ サービス API ABC サービス API ABC サービス それぞれで非同期にローカルトランザクションが実行される(結果整合)。 補償トランザクション 打ち消すための トランザクション実行 API XXX サービス 打ち消すための トランザクション実行 API YYY サービス ここで処理が失敗 API ZZZ サービス 補償トランザクションのパブリッシュ ©MIXI 44
  21. モノリス vs マイクロサービス?? そもそもどちらか⼀⽅ではなく、基本的には共存することが多い。どちらも活かす。 スケールするプロダクト開発では、以下のような流れになるのが⼀般的。 • • 初期フェーズ: ◦ まずは、⼩規模少⼈数で利点が多い”モノリス”で開発を始める

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

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

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

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

    => モノリスでも可(モジュラーモノリス) エンジニアの増加に対する⽣産性向上の観点でいえば、サービスまで分けずとも、モ ジュール分割によって分担したり認知負荷の軽減ができれば⽣産性向上は⾒込める。 そこを優先して他の要件‧サービス切り出しのメリットは妥協するとか。 どこを達成したいか、どこを優先するかという考え⽅が⼤事。 ©MIXI 52
  26. モノリス vs マイクロサービス?? ここまでまとめ: • ここまで話したように、モノリス/マイクロと⾔ってもやり⽅は⾊々あり、どっちが良 い悪いではなく、トレードオフであり、適宜使い分けるものです。 • 特定のアーキテクチャスタイルやデザインパターンを採⽤するからといって、定義通 りに作る必要はなく、全ての箇所で従わなければいけないわけでもありません。

    ◦ • アーキテクチャはあくまで⼿段であり、⾃分たちのチームの課題がどこにあって、何 を解決したいかが重要です。 ◦ ©MIXI => そこを⽬指すと⼿段が⽬的化してしまう 解決するための⼿段をみて、それを実⾏する利点が⽋点を上回れば実⾏すれば良い 53
  27. (再掲)⽬次 • • • • • • • • ソフトウェアアーキテクチャとは

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

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

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

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

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

    機能的強度を⽬指して、機能を細分化しすぎてしまい逆にコードを把握しづらい ◦ SNSの例:「フォローリクエストできる」「フォローリクエストを承認できる」を別 機能として別クラスで実装する? ◦ やりすぎると、ファイルやクラスが別れすぎて逆にコード追いづらいことも ◦ ⼈間が把握しやすいことが⼤事なので、その意図であえて下げる判断も⼤事 何らかのアーキテクチャスタイル採⽤しているのにドメイン層に知識が全くない ◦ データを持つクラスが定義されているだけ => ドメインモデル貧⾎症 ◦ ドメインルール、ビジネスロジックがドメイン層に集約させるべき => しっかりとした⽬的と設計概念への理解が重要 ©MIXI 64
  33. (再掲)⽬次 • • • • • • • • ソフトウェアアーキテクチャとは

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

    ◦ 切り出しやすい。ただし、更新頻度が少ないためそもそも開発効率を上げる意味がない ◦ 第⼀歩としての成功事例を作るためならあり あらゆる機能改修に関わってくる巨⼤クラス(ゴッドクラス) ◦ 今後の開発の効率化に繋がり、切り出す効果は⾼い ◦ ただし、依存先が多いため、疎結合化するにも全体の把握と多くの調整が必要 70
  35. (再掲)⽬次 • • • • • • • • ソフトウェアアーキテクチャとは

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

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

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

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

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

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

    ©MIXI ファクトリ 利用して 組み立てる ドメイン サービス 仕様 値オブジェクト モデリングした知識を⼀箇所に集中させる それを活⽤してアプリケーションを組み⽴てる 86
  42. 値オブジェクト(Value Object) ライフサイクルのないオブジェクト。値に関する知識を表現する。 • • ©MIXI 値オブジェクトの例 ルール 住所 都道府県・市区町村・番地など

    名前 姓と名から成る メールアドレス 特定のフォーマットがある 座標 (x, y)の数値の組み合わせで表現される こういった何らかのルールがあるものは、プログラミング⾔語のプリミティブ型(Int, Float, Stringなど)ではなく、独⾃の型として定義して知識を組み込むのが良い 必要に応じて、振る舞い(メソッド)を定義することもある 87
  43. 値オブジェクト(Value Object) 修正コード例(擬似コード): ※便宜上Go⾔語に変わってます。 • • ©MIXI FollowerScope型を定義し、コンストラクタにルール(バリデーション)を記述 ◦ FollowerScopeのインスタンスが存在している時点でバリデーション通っていることが保証される

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

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

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

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

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

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

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

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

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

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

    アーキテクチャを学ぶ必要性 モノリシックアーキテクチャ マイクロサービスアーキテクチャ モノリス vs マイクロサービス?? 疎結合を実現するための⽅法論の紹介 ドメイン駆動設計(DDD)の解説 <= ここまで終了 DDD実践演習 質問あれば受け付けます。その後休憩に⼊ります。 ©MIXI 103