Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
はてなリモートインターンシップ2023 ソフトウェアアーキテクチャ講義資料
Search
Hatena
October 18, 2023
Programming
0
370
はてなリモートインターンシップ2023 ソフトウェアアーキテクチャ講義資料
https://hatena.co.jp/recruit/intern/2023
Hatena
October 18, 2023
Tweet
Share
More Decks by Hatena
See All by Hatena
【詳説】コンテンツ配信 システムの複数機能 基盤への拡張
hatena
0
260
はてなインターンシップ2024 HTTP, Web, API 講義資料
hatena
0
1.2k
はてなインターンシップ2024 RDBMS ブートキャンプ講義資料
hatena
0
960
はてなインターンシップ2024 フロントエンドブートキャンプ講義資料
hatena
0
890
はてなインターンシップ2024 コンテナ講義資料
hatena
0
1k
はてなインターンシップ2024 コンテナオーケストレーション講義資料
hatena
0
880
はてなインターンシップ2024 インフラ講義資料
hatena
0
900
はてなインターンシップ2024 AI 講義資料
hatena
0
890
はてなインターンシップ2024 ブログライティング講義資料
hatena
4
3.2k
Other Decks in Programming
See All in Programming
技術を改善し続ける
gumioji
0
120
データの整合性を保つ非同期処理アーキテクチャパターン / Async Architecture Patterns
mokuo
54
19k
Honoをフロントエンドで使う 3つのやり方
yusukebe
7
3.5k
仕様変更に耐えるための"今の"DRY原則を考える
mkmk884
9
3.2k
Ruby on cygwin 2025-02
fd0
0
180
PHPカンファレンス名古屋2025 タスク分解の試行錯誤〜レビュー負荷を下げるために〜
soichi
1
680
Datadog Workflow Automation で圧倒的価値提供
showwin
1
160
Jasprが凄い話
hyshu
0
160
第3回関東Kaggler会_AtCoderはKaggleの役に立つ
chettub
3
1.2k
Ça bouge du côté des animations CSS !
goetter
2
150
Rubyで始める関数型ドメインモデリング
shogo_tksk
0
140
『テスト書いた方が開発が早いじゃん』を解き明かす #phpcon_nagoya
o0h
PRO
8
2.4k
Featured
See All Featured
Code Reviewing Like a Champion
maltzj
521
39k
Fight the Zombie Pattern Library - RWD Summit 2016
marcelosomers
233
17k
Scaling GitHub
holman
459
140k
Improving Core Web Vitals using Speculation Rules API
sergeychernyshev
10
510
Testing 201, or: Great Expectations
jmmastey
42
7.2k
How To Stay Up To Date on Web Technology
chriscoyier
790
250k
Save Time (by Creating Custom Rails Generators)
garrettdimon
PRO
29
1k
"I'm Feeling Lucky" - Building Great Search Experiences for Today's Users (#IAC19)
danielanewman
226
22k
Raft: Consensus for Rubyists
vanstee
137
6.8k
4 Signs Your Business is Dying
shpigford
182
22k
Why Our Code Smells
bkeepers
PRO
336
57k
GitHub's CSS Performance
jonrohan
1030
460k
Transcript
ιϑτΣΞΞʔΩςΫνϟ #hatenaintern)*)+ !
アーキテクチャとは • 構造? • ソフトウェアに物質的な構造はそもそもなくない? !
建築の場合: 構造設計 • そもそも建つために必要 • 物理的に⽴たないものは建たない • 施⼯性の確保 • 安全のため
• 建てたあと倒壊したら困る • 法令等で基準が定められている • コストのため • やり直しは⼤変 !
なぜ構造設計が必要か ミスったときのリスクが⼤きいから !
構造設計はいつ必要か 不要 個⼈で⽝⼩屋を建てる - そもそも作りが簡素で考えることが少ない - 壊れたらまた建てたらよい - ミスったら作り直せばよい 必要
⼤規模⼯事で⾼層ビルを建てる - 複雑だから闇雲には建たない - 壊れたら⼈命に関わる - 作り直すには莫⼤なコストがかかる - e.g. 耐震補強⼯事 - ⻑年耐えてほしい !
ソフトウェアでも同じ! !
ソフトウェアのアーキテクチャとは • 簡単には変更できない決定事項 • ⼈間が⾒出す抽象的なもの • フラクタルにどこまでもブレークダウン可能 • 開発者の共通理解として主観的に存在 !
ソフトウェアに求めること • 価値提供し続けるために開発‧運⽤コストを低くしたい • 機能追加に耐える • ハードウェアリソースの効率がよく可⽤性が⾼い • 環境変化に迅速に対応したい •
作って終わりではない !
優れたアーキテクチャのための指針 開発しやすい • 疎結合で凝集性が⾼い • 認知負荷が低い • 変更箇所が局所的 • ⼀度に関わる⼈数が少ない
• 開発からリリースまでが短い 運⽤しやすい • パフォーマンス‧スケーラビ リティ • 耐障害性 • 可観測性 !
Webサービスのアーキテクチャ !"
システムの外形的アーキテクチャ • モノリス • モジュラーモノリス • マイクロサービス !!
モノリス !"
モノリスの特徴 • プロダクト全体が1つのコードベース • 単⼀のWebアプリケーション‧単⼀のDB • シンプル • 開発時に触るリポジトリは1つだけ •
デプロイが必要なのは1つのアプリケーション !"
モノリスが複雑化すると - 技術⾯ 実はいろいろなコンポーネントがある !"
モノリスが複雑化すると - 機能⾯ いろいろな機能 !"
モノリスが複雑化 すると - 組織⾯ 1つのコードベースに複 数チームが関わる !"
複雑化したモノリスの課題 • 雰囲気の違ういろんなコードが混ざり合ってしまいがち • 「⼤きな泥だんご (big ball of mud)」 ['OP
Foote & Yoder] • チーム間のコンフリクト • 変更箇所のコンフリクト • リリースタイミングのコンフリクト • 技術スタックが1つに縛られる • e.g. 機械学習は適した⾔語でやりたい • デプロイパイプラインに無駄が多い • e.g. Webサーバとバッチは別でデプロイ • 不要なコンポーネントのテストも毎回必要になる !"
モジュラモノリス • 性質の異なる単位ごとにコンポーネントを分ける • コード上は最上位のディレクトリを分けるなどする • コンポーネント間は限られたインタフェースでのみやりとり !"
モジュラモノリスで課題は解決するか? • 雰囲気の違ういろんなコードが混ざり合ってしまいがち • コンポーネントごとに切り分ける • チーム間のコンフリクト • チームごとに担当コンポーネントを分ける •
技術スタックが1つに縛られる • コンポーネントごとに技術スタックも分けてしまう? • → もはやリポジトリが同じだけで単⼀のコードベースとは呼べなくなる • デプロイパイプラインに無駄が多い • コンポーネントごとにパイプラインを分ければ解決? • → もはやリポジトリが同じだけで(ry !"
マイクロサービス !"
マイクロサービスの特徴 • 1つのプロダクトを複数サービスの連携により実現 • 性質の異なるコンポーネントごとにサービスを分ける • 各サービスは独⽴して開発‧リリースできる !"
サービスの分け⽅の基準 • ドメインの境界で分ける • e.g. 課⾦機能と投稿画⾯と閲覧 機能 • 再利⽤性の⾼いものを分ける •
e.g. アカウント基盤 • 技術スタックで分ける • e.g. 機械学習 • 開発のライフサイクルの違いで分 ける • e.g. ネイティブアプリ向けAPI 層 • BFF (Backend For Frontend) • 組織構造に合わせて分ける • e.g. ユーザグロースチームと CMS基盤チーム !!
サービス間通信のパターン 同期的 • サブルーチン呼出しが別サービスへのリクエストになるだけ • リクエスト先のサービスが⽌まるとリクエスト元もエラーを返すしかなくなる !"
サービス間通信のパターン ⾮同期的 • 呼出し元はメッセージを送信 • レスポンスを待たない • 呼出し先はメッセージを受信したら処理する • サービス同⼠の独⽴性が⾼く⼀部の障害が全体に波及しにくい
!"
サービス間通信のパターン ⾮同期的: Pub/Subモデル • 送信元は誰が受信するか知らない !"
サービス間通信のプロトコル 同期的 • RPC • gRPCなど • サブルーチン呼出しに近い • REST
• GraphQL • etc. ⾮同期的 • AMQP • RabbitMQなど • 独⾃ • Apache Kafka • Amazon SQS • Google Cloud Pub/Sub • etc. !"
サービス間の整合性の取り⽅ CAP定理 分散システムにおいて以下の3つをすべて保証することはできない • Consistency (⼀貫性) • Availability (可⽤性) •
Partition-tolerance (分断耐性) !"
サービス間の整合性の取り⽅ 結果整合性 (eventual consistency) • ⼀時的に古いデータが参照されることを許容する • 最終的には不整合のない更新内容が反映される !"
サービス間の整合性の取 り⽅ Sagaパターン • ⻑⼤なトランザクションを分割するパターン • マイクロサービスではサービスごとのトランザクシ ョンに分解 • サービスA,
B, CのトランザクションTG, TH, TI • トランザクションには失敗時に元の状態に戻す補償 トランザクションを⽤意 • TG, TH, TIに対してCG, CH, CI • TIが失敗したらCHとCGを実⾏ !"
サービス間の整合性の取り⽅ TCCパターン (Try-Confirm-Cancel) • Tryフェーズ • 各サービスで仮登録状態にする • Confirm/Cancelフェーズ •
すべてのサービスでTryが成功したらConfirmリクエスト • いずれかのサービスでTryかConfirmが失敗したらCancelリクエスト !"
サービス間の整合性の取り⽅ 羃等性 (idempotency) • 同じ操作を何度やっても同じ結果になる性質 • サービス間のリクエストは羃等が望ましい • 失敗したらリトライしたい •
失敗と成功レスポンスの受け取り失敗は厳 密には区別できない • e.g. リクエストの処理中にネットワーク が切断した場合 ⽅法 • (a) リクエストする側が操作にIDを振っておく • 処理する側は処理済みのIDは覚えておく • 過去に処理済みのリクエストは無視する • (b) 差分ではなく最終状態にバージョンをつ けてリクエスト • 古いバージョンによる上書きは無視する !"
ここまでのまとめ • アーキテクチャとは • 後戻りできない決定事項 • 外形的に優れたアーキテクチャ • うまい分割 •
ドメインや技術スタックなど • リードタイム短縮 • ⼈と組織が重要 • 分散システムにすると考えることは増える • どこまで頑張るかは規模や想定する運⽤年数による !"
システムの内側のアーキテクチャ !!
よりミクロな視点 • うまい分割 • 認知負荷を下げる • 重要な箇所が些細な変更に影響されない • スピード •
テストしやすい → 変更しやすい !"
ビジネスロジックとビュ ーの分離 MVC • もともとはデスクトップGUIアプリのアーキテクチャ • M : モデル •
ビジネスロジックを表現する • データとその操作や永続化⽅法 • V : ビュー • モデルのデータをUIとして表⽰する • C : コントローラ • ⼊⼒イベントをモデルに渡す • モデルの変更がビューに反映されるように繋ぐ !"
ビジネスロジックとビューの分離 MとVが分離されていないと何が困るか • ビューの各所にロジックが偏在 • ロジック(仕様)を変えるにはビューのいろんな箇所の変更が必要 • ロジック(仕様)が正しいかテストするのにビューのテストが必 要 •
⾒せ⽅を変えただけでロジックが壊れる !"
ビジネスロジックのさら なる分解 レイヤー化アーキテクチャ • ビジネスロジック = ドメインモデル + ユースケース •
ドメインモデル • 登場⼈物とその関係 • e.g. 「著者」は「記事」を投稿できる • e.g. 「記事」には「カテゴリ」を設定できる • ユースケース • ユーザの体験としてどのようなドメインモデルの操作が可能か • e.g. ユーザは「著者」として「カテゴリ」設定した「記事」を投稿できる • 「カテゴリ」がまだ存在しなければ作成される • 永続化⽅法などは実装上の都合 (インフラ層) !"
依存関係逆転の原則 MVCの場合 • ビュー ← モデル ではない • モデルが⾃⾝の変更を能動的にビューに伝える =
モデ ルがビューに依存 • モデルのテストにビューが必要になってしまう • 依存を逆転する⽅法 • (a) モデルに変更があったらイベントを発⽕するだけ • フロントエンドで典型的なアプローチ • (b) 変更後のモデル状態をコントローラがビューに渡 す • バックエンドで典型的なアプローチ !"
依存関係逆転の原則 レイヤー化アーキテクチャの 場合 • ドメイン層 → インフラ層 ではない • ドメインロジックは永続化⽅法によらない
• e.g. データベースをMongoDBからMySQLに変えて もドメインロジックは不変 • 依存を逆転する⽅法: リポジトリインタフェース • モデルの変更の反映はリポジトリを介する • リポジトリのインタフェースはドメイン層に置く • リポジトリの実装はインフラ層に置く !"
もっと細かいアーキテクチャ • MVCのビューまわりの解像度を上げる • MVVMやMVPなど • ビューまで考慮したレイヤー化アーキテクチャ • クリーンアーキテクチャなど !"
まとめ • アーキテクチャとは • 後戻りできない決定事項 • 優れたアーキテクチャ • 開発しやすい •
運⽤しやすい • アーキテクチャの選択 • マクロな視点とミクロな視点 • 規模や想定する運⽤年数に応じて決める !"