アプリケーションアーキテクチャ

アプリケーションアーキテクチャ概要 ― 内側の約束事 ― 生成AI時代のアーキテクチャ超入門

アプリケーションアーキテクチャ概要 ― 内側の約束事 ― 生成AI時代のアーキテクチャ超入門

本記事について

当サイトを閲覧いただきありがとうございます。 本記事はシリーズ『生成AI時代のアーキテクチャ超入門』の「アプリケーションアーキテクチャ」カテゴリの入口として、この領域全体を俯瞰する記事です。

モノリスマイクロサービスかを論じる前に、アプリ内部のコードが統一された書き方になっていないと、どんな全体構造も絵に描いた餅になります。本記事ではソフトウェアアーキテクチャとの違い、クラス設計・命名・ドメインロジック・エラーハンドリングなど内部構造の決めごとの全体像と、「チーム全員が同じコードを書けるようにする」という目的を示します。

このカテゴリの他の記事

「コードをどう書くか」の約束事

ソフトウェアアーキテクチャの一部として語られることもありますが、そちらに含めてしまうと粒度のバランスが取れなくなるため、別のアーキテクチャとして分離しておく方が望ましいです。ソフトウェアアーキテクチャで決めた設計方針に大きく影響を受けるため、検討する際は必ず整合性を取ることが重要です。

アプリケーションアーキテクチャが手薄なプロジェクトは、コードの書き方がチーム内で散らかり、レビューのたびに「この書き方いいの?」の議論が再燃します。地味な規約の徹底が、日々の生産性と長期の保守性を静かに支えているのが実情です。

ソフトウェアとアプリケーションの違い

flowchart TB
    subgraph SW["ソフトウェアアーキテクチャ (外側の骨格)"]
        SW1[モノリス vs マイクロサービス]
        SW2[言語選定]
        SW3[API設計]
        SW4[DB選定]
    end
    subgraph APP["アプリケーションアーキテクチャ (内側の約束事)"]
        APP1[クラス設計 / SOLID]
        APP2[ドメインロジック]
        APP3[命名規則]
        APP4[エラーハンドリング]
    end
    SW -->|前提を提供| APP
    SW -.|One-way Door<br/>変更困難|.- L1[要件定義で決定]
    APP -.|Two-way Door<br/>変更しやすい|.- L2[実装フェーズで確定]
    classDef sw fill:#dbeafe,stroke:#2563eb;
    classDef app fill:#fef3c7,stroke:#d97706;
    class SW,SW1,SW2,SW3,SW4 sw;
    class APP,APP1,APP2,APP3,APP4 app;

言葉が似ているため混同されがちですが、ソフトウェアアーキテクチャとアプリケーションアーキテクチャは「対象の粒度が根本的に異なる」設計です。ソフトウェアアーキテクチャはアプリ全体の骨格、つまりモノリスマイクロサービスか、使用言語、API設計、データベースの選定といった外側の枠組みを決める領域。一方アプリケーションアーキテクチャは、その枠組みの中で実際にコードをどう書くか、つまりクラス分割、命名規則、ドメインロジックの表現方法といった内側の約束事を決めます。

両者を区別する理由は、意思決定の責任者と変更のコストが大きく違うからです。ソフトウェアアーキテクチャは一度決めると後戻りが難しいOne-way Doorの判断が多く、アーキテクトが要件定義フェーズでじっくり決めます。アプリケーションアーキテクチャは実装フェーズで確定し、テックリードやリードエンジニアが主導する、比較的やり直しの効くTwo-way Doorの判断です。

観点ソフトウェアアーキテクチャアプリケーションアーキテクチャ
粒度アプリの外部構造アプリの内部構造
モノリス / マイクロサービス / 言語 / API設計クラス設計 / 命名規則 / ドメインロジック
決定時期プロジェクト計画〜要件定義設計〜実装フェーズで確定
変更容易性変更が極めて困難(One-way Door)比較的変更しやすい(Two-way Door)

家で例えるなら、ソフトウェアアーキテクチャは間取り図(何LDKか、玄関はどこか、水回りは一箇所にまとめるか)、アプリケーションアーキテクチャは「各部屋の家具配置・コンセントの位置・壁紙の柄」にあたります。間取りを変えるには壁を壊す大工事が必要ですが、家具は比較的動かしやすい。そのぶん日々の暮らしやすさは家具配置で決まる、という関係です。

なぜ分けて考えるのか

両者を混ぜて考えると、議論の抽象度が常にバラつき、会議が噛み合わなくなります。マイクロサービスにすべきか」という大枠の話をしているのに「その中のクラスはどう分けるのか」が割り込んできたり、逆に命名規則を決める場で「そもそも言語の選定が……」と話が戻ったり。「決定の粒度を揃える」ことは、設計議論を前に進めるための前提条件です。

キャリア初期のエンジニアがつまずきやすいのもまさにこの部分で、「クラス設計を頑張ればアーキテクチャが良くなる」と思い込みがちです。ところが実際には、マイクロサービス化やデータベース分離といった外側の判断を間違えていると、どれだけクラスを綺麗に書いても挽回できません。逆にアーキテクトが外側だけ決めて内側を放置すると、チームごとに書き方がバラついて保守不能になります。両レイヤーを別物として並走させる発想が出発点です。

  • ソフトウェア側が細かい実装ルールに引っ張られて大枠設計がブレる
  • アプリケーション側が曖昧なまま開発が進み、チーム毎に実装がバラつく

「アーキテクト」「リードエンジニア / テックリード」で責任を分担し、それぞれが違うレイヤーの決定を担うのが健全です。

決めるべきこと — あなたのプロジェクトでの答えは?

以下の項目について、あなたのプロジェクトの答えを1〜2文で言語化してみてください。曖昧なまま着手すると、必ず後から「なぜそう決めたんだっけ」が問われます。

内部構造・ドメイン設計

項目選択肢の例
クラス構成単一責任・継承・委譲・ミックスイン
ドメインロジック手続き型(トランザクションスクリプト)・リッチドメイン(DDD(Domain-Driven Design、ドメイン駆動設計))
エラーハンドリングポリシー例外・Result型・エラー境界の設計
命名規則と概念モデルユビキタス言語・用語集の整備
コード規約フォーマッタ・リンター・レビュー方針

コード構成・テスト・観測

項目選択肢の例
ディレクトリ構成機能別(feature-based)/ レイヤ別(layered)
依存関係の方向循環禁止 / クリーンアーキテクチャ
テスト戦略ユニット / 統合 / E2E のバランス
バリデーション設計どの層で行うか・再利用方法
ロギング・監査ログ粒度・相関ID・PII(Personally Identifiable Information、個人を特定できる情報)のマスキング

ケース別の選定

プロジェクトの性質によって、アプリケーションアーキテクチャでどこに力を入れるかは大きく変わります。全方位に厳密な設計を施すと過剰設計になり、逆に放置すると保守性が一気に崩れるため、状況に応じて投資配分を変えます。

ケース重点を置くべき領域
新規CRUD中心アプリ命名規則とLinter/Formatterの徹底。ドメインロジックは手続き型で十分
複雑な業務ロジック(保険・金融・会計)ドメインモデルを厚く設計(DDD)。業務用語との一致(ユビキタス言語)を優先
複数チームのマイクロサービスディレクトリ構成・API契約・エラー規約をチーム横断で統一
レガシー改修プロジェクト既存の命名・構成を尊重しつつ、新規追加部分だけ段階的に規約を適用

新規CRUDアプリにDDDを持ち込むのは典型的な過剰設計で、シンプルな手続き型で書いた方が保守性が高くなります。一方で業務ロジックが複雑なドメインでは、手続き型だと条件分岐が爆発してメンテ不能になるため、ドメインモデルへの投資が効きます。レガシー改修は「既存流儀への敬意」が最優先で、新しい規約を一気に全面適用するのは失敗パターンです。

ドメインロジックの2大方針

方針特徴向くケース
手続き型(Transaction Script)処理の流れをそのまま関数化。DDDより単純小規模 / CRUD中心 / 短期プロジェクト
リッチドメイン(DDD)ビジネスロジックをドメインオブジェクト内に凝集大規模 / 複雑な業務ロジック / 長期運用

「小さく始めて、複雑化したらリッチドメインに移行」という段階的な設計変更も一般的。過剰設計を避けるため、最初からDDDありきで始めないのが健全です。

クリーンアーキテクチャの考え方

「依存の方向を内側に向ける」ことで、外側(DB・UI・FW)の変更がビジネスロジックに波及しないようにする設計原則です。

flowchart TB
    subgraph OUT["外側(変わりやすい)"]
        FW["フレームワーク / DB / UI"]
        subgraph ADAPT["インターフェース変換層"]
            subgraph USE["ユースケース"]
                ENT["エンティティ<br/>(内側=変わりにくい)"]
            end
        end
    end
    FW -->|依存は内向きのみ| ADAPT
    ADAPT --> USE
    USE --> ENT
    classDef out fill:#fee2e2,stroke:#dc2626;
    classDef adapt fill:#fef3c7,stroke:#d97706;
    classDef use fill:#dbeafe,stroke:#2563eb;
    classDef ent fill:#dcfce7,stroke:#16a34a,stroke-width:2px;
    class OUT,FW out;
    class ADAPT adapt;
    class USE use;
    class ENT ent;

規模×業務複雑度の段階表

アプリケーションアーキテクチャはコードベース規模業務複雑度で必要な投資が変わります。ざっくり結論だけ先に言うと、1万行までは素のレイヤードで十分、5万行を超えたらヘキサゴナル、20万行級の金融・保険系で初めて本格DDD。このパスが2026年時点で最もROIが合います。

コードベース規模業務複雑度推奨パターンドメイン表現ファイル行数目安
〜1万行CRUD中心レイヤード / 素のMVCTransaction Script〜300行
〜5万行中程度レイヤード or ヘキサゴナルTS + Value Object〜300行
〜20万行複雑(EC・物流)ヘキサゴナル / クリーンDomain Model(DDD軽量版)〜300行
20万行〜極めて複雑(金融・保険)クリーン + 戦術的DDD本格DDD(Aggregate等)〜300行

「1ファイル300行・1メソッド50行・循環的複雑度10」が多くのプロジェクトで採用される定量ガードレールです。これを超えたら分割の合図で、ESLint・SonarQube で自動検出するのが現代流。「新規CRUD画面にクリーン4層を適用」するのが典型的過剰設計です。

パターンは規模に合わせて段階的に昇格します。MVPにDDDは過剰、巨大プロジェクトで手続き型は破綻します。

アプリケーションアーキテクチャ全体の鬼門

各論記事で触れた禁じ手のうち、内部構造レベルで押さえるべき核心を整理します。

禁じ手なぜダメか
神クラス・God Module を育てる「ついでにここに」の積み重ねで3000行級、分割は実質書き直し
貧血ドメインモデルDDDの形だけ真似、ロジックが全部Service層
循環依存を放置A→B→Aの依存は必ずバグの温床、ESLintで検出
Util / Manager / Helper と命名責任を語らない名前、責任が明確なら具体名
継承4段以上の深いツリーLSP違反・変更の波及・理解困難
エラーを握り潰すcatch { }サイレント障害の温床、本番で原因不明
命名規則をチームごとにバラバラUser / Member / Account / Customer 問題
リトライに冪等性なし二重決済・二重登録の定番、Idempotency-Key 必須
コメントにWHAT(何を)を書くコードで分かることを書くな、WHYを書く
Linter / Formatter をCIで強制せずREADME記載守られない規約は存在しないのと同じ

アプリケーションアーキテクチャは規約の徹底で決まります。ツールで機械的に強制するのが唯一の解です。

AI時代の視点

AI駆動開発(バイブコーディング)が前提になると、アプリケーションアーキテクチャは「AIが書いたコードを人間が読んで判断できるか」が価値を決めます。AIはクラスもドメインロジックも高速に量産できますが、設計上のブレを無限に生み出すため、「明確な規約と型でAIを制約する」ことが重要になります。

AI時代に有利AI時代に不利
厳格な型・スキーマ・インターフェース定義動的型付け・暗黙の規約
統一されたディレクトリ構成・命名規則チームごとの暗黙のスタイル
純粋関数・副作用の分離(Hexagonal等)副作用の多い手続き型コード
単一責任の小さなクラス・関数巨大な神クラス・長い関数

AIが書いたコードは表面的に正しく見えて本質がズレていることが多く、命名規則や責任分離がブレると一気にメンテ不能になります。AIに対して「この規約・この型・この責任範囲」と明示できる設計が、これからのアプリケーションアーキテクチャの価値になります。

よくある勘違い

  • DDDはクラスを増やせば実践できる」 → DDDの本質は業務用語とコードの一致(ユビキタス言語)です。Entity・ValueObject・Aggregateといったクラスを並べても、業務の言葉で会話できなければDDDではない
  • 「アプリケーション設計=クラス図を描くこと」 → クラス図は成果物の一部でしかなく、命名規則・エラー方針・ディレクトリ構成・テスト戦略といった地味な規約の方が日々の生産性を左右する
  • 「命名規則は個人の趣味の問題」 → チーム内で命名がズレると、コードを読むたびに「このUserServiceはUserManagerとどう違うのか」を推測する無駄が発生し、累積で設計議論の時間を圧迫する
  • 「例外処理は後から追加すればいい」 → エラー設計は実装の後付けでは必ず漏れる。どの層で何を捕まえて何を上に伝えるかは、クラス設計と同時に決めるべき一次判断

最終的な判断の仕方

アプリケーションアーキテクチャは内部構造の規約で、ソフトウェアアーキテクチャが決めた大枠の中で、「チーム全員が同じコードを書けるようにするためのもの」です。ここでの選定は比較的変更しやすい(Two-way Door)ですが、一貫性が崩れると保守性が一気に下がる。核心は「何が正しいか」ではなく「チーム全体で同じ書き方を徹底できるか」に尽きます。

DDD・クリーンアーキテクチャ・ヘキサゴナルといった思想は魅力的ですが、それ自体を目的にすると過剰設計になる。小さく始めて、複雑化したら段階的に強化するのが健全なパスです。

現代の決定的な軸は「AIを規約で縛れるか」AIはコードを高速に量産しますが、同時に設計上のブレを無限に生み出します。厳格な型・統一された命名・明確な責任分離・ディレクトリ構成の規約があれば、AIはその枠内で正確なコードを生成できる。逆に曖昧な規約のプロジェクトでは、AIが生成するコードが毎回少しずつ違うスタイルになり、コードベースが急速に崩壊します。

AIに与える制約こそがアプリケーションアーキテクチャの新しい価値で、型・スキーマ・インターフェースをコードで明示できる設計が圧倒的に有利になります。

選定の優先順位をまとめると次の通りです。

  1. ソフトウェアアーキテクチャと整合させる(大枠の制約を守る)
  2. 一貫性を最優先にする(思想より規約徹底)
  3. 小さく始めて必要なら強化DDDありきは過剰設計)
  4. 型・規約・構成をコードで明示(AI時代の必須条件)

まとめ

本記事はシリーズ『生成AI時代のアーキテクチャ超入門』の「アプリケーションアーキテクチャ」カテゴリの入口として、内部構造の規約をどう決めるかの全体像を解説しました。如何だったでしょうか。

思想の選択より規約の徹底、過剰設計より段階的成長、人間のためだけでなくAIへの制約として設計する。これがアプリケーションアーキテクチャの3つの核です。

次回からはこの領域の各論に入り、まずクラス設計(SOLID原則・継承vs委譲)から解説していきます。

シリーズ目次に戻る → 『生成AI時代のアーキテクチャ超入門』の歩き方

それでは次の記事も閲覧いただけると幸いです。