アプリケーション実装と品質保証「アーキテクトの教科書 価値を生むソフトウェアのアーキテクト構築」書評 第3回
こんにちは!前回までの2回にわたり、「アーキテクトの教科書 価値を生むソフトウェアのアーキテクト構築」の内容を基に、アーキテクチャの基本と進め方、そしてアーキテクチャの比較と実装準備について解説してきました。
第一回はこちら👇
第二回はこちら👇
シリーズ最終回となる今回は、いよいよ「アプリケーション実装と品質保証」に焦点を当てていきます。
私は昨年あるAI開発プロジェクトに携わり開発を行ってました。本番リリース後にシステムエラーが発生。原因を調査すると、共通機能の実装不足とテスト戦略の甘さでした。今回は、本書の知見とそんな失敗経験を踏まえ、実践的なノウハウを共有します。
「完璧なシステムなど存在しない」とはよく言われますが、適切な実装方法と品質保証プロセスを踏むことで、ユーザーに価値を届けるシステムを作ることは可能です。では、早速見ていきましょう!
1. アプリケーション共通機能の実装
アプリケーションには、業務固有の機能だけでなく、多くの共通機能が必要です。これらの共通機能は、アプリケーション全体の品質や使い勝手に大きく影響します。
1.1 認証・認可・セッション管理
認証(Authentication)
認証は「あなたは誰ですか?」を確認する機能です。
認証がなぜ必要なのか?
システムにアクセスしたユーザーが正当な利用者であることを確認するためです。例えば、SNSで他人のアカウントから投稿できてしまっては大問題ですよね。
代表的な認証機能:
- ログイン画面:ユーザーが認証情報を入力
- 認証処理:データベースやIdP連携による認証
- 認証状態チェック:保護されたリソースへのアクセス時に確認
- ログアウト:認証状態をクリア
認可(Authorization)
認可は「あなたは何ができますか?」を制御する機能です。
認可がなぜ必要なのか?
ユーザーに適切な権限を与え、不適切なアクセスを防ぐためです。例えば、一般社員が役員用の機密情報を見られるようでは困りますよね。
リソースの保護レベル:
- 機能・画面:アクセスできる機能や画面を制御
- 機能の実行レベル:同じ機能でも権限によって実行できる操作を制限
- 画面項目:画面の一部項目のみを特定ロールに表示
- データ:ロールに応じてデータの閲覧範囲を制限
よくある失敗は、画面レベルでの認可は実装したのに、API直接呼び出しの認可チェックを忘れるケースです。必ずすべてのアクセス経路で認可を確認しましょう。
セッション管理
セッション管理は、ユーザーの状態を一時的に保持する機能です。
セッション管理がなぜ必要なのか?
- HTTP通信はステートレス(無状態)なため、ユーザーの状態を維持するための仕組みが必要
- 認証状態の維持やショッピングカートの内容など、一時的な情報を保持
セッション管理の課題と対策:
- 複数タブでの衝突:階層構造でタブごとにセッション情報を分離
- メモリ圧迫:必要最小限の情報のみをセッションに保存
- セキュリティリスク:機密情報はセッションに保存しない
ある機能を実装した際に別アプリに飛ぶと、それまでのメモが全て消える、みたいな事象が発生しました。
1.2 エラーハンドリング・ロギング
エラーハンドリング
エラーハンドリングは、システムで発生したエラーを適切に処理し、ユーザーに通知する機能です。
エラーハンドリングがなぜ必要なのか?
- ユーザー体験の向上:エラー発生時でも適切なガイダンスを提供
- システム安定性の確保:予期せぬエラーでもシステム全体が停止しないように
エラーレベルと対応:
レベル | 説明 | 具体例 | 対応 |
---|---|---|---|
通常 | ユーザー自身でリカバリー可能 | 在庫不足、入力ミス | 画面上にメッセージ表示 |
重大 | 担当者によるリカバリーが必要 | マスタデータの不備 | 画面メッセージ+担当者通知 |
深刻 | 運用担当者による対応が必要 | システムバグ、リソース不足 | エラー画面+運用担当者通知 |
致命的 | システム全体の障害 | サーバダウン、DB障害 | 運用監視システムで検知 |
私が携わったプロジェクトではエラーの際に「エラーID」を付与し、ログと紐づけられるようにしています。これにより、ユーザーからの問い合わせ時に迅速に原因特定できるようになりました。
ロギング
ロギングは、システムの動作状況や利用状況を記録する機能です。
ロギングがなぜ必要なのか?
- 問題診断とデバッグ:エラー発生時の状況把握
- システム監視:パフォーマンスや利用状況の分析
- セキュリティ監査:不正アクセスの検出
- ビジネス分析:ユーザー行動のパターン把握
- 法令遵守:監査対応や証跡保存
主要なログの種類:
ログ | 目的・用途 | 概要 |
---|---|---|
アクセスログ | 監査、障害調査 | ユーザーのシステムへのアクセス履歴 |
認証ログ | 監査 | ユーザー認証の成功や失敗 |
操作ログ | 監査、障害調査 | ユーザーが行った操作 |
エラーログ | 監視、障害調査 | エラーの詳細情報 |
パフォーマンスログ | 性能分析 | 処理時間や応答時間 |
ロギングで気をつけるべきは「情報過多」です。あるプロジェクトでは、デバッグレベルのログを本番環境でも出力し続け、ディスクがあっという間に一杯になるという事態が発生しました。環境ごとに適切なログレベルを設定することが重要です。
1.3 セキュリティとトランザクション制御
セキュリティ
アプリケーションセキュリティは、システムを悪意ある攻撃から守るための機能です。
セキュリティ対策が必要な主な脅威:
脅威(攻撃手法) | 概要 | 主な対策 |
---|---|---|
クロスサイトスクリプティング(XSS) | 攻撃者が埋め込んだ不正なスクリプトがユーザー環境で実行される | 入力値チェック、表示時のエスケープ処理 |
クロスサイト・リクエスト・フォージェリ(CSRF) | 攻撃者が被害者のアカウントで悪意のあるリクエストを送信 | CSRFトークンの利用 |
SQLインジェクション | 不正なSQLコマンドを挿入して実行させる | プリペアードステートメントの利用 |
セキュリティは「あったら良い」ではなく「なければ致命的」な機能です。初期段階からセキュリティを考慮した設計(セキュリティ・バイ・デザイン)を心がけましょう。
トランザクション制御
トランザクション制御は、データベース操作の一貫性を確保するための機能です。
トランザクション制御がなぜ必要なのか?
- データの整合性確保:複数の更新が途中で失敗した場合にも不整合を防ぐ
- 同時実行制御:複数ユーザーが同時にデータを更新する場合の整合性確保
トランザクションの基本原則(ACID):
- 原子性(Atomicity):全ての処理が成功するか、全て失敗するか
- 一貫性(Consistency):データベースの整合性制約を維持
- 独立性(Isolation):並行実行されるトランザクション間の影響を制御
- 永続性(Durability):完了したトランザクションの結果は永続的
トランザクション制御で最も注意すべきは「スコープ」です。大きすぎるトランザクションはパフォーマンス低下やデッドロックのリスクを高めます。適切な粒度を見極めることが重要です。
1.4 データベースアクセスと国際化
データベースアクセス
データベースアクセスは、データの保存と取得を行う機能です。
データベースアクセス技術の選択肢:
- プログラミング言語の標準ライブラリ(例:Python の sqlite3)
- フレームワークの機能(例:Django ORM)
- 専用ライブラリ(例:SQLAlchemy)
ORM(オブジェクト・リレーショナル・マッピング)の利点:
- オブジェクト指向とデータベースの橋渡し
- SQLを直接書く必要がない
- データベース抽象化(DBMSの切り替えが容易)
データベース選定のポイント:
- 同時アクセス性能
- データ量
- セキュリティ要件
- 運用/保守の負担
- 機能の充実度
フロントエンドでもデータを保存する技術があります:
データ保存技術 | 概要 | 用途例 |
---|---|---|
localStorage | ブラウザに永続的に保存 | ユーザー設定、オフラインデータ |
sessionStorage | ブラウザセッション中のみ保存 | 一時データ、ウィザード状態 |
IndexedDB | ブラウザ内のNoSQLデータベース | 大量データ、構造化データ |
Cookies | サーバーとやり取りする小さなデータ | 認証トークン、設定 |
詳しいデータベースの取り扱いに関してはこちらの記事に詳細を記載しております。
国際化(i18n)と地域化(l10n)
国際化は、アプリケーションを様々な言語や地域で利用できるようにする機能です。
国際化がなぜ必要なのか?
- グローバル展開:より多くのユーザーにリーチ
- ユーザー体験の向上:母国語でのインターフェース提供
- 法的要件:一部地域では現地語対応が義務付け
国際化の主な要素:
- テキスト翻訳:UIのテキストを各言語に対応
- 日付・時刻形式:国ごとに異なる表記方法に対応
- 数値・通貨形式:桁区切りや小数点の違いに対応
- 文字エンコーディング:様々な文字セットに対応
最初から国際化を考慮しておくと、後々の対応が格段に楽になります。「後から対応すれば」という考えは、多くの場合大きな技術的負債を生み出します。
2. 開発準備と構成管理・CI/CD
2.1 アプリケーション開発の準備
アプリケーション開発を効率的に進めるためには、開発環境や規約を整備しておくことが重要です。
必要なドキュメント類:
ドキュメント種別 | 説明 | 具体例 |
---|---|---|
開発規約 | 開発者が遵守すべきルール | コーディング規約、命名規約、構成管理規約 |
手順書 | 環境構築やツールの利用方法 | 開発環境構築手順書、ツール利用手順書 |
実装参考資料 | 実装の参考となる資料 | 実装ガイドライン、チュートリアル |
これらのドキュメントは、単なるルール集ではなく、「なぜそのルールが必要か」の理由も含めることで、開発者の理解と納得を得られます。
2.2 構成管理とCI/CD
構成管理
構成管理は、成果物を識別し、変更を追跡するプロセスです。
構成管理対象資材:
- ソースコード
- テストコード
- テストデータ
- 設定ファイル
- ビルドスクリプト
- データベース資材
ブランチ管理方法:
-
git-flow:
- 大規模開発向き
- master, develop, feature, release, hotfix ブランチを使用
- リリースサイクルが長い場合に適している
-
GitHub Flow:
- シンプルで小規模開発向き
- master(メイン)とfeature(作業)の2種類のブランチ
- 頻繁なリリースに適している
私も初めはgit-flowを採用しようとしましたが、そこまで大規模なシステムではなかったため、GitHub Flowにしておりました。リリースサイクルが短い生成AIアプリ開発だと特にシンプルさが重要かなと思ったためです。
git-flowとGitHub Flowに関してはこちらの記事で詳細を解説してます👇
CI/CD
CI/CD(継続的インテグレーション/継続的デリバリー)は、コードの統合からデプロイまでを自動化するプラクティスです。
CIで行われるタスク:
- コンパイル
- 静的解析
- ユニットテスト
- 統合テスト
- E2Eテスト
- ビルド
- ドキュメント生成
CDで行われるタスク:
- 環境へのデプロイ
- 構成管理
- 品質ゲート確認
- 承認プロセス
CI/CDパイプラインは「早期発見、早期修正」の原則を体現するものです。問題を早く見つけるほど、修正コストは低くなります。
CI/CDに関連する話でGitHub actionに関して記載しております👇
3. 品質保証とテスト戦略
3.1 機能テストの自動化
機能テストは、システムが要件通りに動作することを確認するテストです。テストピラミッドの考え方に基づき、下位のテストほど多く実施します。
ユニットテスト
ユニットテストは、コードの最小単位(関数、メソッド、クラスなど)をテストします。
ユニットテストの特徴:
- 準備が容易:入力データや依存オブジェクトの用意が簡単
- バリエーション増加:様々なケースを容易に作成可能
- 実行時間が短い:フィードバックが速い
- 原因特定が容易:問題箇所の特定がしやすい
ユニットテストでは、AAA(Arrange-Act-Assert)パターンがよく使われます:
- Arrange:テストの準備
- Act:テスト対象の実行
- Assert:結果の検証
インテグレーションテスト
インテグレーションテスト(結合テスト)は、複数のユニットやコンポーネントが連携して動作することを確認します。
インテグレーションテストのポイント:
- コンポーネント間のインターフェースに焦点
- 実際の環境に近い条件でのテスト
- 外部依存(DB、外部API)との連携確認
E2Eテスト
E2E(End-to-End)テストは、ユーザーの視点でシステム全体をテストします。
E2Eテストの対象:
- 主成功シナリオ(ハッピーパス)
- 代表的な例外シナリオ
- 重要な業務フロー
E2Eテストツール:
- コードベース:Selenium, Cypress
- ノーコード:Autify, MagicPod
E2Eテストは重要ですが、実行が遅く、メンテナンスコストが高いため、数を絞って重要なシナリオに集中することがポイントです。
3.2 パフォーマンステスト
パフォーマンステストは、システムが期待通りの性能で動作することを確認するテストです。
単機能テスト
単機能テストでは、個々の機能を単独で実行した際のパフォーマンスを検証します。
テスト対象機能の選定基準:
- 業務における重要度
- 利用頻度
- 処理の複雑度
- 取り扱うデータ量
性能目標値設定例:
- 登録・更新処理:1秒以内
- 一覧・検索処理:3秒以内
性能問題の主な原因は、データベースアクセス周辺に集中しています。SQLクエリの実行速度や、発行SQLの数に注目してチューニングを行いましょう。
負荷テスト
負荷テストは、ピーク時の負荷がかかった状態でのシステム全体のパフォーマンスを検証します。
性能目標値の指標:
- レスポンスタイム:リクエストから応答までの時間
- スループット:単位時間あたりの処理量
目標値には平均値ではなく、パーセンタイル値(95パーセンタイルなど)を使用するのが一般的です。これにより、大多数のユーザーにとっての体験を保証できます。
ロングランテストとスケーラビリティテスト
ロングランテストは、長時間の連続稼働での安定性を検証します。メモリリークやリソース枯渇の検出に効果的です。
スケーラビリティテストは、負荷増加に対してシステムをスケールさせた際の挙動を検証します。クラウド環境でのオートスケーリング設定の検証などに活用します。
あるプロジェクトでは、開発環境での負荷テストは問題なかったのに、本番環境でパフォーマンス問題が発生しました。原因は、テストデータと本番データの分布の違いでした。可能な限り本番に近いデータでテストすることの重要性を学びました。
4. まとめ
3回にわたるこのシリーズでは、アーキテクチャの基本から、設計、実装、品質保証まで、ソフトウェア開発の全体像を解説してきました。
アーキテクチャは単なる設計図ではなく、プロジェクトの成功を左右する重要な要素です。適切なアーキテクチャの構築と実装によって、ユーザーに真の価値を提供するシステムを作り上げることができます。
私自身、様々なプロジェクトを経験する中で、アーキテクチャの重要性を痛感してきました。アーキテクチャに時間をかけることは「贅沢」ではなく「投資」なのです。
5. 「価値を生むソフトウェアのアーキテクト構築」書評
ここまで3回のシリーズでご紹介した内容は、実は素晴らしい一冊の書籍に大きく触発されたものです。今回ご紹介する「アーキテクトの教科書 価値を生むソフトウェアのアーキテクト構築」は、アーキテクチャを学ぶ上で間違いなく最良の入門書の一つと言えるでしょう。
5.1 本書の特徴
本書の最大の魅力は、「理論」と「実践」のバランスが絶妙なことです。アーキテクチャというと抽象的で理解しづらいテーマですが、本書は具体的な例や図解を多用し、初学者でも理解しやすく解説しています。
特に印象的だったのは、アーキテクチャドライバという概念の解説です。アーキテクチャを設計する際の「なぜその決定をしたのか」という理由付けが明確になり、チーム内での共通理解を促進する効果があります。
また、本書では「アーキテクチャデシジョンレコード」の具体的な記述方法まで詳しく解説されており、すぐに実務に応用できる点も高く評価できます。
5.2 内容の充実度
全8章からなる本書は、以下のような内容で構成されています:
- アーキテクチャの基本概念
- アーキテクチャドライバの特定
- アーキテクチャ設計と文書化
- アプリケーション基盤の構築
- 開発プロセスの標準化
- 共通機能の実装
- 構成管理とCI/CD
- 品質保証とテスト戦略
特に第4章「アプリケーション基盤の構築」と第6章「共通機能の実装」は、他の書籍ではあまり詳しく触れられていない内容が豊富で、実務に直結する知識が得られます。
5.3 実務での活用法
本書の真価は、実際のプロジェクトでの活用シーンにあります。私自身、本書を読んだ後、次のように活用しました:
- アーキテクチャ設計会議で、アーキテクチャドライバの概念を導入
- ADR(アーキテクチャデシジョンレコード)テンプレートを作成し、チーム内で共有
- 「4+1ビュー」モデルに基づくアーキテクチャ文書化の実践
- 共通機能のチェックリストとして第6章を活用
これらの取り組みにより、チーム内でのアーキテクチャに関する議論が活性化し、設計の質が向上しました。また、新メンバーの教育資料としても本書は大いに役立ちました。
5.4 こんな人におすすめ
本書は、以下のような方々に特におすすめです:
- アーキテクトを目指すエンジニア
- プロジェクトリーダーやテックリード
- 開発プロセスや品質向上に悩むマネージャー
- システム設計の基礎を固めたい若手エンジニア
- レガシーシステムのリファクタリングを検討している方
初学者にも理解しやすい丁寧な解説ながら、経験豊富なエンジニアにとっても新たな気づきがある内容となっています。
こちら本を購入したいという方はこちらに画像リンクを貼っています👇
5.5 総評
「アーキテクトの教科書 価値を生むソフトウェアのアーキテクト構築」は、アーキテクチャという抽象的な概念を具体的かつ実践的に解説した、まさに「教科書」と呼ぶにふさわしい一冊です。
私がこの本から学んだ最も重要な教訓は、「アーキテクチャは技術的な活動ではなく、ビジネス価値を実現するための活動である」ということです。この視点があれば、過剰な技術的こだわりや不必要な複雑さを避け、真に価値のあるシステムを設計することができるでしょう。
本書を読んで実践することで、あなたのプロジェクトが「動くだけ」のシステムではなく、「価値を生み出し続ける」システムへと進化することを願っています。
いかがでしたか?この3回シリーズが、皆さんのアーキテクチャ理解の一助となれば幸いです。実際に「アーキテクトの教科書」を手に取り、より深く学ぶことをおすすめします。アーキテクチャは一朝一夕に身につくものではありませんが、継続的な学びと実践を通じて必ず上達していきます。
またお会いしましょう!
最後に
私は2つのプラットフォームで生成AIに関する発信を行なっております。
生成AIサービスの考察を見たい方へ
生成AIサービスの動向やや具体的な内容は、noteで詳しく解説しています。
noteプロフィール: @mizupee
日々の生成AI分析を追いたい方へ
毎日1つの生成AIサービスを分析するTwitter投稿「#100DaysofAI」もぜひフォローください。簡潔なポイント分析とアイデア共有を継続中です。
Twitter: @mizupee
Discussion