ソフトウェア設計

ライブラリとフレームワークの違いは「誰が誰を呼ぶか」(制御の反転)

Alamofireはライブラリ、SwiftUIはフレームワークと呼びます。でも、どちらも「誰かが作ったコードを使う」ものではありませんか。何が違うのでしょうか。

読了 5 分
ライブラリとフレームワークの違いは「誰が誰を呼ぶか」(制御の反転)のカバー画像

Alamofireはライブラリ、SwiftUIはフレームワークと呼びます。でも、どちらも「誰かが作ったコードを使う」ものではありませんか。何が違うのでしょうか。

「フレームワークのほうが大きい」とよく言われますが、本質は規模ではありません。小さなフレームワークも巨大なライブラリもあります。

誰が誰を呼ぶのか。

この1つの基準を押さえると、重要な概念である制御の反転(IoC)にも自然につながります。依存性注入を学ぶときにも再び登場する概念なので、ここで正しく理解しておくと役立ちます。

要点をまとめます。

  1. ライブラリ:必要なときに自分のコードから呼び出すツール群。制御権は自分にある
  2. フレームワーク:流れを握り、自分のコードを呼び出す骨格。制御権はフレームワークにある
  3. この逆転した呼び出し方向を制御の反転(Inversion of Control)と呼びます
  4. ハリウッドの原則:「こちらに電話しないでください。こちらから連絡します」

ライブラリ:自分が呼び出すツール

ライブラリは、特定の機能をあらかじめ実装したコードのまとまりです。いつ、どの順番で使うかは、すべて自分のコードが決めます。

// 流れの主導権は自分のコードにある
let json = try JSONDecoder().decode(User.self, from: data)
let hash = SHA256.hash(data: input)

プログラムの開始と終了、全体の流れを自分で設計し、途中で必要なツールを取り出して使います。工具箱からドライバーを取り出すようなものです。ドライバーが作業の順番を決めるわけではありません。

AlamofireやKingfisherがこの範囲に入ります。いつネットワーク要求を送るか、いつ画像を読み込むかは自分で決めます。


フレームワーク:自分を呼び出す骨格

フレームワークは、アプリケーション全体の構造と実行フローをあらかじめ用意した骨格です。自分は、その骨格が空けておいた場所にコードを埋め込みます。

iOSアプリを考えると明確です。アプリの開始点、イベントループ、画面のライフサイクルはすべてUIKitとSwiftUIが握っています。自分が書くviewDidLoad、body、onAppearなどは、フレームワークが決められたタイミングで呼び出すコードです。

struct ProfileView: View {
    var body: some View {   // 自分からは呼び出さない.
        Text("Hello")       // SwiftUI必要なときに呼び出す
    }
}

bodyを自分で呼び出すことはありません。いつ何回呼び出すかはSwiftUIが決めます。流れの主導権が入れ替わったのです。

呼び出し方向が逆です。これが制御の反転です。
呼び出し方向が逆です。これが制御の反転です。

制御の反転とハリウッドの原則

この逆転した関係には名前があります。制御の反転(IoC)です。

通常の手続き型プログラムでは、自分のコードが制御フローを握り、外部コードを呼び出します。フレームワークベースのプログラムでは、フレームワークがフローを握り、自分のコードは登録した箇所で呼び出されます。制御権が逆方向に移るため「反転」と呼ばれます。

これを機知に富んだ表現にしたものが、ハリウッドの原則です。

「こちらに電話しないでください。こちらから連絡します」— 電話せず、こちらから連絡します。

オーディションを受けた俳優が制作会社に電話をかけ続けるのではなく、起用されると制作会社から連絡が来ます。フレームワークと自分のコードの関係は、まさにこれです。

デリゲートパターンも同じ原理です。UITableViewDataSourceを実装するとき、cellForRowAtを自分で呼び出しますか。いいえ。必要なときにテーブルビューが自分を呼び出します。フレームワークの世界の作法がコードのいたるところに浸透しているのです。


実務では何が変わるのか

学び方が異なります。ライブラリでは「どんな機能があるか」を調べればよい一方、フレームワークではまず「いつ自分を呼ぶのか」(ライフサイクル・呼び出し規約)を学ぶ必要があります。UIKitの学習がライフサイクルから始まる理由です。

置き換えコストが異なります。ライブラリは呼び出し箇所を直せば乗り換えられますが、フレームワークはコード全体がその骨格の上にあるため、置き換えは事実上の書き直しです。UIKitからSwiftUIへの移行が、数個の関数を変えるだけでは済まない理由です。

テスト戦略が異なります。フレームワークが呼び出すコードは、フレームワークなしで単独実行するのが困難です。そのため、ロジックをフレームワーク非依存の層(純粋なSwift)に分離するよう繰り返し勧められます。

電話しないでください。こちらから連絡します — ハリウッドの原則
電話しないでください。こちらから連絡します — ハリウッドの原則

面接で一文にまとめると

「ライブラリは自分のコードが呼び出すツールで、フレームワークは制御フローを握って自分のコードを呼び出す骨格です。この制御権の方向の違いを制御の反転と呼びます」

続く質問は「IoCの例を挙げてください」(ライフサイクルメソッド、デリゲート)、「それがなぜよいのですか」(フローを標準化し、開発者がビジネスロジックに集中できる)という順になります。


まとめ

  • 区別の基準は規模ではなく、呼び出し方向です
  • ライブラリ:必要なときに自分のコードが呼び出すツール。制御権は自分にある
  • フレームワーク:流れを握り、決められたタイミングで自分のコードを呼び出す骨格。制御権はフレームワークにある
  • この逆転した制御権が制御の反転(IoC)で、別名はハリウッドの原則です
  • viewDidLoad、body、デリゲートメソッドはすべて「呼び出される」コードです
  • 実務上の違い:まずフレームワークのライフサイクルを学び、置き換えは難しく、ロジック分離がテストの要になります