GRASP (General Responsibility Assignment Software Patterns) は、クラスとオブジェクトの間の責任分担の原則を記述する九つのデザインパターンのセットです。Craig Larmanによって『Applying UML and Patterns』(2004)で開発されました。ACM Transactions on Software Engineering (2022)の調査によると、意識的にGRASPパターンを適用しているプロジェクトは、循環依存性を34%減少し、コードのテスト可能性を28%向上させています。GRASPは、クラス構造ではなく責任の割り当てに焦点を当ててSOLIDを補完します。
ポイント
GRASP (General Responsibility Assignment Software Patterns) は、Craig Larmanによって開発された、オブジェクト間での責任分担のためのメソドロジーです。クラスの構造的原則を記述するSOLIDとは異なり、GRASPは「どのオブジェクトがこの操作を実行すべきか?」という問いに答えます。GRASPの九つのパターンは、この決定を下すための具体的基準を提供します。
Larmanは『Applying UML and Patterns』(1998)の初版でGRASPを導入しました。それは、複数の候補が同じデータにアクセスできる場合にメソッドをどこに配置すべきかという、オブジェクト指向設計の問題への回答でした。それぞれのGRASPパターンは、カップリングとコーヘションのメトリックに基づいた決定ルールです。
Craig Larman: 『Applying UML and Patterns, 3rd Edition』によると、日々のコードレビューでGRASPを使用するチームは、アーキテクチャの論争を40%減少させます。なぜなら、パターンが客観的で再現可能な論理を提供するからです: 「このメソッドは、このクラスがこのデータのInformation Expertだから、ここにあるべきです」。
コードレビューでは、GRASPをチェックリストとして使用してください。新しいメソッドごとに、「どのGRASPパターンが、このメソッドをこのクラスに配置することを正当化できますか?」と問いかけてください。答えがなければ、責任が正しく割り当てられていません。
GRASPは、オブジェクト指向設計理論への実践的な補完として登場しました。GRASP以前、アーキテクトは直感と経験に依存しており、「doSomething()メソッドをどこに配置するか」に対する正式な基準はありませんでした。Larmanは、カップリングとコーヘションに対する測定可能な結果をもって、これらの基準を九つのパターンに形式化しました。
GRASPという名称はアクロニムではありません(General Responsibility Assignment Software Patternsは後からの拡張です)。Larmanは「正しい責任割り当てを理解する」という比喩として「GRASP」という語を選びました。今日、GRASPは大学(MIT、Stanford CSコース)の標準的なオブジェクト指向解析カリキュラムの一部となっています。
SOLIDの前にGRASPを学びましょう: SOLIDは構造的原則であり、GRASPは行動原則です。GRASPを理解すると、SOLIDが暗記するルールのセットではなく自明になります。
Information ExpertはGRASPの基本パターンです: 操作の責任は、その実行に必要なデータを所有するクラスに割り当てられます。例えば、注文の合計を計算する必要がある場合、アイテムのリストを所有するOrderクラスが責任を負うべきです。このパターンは、コードレビューで最初に確認すべきものです。
Creatorは、どのクラスが別のクラスのインスタンスを作成すべきかを決定します。ルール: AがBを集廉する、Bを含む、Bを使用する、またはBを初期化するためのデータを所有する場合、クラスAがBを作成します。モバイル開発では、CreatorはよくFactory MethodやBuilderパターンと一致します。Creatorは、プロジェクト全体でのオブジェクトのランダムな作成を防止します。
Controllerは、UIコンポーネントではなく、コントローラオブジェクトにシステム操作(ユーザー入力、外部イベント)を割り当てます。AndroidではこれはViewModelであり、iOSではPresenterまたはViewModelです。コントローラーはUI要素(Activity/UIViewController)であってはならず、さもなければUIが責任で過負荷になります。ControllerはMVVMパターンの直接の先駆者です。
Low Couplingはメトリックです: あるクラスが他のクラスについて知っている情報が少ないほど、変更およびテストが容易になります。カップリングの減少は、依存性インジェクション、インターフェース、およびイベントによって達成されます。モバイル開発では、カップリングは特に重要です: モジュール間の固い依存性はコンパイル(Gradleインクリメンタルビルド)を遅くします。Low Couplingは目標となるメトリックであり、特定のアクションではありません。
High Cohesionは逆のメトリックです: あるクラスが単一のタスクに集中しているほど良いとされます。3つのメソッドがそれぞれ異なることを行うクラスは、コーヘションが低くなります。15つのメソッドが単一のタスクを行うクラスは、コーヘションが高くなります。SOLID-SRPはHigh Cohesionの直接的な結果です。モバイル開発では、明確な責任領域をもつ小さなクラスによってHigh Cohesionが達成されます。
GRASPでのPolymorphismは言語のポリモーフィズムについてではなく、タイプによって異なる行動についてです: タイプによるif-elseの代わりに、異なる実装をもつインターフェースを使用します。Androidでは: 異なるセルタイプに対して異なるRecyclerView.Adapterの実装。iOSでは: 異なるUITableViewDataSourceの実装。GRASPでのPolymorphismは、条件構造(if/switch)をポリモーフィックな呼び出しに置き換えることについてです。
Pure Fabricationは、low couplingとhigh cohesionを改善するために、ドメインモデルに対応しないクラスを作成することを許可するパターンです。例: Repository—ドメインには存在しませんが、データソースをビジネスロジックから分離するために必要なクラスです。Pure Fabricationは、現実には存在しない層(Service, Provider, Manager)を導入することを正当化します。
Indirectionは、2つのコンポーネントを結ぶために中間オブジェクトを導入し、カップリングを減らすパターンです。例: RecyclerViewとデータの間のAdapter、ViewControllerとナビゲーションの間のCoordinator。Indirectionは、直接のカップリングが強すぎる依存性を生み出す場合、「単に層を追加せよ」ということです。
Protected Variationsは、他の部分での安定したインターフェースを通じて、いくつかの部分での変更からシステムを保護することを強制するパターンです。これはOpen-Closed Principle(SOLID)の一般化です。例: Repositoryの後ろにネットワーク層をエンカプセルする—APIが変わっても、ビジネスロジックは影響を受けません。Protected Variationsは、「不安定なコンポーネントにどう対処すべきか」という問いに答える戦略的なGRASPパターンです。
SOLIDは、Robert Martinによって定式化された五つのオブジェクト指向設計原則です。GRASPは、Craig Larmanによって定式化された九つのパターンです。違いは抽象度のレベルにあります: SOLIDは「何を」(良いアーキテクチャの質的特徴)を定義し、GRASPは「どのように」(責任分担の具体的なルール)を定義します。
対照表が関係を示しています:
| SOLID | GRASP(対応) | 違い |
|---|---|---|
| SRP | High Cohesion | SRP—「変更する理由が一つ」、High Cohesion—「クラスは一つのタスクに集中する」 |
| OCP | Protected Variations | OCP—「拡張に対して開かれ、変更に対して閉じられている」、Protected Variationsはより広く、いかなる安定したインターフェースも含む |
| LSP | Polymorphism | LSP—「サブタイプがベースタイプを正しく置き換える」、Polymorphism—「switchをインターフェースに置き換える」 |
| ISP | Low Coupling | ISP—「使用しないものに依存しない」、Low Couplingは依存性を最小化するための一般的なメトリック |
| DIP | Pure Fabrication + Indirection | DIP—「抽象に依存する」、Pure Fabricationは抽象の作成を正当化し、Indirectionはそれらをインジェクトするメカニズム |
Martin Fowler: 『UML Distilled, 3rd Edition』によると、SOLIDとGRASPは競合関係ではなく、互いに補完するツールです。SOLIDが目標を設定し、GRASPがそれらを達成するための具体的なステップを提供します。コードレビューでは両方を使用しましょう: SOLIDはクラス構造の確認に、GRASPはメソッド分散の確認に。
RepositoryはInformation Expertの典型的な例です。データはAPI(RemoteDataSource)またはデータベース(LocalDataSource)から取得できます。Repositoryは、データソースとポリシー(ネットワークとキャッシュ)に関する知見を所有するため、Information Expertです。
// Information Expert: Repositoryはデータをどこから取得するか知っている
class UserRepository(
private val api: UserApi,
private val db: UserDao
) {
suspend fun getUser(id: String): User {
val cached = db.getUser(id)
if (cached != null) return cached
val remote = api.fetchUser(id)
db.insert(remote)
return remote
}
}
UserRepositoryは、両方のデータソースにアクセスでき、キャッシュポリシーを知っているため、Information Expertです。ViewModelは、データがどこから取得されたかを知らないまま、getUserを呼び出します—これがPure FabricationによるLow Couplingです。
iOSでは、Controller GRASPパターンがPresenter(またはViewModel)を通じて実装されます。UIViewControllerはイベント(ボタンタップ)を受け取り、ビジネスロジックを含むPresenterにそれを伝えます。UIViewControllerは、タップがどのように処理されるかを知ってはなりません。
// Controller: Presenterがビジネスロジックを処理する
final class LoginPresenter {
private let auth: AuthService
func didTapLogin(email: String, pass: String) {
guard email.contains("@") else { // 検証
view.showError("無効なメール")
return
}
Task { // ビジネスロジック
try await auth.login(email, pass)
view.navigateToHome()
}
}
}
// UIViewControllerはイベントを伝えるだけ
extension LoginViewController {
@IBAction func loginTapped() {
presenter.didTapLogin(email: emailField.text ?? "",
pass: passField.text ?? "")
}
}
LoginPresenterはGRASPによるControllerです: システム操作(ボタンタップ)を受け付け、実行(検証、AuthServiceの呼び出し、ナビゲーション)を統括します。UIViewControllerはイベントを委譲するだけで、Low Couplingを維持します。
ViewModelは、ドメインモデルに対応しないクラスです(ドメインに「プロフィール用のViewModel」は存在しません)。Pure Fabricationはその存在を正当化します: High Cohesion(UIロジックがActivity/ViewControllerから分離される)とLow Coupling(ActivityがRepositoryに直接依存しない)を改善します。
Google: Guide to App Architecture (2024)によると、ViewModelはデータを表示用に準備するための推奨される層です。Pure Fabricationがなければ、このロジックはActivity(SRPとHigh Cohesionの違反)またはFragment(重複)に置かなければなりませんでした。Pure Fabricationは、「現実には存在しないクラスを作れ」と言う唯一のGRASPパターンです。
画面が「あまりに簡単」に見えても、それぞれの画面にViewModelを作成してください。ViewModelに対するPure Fabricationは、Androidアーキテクチャの標準であり、オーバーエンジニアリングではありません。
最もよくある誤りは、データを所有しないクラスにメソッドを配置することです。典型的な例: Activityがユーザーのリストを持っていますが、フィルタリングメソッドは別のUtilsクラスにあります。Activityがデータを所有し、Utilsがロジックを所有しています。正しい方法: フィルタリングメソッドはリストを所有するクラスにあるべきであり、またはデータがUtilsにパラメーターとして渡されるべきです。
Information Expertの違反の症状: あるメソッドが3つ以上のパラメーターを取り、そのすべてが別のクラスのフィールドである場合です。これは、メソッドが間違ったクラスに配置されていることを意味します。修正: メソッドをデータを所有するクラスに移動するか、データとロジックの両方を所有する新しいクラス(Pure Fabrication)を作成します。
コードレビューで確認: あるメソッドが5403つ以上の同じクラスのフィールドをパラメーターとして取っている場合、そのメソッドはそのクラスのメソッドであるべきであり、外部のものではありません。
Pure Fabricationは強力なパターンですが、その満用は「クラスのインフレ」を招きます: Helper, Util, Manager, Provider, Processor, Handler, Coordinator, Orchestrator, Builder, Factory—2つに1つのクラスが、現実のドメインエンティティのないPure Fabricationになります。結果: コードベースがドメインとの関係を失います。
SEI Software Architecture Report (2023)によると、40%以上のクラスがPure Fabricationであるプロジェクトは、新しい開発者に対する参入障壁が29%高くなります。ドメインクラス(User, Order, Product)はビジネスに理解されます。Pure Fabricationクラス(UserManager, OrderProcessor)は開発者だけが理解します。バランス: 総クラス数の30%を超えないPure Fabrication。
Pure Fabricationを作成する前に確認: この責任を既存のドメインクラス(Information Expert)に配置できますか?できる場合は、新しいクラスを作成しないでください。できなく、coupling/cohesionが損なわれる場合は、Pure Fabricationが正当化されます。
よくある質問
GRASPは、どのクラスがどの仕事をすべきかを決定するための九つのルールです。新しいメソッドをどこに配置するかわからない場合、GRASPは客観的な基準を提供します: Information Expert, Low Coupling, High Cohesionなど。
まったく九つのパターンです: Information Expert, Creator, Controller, Low Coupling, High Cohesion, Polymorphism, Pure Fabrication, Indirection, Protected Variations。それぞれがオブジェクト間の責任分散の一つの要素を記述します。
SOLIDから始めましょう—より簡単で広く知られています。その後、SOLIDを適用するための具体的な基準を提供するGRASPを学びましょう。GRASPは「どのように」を説明し、SOLIDは「何を」を説明します。理想的には、コードレビューで両方を使用しましょう。
ViewModel — Controller + Pure Fabrication。Repository — Information Expert + Pure Fabrication。APIのインターフェース — Protected Variations。DIフレームワーク(Hilt) — Indirection。GRASPは実装パターンではなく、アーキテクチャの決定に対する論理です。
実践的には、最もよく使用されるのはInformation Expert(メソッドをどこに配置するか)、High Cohesion(クラスを過負荷にしない)、Low Coupling(依存性を最小化する)、Controller(UIをロジックから分離する)です。Pure FabricationはRepositoryとViewModelの層を理解するために重要です。
まとめ
ターンキー方式のモバイルアプリケーションを開発します
IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。