はじめに
TRIAL&RetailAI Advent Calendar 2025 の 4 日目の記事です。
昨日は @atsukishさんの『Anthropic が示した「コード実行で 98.7% トークン削減」を安全に実装する』でした。AIエージェントが生成したコードを安全に実行するための仕組みとして、Python Code Executor MCPサーバーが紹介されました。ぜひチェックしてみてください。
今回はライティングソフトウェアについてまとめます。
私の所属するチームではライティングソフトウェアの考え方を前提に設計が進められており、自分自身も必要な知識として理解しておく必要があると感じ、今回この本を読み始めました。読んだ書籍はこちらです。

レビューでは「独りよがり」「たとえ話が多い」といった声もありますが、内容自体は読む価値のある一冊だと感じます。対象読者はソフトウェアアーキテクト向けとされていますが、スキルセットを広げたい開発者にも役立つとのことです。
なお、今回まとめているのは第4章までの内容となります。
第1章 ザ・メソッド
ザ・メソッドは「テクニック」と書かれているが、複数の手法をまとめた総称だと思われます。ザ・メソッド=システムデザイン+プロジェクトデザインとあり、システムデザインとプロジェクトデザインについては第2章で詳しく説明されています。
- システムデザイン: システムの分割方法
- プロジェクトデザイン: スケジュールの管理
また、デザインに時間をかけすぎない方がよく、ザ・メソッドを使うことでコミュニケーションが円滑になると書かれています。
第2章 分解
まず、機能別分解をしてはいけないと書かれています。
機能別分解をするとサービスを再利用できなくなったり、機能の違いの分だけサービスが増えることになるので大きくなりすぎるとのこと。
例えば機能別分解によって家を設計すると、料理ごとにキッチンを作ることになると書いています。朝食だったら朝食用のキッチン、昼食だったら昼食用のキッチン...という感じでキッチン(サービス)が爆発的に増えることとなります。
機能別分解は悪いという内容がほとんどですが、要件を見つけるテクニックとしては役に立つと書かれています。
また、ドメイン別分解もしてはいけません。再度、家の設計の例になりますが、例えば家をドメイン別分解で設計したとき、台所、寝室、居間...というようにドメインを分けることができます。このとき、台所は料理をするところ、寝室は寝るところ...とすると、居間で寝たり台所でホームパーティ(?)ができなくなるそうです。したがってドメイン別分解というのは形を変えた機能別分解であると記述されています。
変動性に基づく分解
この機能別分解を避けるためには、変動性に基づく分解を行います。
変動性に基づく分解とは、変更される可能性がある領域を明らかにし、その部分をサービスやシステムの部品としてカプセル化することです。

例えば、この画像のようにカプセル化された領域(金庫)内で変動(爆発)が起こったとき、他の領域に影響しません。
ただ、この変動性に基づく分解は難しく、とても時間がかかるものだと述べられています。以降は、変動性を持つ領域を探し、見分けるための手法の紹介となります。
変動領域の見つけ方
変動領域探しには、変動性の軸を使います。
- 変動性の軸
- 時間とともに同じ顧客に発生する変動性
- 同じ時点で異なる顧客の間で発生する変動性
ここでも家の例を使って、変動性に基づく分解を説明します。
家の例で考えると、家具や住人、家電は時間とともに変動します。また、自分の家と他の家を比べると、構造や隣人の違いにより、同じ時点でも変動が生じていることがわかります。
要件を装うソリューション
目的と手段が混同されやすいように、要件とソリューションは別物です。
例えば料理は要件ではなく、「家の住人に食事を提供する」という要件に対するソリューションの一つに過ぎません。
変動領域を明確にするためには、変動領域かもしれないもののリストを作り、それらが変動領域である根拠を示します。
変動性のリスト例
- ユーザー:顧客やシステム管理者の種類によって変動
- クライアントアプリ:顧客に応じて異なるアプリ環境
- セキュリティ:ユーザーに応じて認証方式が変わる
- 通知:メール送信は手段であり、要件は「ユーザーに通知を送ること」
変動領域が明確になったら、それをアーキテクチャのコンポーネントとしてカプセル化します。
変動性とビジネスの本質
変化する可能性があるからといって、すべてをカプセル化する必要はありません。
例えば、1軒の住宅を将来50階建てに拡張する可能性までカプセル化すると、普通の住宅設計とは大きく異なるものになります。これはビジネスの本質は変えることと同じことを意味します。
第3章 構造
この章では、システムをどのように構造化するかを解説します。
ネズミとゾウは大きく異なるが、同じアーキテクチャを使っています。ただし、細かいデザインでは差があるように、ザ・メソッドはシステムアーキテクチャを提供できるが、詳細設計までは提供できません。
ユースケースと要件
多くのプロジェクトでは、機能要件を使いがちですが、必要なのは必要なふるまいを表すことです。ユースケースは、システムがどのように仕事を達成し、ビジネスに価値を与えるかを表します。
ユースケース図:
アクティビティ図
アクティビティ図は、フローチャートでは表現できない並列実行や待ちなどの時間的側面を捉えられ、条件のネストも追いやすいのが利点です。
階層構造とサービス活用
階層構造を使うと変動性のカプセル化がしやすく、スケーラビリティ、セキュリティ、可用性、信頼性、整合性、同期の面でメリットがあります。
- 典型的な階層:
クライアント層:プレゼンテーション層
ビジネスロジック層:ビジネスロジックの変動性をカプセル化
リソースアクセス層:リソースアクセスの変動性をカプセル化
リソース層:物理リソース(DB、ファイル、MQなど)
ユーティリティ層:共通インフラ(セキュリティ、ロギング、pub/subなど)
- サービス名の付け方:
- 複合語の Pascal ケース
- 2語目はサービスタイプ(Manager, Engine, Access など)
- 1語目はカプセル化対象に応じた名詞
- エンジンの1語目のみ動名詞OK
- アトミックなビジネス動詞1は使わない
- アーキテクチャのポイント:
- 下に行くほど変動性が低く、再利用性が高い
- オープンアーキテクチャ:
どの階層でも任意のコンポーネントを呼び出すことができる -> 柔軟だが密結合になる - クローズドアーキテクチャ:
上位階層の呼び出しと、同一階層の呼び出しを禁止する -> 柔軟性を犠牲にしてデカップリングを促進
普通のビジネスシステムの最良の選択は、常にクローズドアーキテクチャですが、クローズドアーキテクチャは最も融通が効かないアーキテクチャでもあります。このアーキテクチャは最もデカップリング、最もカプセル化される反面、ビザンチン将軍レベルの複雑さを招きかねないらしいので、ザ・メソッドではクローズドアーキテクチャのルールを緩和して、カプセル化とデカップリングを犠牲にすることなく、複雑度とオーバーヘッドを軽減します。
クローズドアーキテクチャのルール緩和
- ユーティリティ呼び出し👌
アーキテクチャの全てのコンポーネントはユーティリティを呼び出して良いことになっています。 - ビジネスロジックによるリソースアクセス呼び出し👌
- マネージャーからのエンジンの呼び出し👌
- マネージャーからマネージャーへのキューイングされた呼び出し👌
マネージャーは同レベルの他のマネージャーを呼び出してはならないが、キューを介して他のマネージャーを呼び出すことは許されます。
章の最後では、デザインの「べからず集」が記載されています。
以下、補足です。
-
マネージャーとエンジンの違い:
- マネージャー:シーケンスの変動性をカプセル化
シーケンスの変動性の例:
- エンジン:アクティビティの変動性をカプセル化
- マネージャー:シーケンスの変動性をカプセル化
第4章 組み立て
要件は変わるものなので、要件が変わっても対応できるデザインにすることが重要です。要件に合わせてデザインを作ってしまうと、要件が変わったときに設計も変更しなければならず、良くありません。そこで、組み立てられるデザインを目指すことが推奨されています。
全てのユースケースを満たすことは基本的に不可能なので、まずはビジネスの本質に関わるコアユースケースを特定することが大切です。アーキテクトとしての役割は、コアユースケースをすべて満たすために、組み合わせて使える最小限のコンポーネントセットを見つけることです。
「機能とは、単独の実装の問題ではなく、インテグレーションの問題である」とも述べられています。例えば車で考えると、「特定の地点から特定の地点まで人を運ぶ」という機能があります。しかし、この機能が実現するのは、エンジンやシート、ドライバー、道、保険、燃料など、必要な要素がすべてそろい、正しく組み合わさったときです。つまり、機能は各要素の統合によって初めて成立するということです。
さいごに
本記事は、ライティングソフトウェア4章までのまとめでした。まだ途中までなので、引き続き読み進めていきたいと思います。
明日のアドベントカレンダーは、@fujithuro さんの『未来の自分を泣かせないコミットメッセージ』です。お楽しみに!
最後になりますが、Retail AI と TRIAL ではエンジニアを募集しています。
この記事を見て興味を持ったという方がいらっしゃいましたら、ぜひご連絡ください!
-
細分化して分解できないレベルの小さなアクティビティ。例えば、Insert(), Delete()など。 ↩

