SwiftUIの紹介文書の冒頭には、必ずといってよいほど「宣言的(declarative)フレームワーク」という言葉が登場します。ReactもJetpack Composeも、自らを宣言的だと説明しています。
ところが「宣言的とは何ですか?」と聞かれると、答えに困ります。「コードがきれいということ」は正解ではありません。
宣言的と命令的の違いは、一文で分かれます。「How(どのように)」を書くのか、「What(何を)」を書くのかです。
この記事では、日常的な例でこの基準を捉え、UIKitとSwiftUIのコードで確認したうえで、宣言的が無料ではないことまで扱います。
要点をまとめます。
- 命令的:望む結果に到達する手順を段階的に指示する — How
- 宣言的:望む結果を記述し、手順はシステムに任せる — What
- SQL、HTML、map/filter、SwiftUIは宣言的アプローチの代表例
- 宣言的UIの本質:「状態がこうなら、画面はこうなる」と宣言すると、状態変化に応じた更新をフレームワークが行うこと
タクシーにたとえると
命令的とは、運転手に道順を直接伝えることです。「右折して、300メートル直進、信号で左折…」と手順を一つずつ指示し、その積み重ねで目的地に到着します。
宣言的とは「江南駅までお願いします」です。目的地(What)だけを伝え、経路の選択(How)は運転手とナビゲーションに任せます。
どちらも目的地に着きます。違いは、自分が手順を所有するのか、結果の記述だけを所有するのかです。
コードでは同じことを2通りの方法で書けます
偶数だけを選び、二乗するコードを2通りで書いてみましょう。
// 命令的:どう走査し、どこに格納するかを自分で指示する
var result: [Int] = []
for n in numbers {
if n % 2 == 0 {
result.append(n * n)
}
}
// 宣言的:何が欲しいかだけを記述する
let result = numbers.filter { $0 % 2 == 0 }.map { $0 * $0 }
命令的なバージョンでは、ループ変数や中間配列、順序といった「手順の部品」が表に出ます。宣言的なバージョンに残るのは「偶数を絞り込み、二乗したもの」という意図だけです。走査方法はfilterとmapの内部に隠れています。
より身近な宣言的アプローチも、すでに使っているはずです。SQLでは「この条件の行をください」とだけ書き、インデックスの探索方法は書きません。HTMLも「ここに見出し、ここに段落」と構造だけを宣言し、描画手順は書きません。
UIでは違いが劇的に大きくなります
命令的UI(UIKit)は、画面を変更する手順を書きます。
// UIKit: 状態が変わるたびに画面操作を直接指示する
func updateBadge(count: Int) {
if count > 0 {
badgeLabel.isHidden = false
badgeLabel.text = "\(count)"
} else {
badgeLabel.isHidden = true
}
}
この方式の難しさは、「現在の画面がどの状態にあるか」を開発者が常に追跡しなければならないことです。更新経路が複数あると一つ抜けやすく、「データは変わったのに画面はそのまま」というバグになります。
宣言的UI(SwiftUI)は、状態に応じた画面の姿を宣言します。
// SwiftUI: count状態がこうなら画面はこうなる、と宣言する
struct BadgeView: View {
let count: Int
var body: some View {
if count > 0 {
Text("\(count)").badgeStyle()
}
}
}
countが変わったときに画面をどう直すかは書きません。SwiftUIが以前の宣言と新しい宣言を比較し、必要な部分だけを更新します。UIを「状態の関数」にしたのです。更新手順の所有権をフレームワークに渡したため、更新コードを入れ忘れる余地もありません。
宣言的は無料ではありません
バランスを取るために、反対側も見ておく必要があります。
手順を隠した代わりに、手順が必要なときはもどかしくなります。「スクロールを正確にこのオフセットへ移動して」のような命令的な要求には、宣言的フレームワークではむしろ回避策が必要です。
デバッグの質感も異なります。命令的なら手順を追えばよいのに対し、宣言的では「なぜ再描画されたのか」のように、フレームワークの判断を追跡する必要があります。隠れたHowを知らなくてよいわけではありません。
パフォーマンスチューニングも、結局は内部の理解に戻ってきます。SwiftUIでビューが過剰に再計算されるときは、解決のためにdiffingと依存関係の追跡がどう動くかを知る必要があります。
したがって正確な見方は「宣言的が優れている」ではなく、抽象化レベルの選択です。手順の所有権を渡せばコードは意図中心に単純になりますが、その代わり細かな制御と内部理解が課題として残ります。
まとめ
- 命令的は結果に到達する手順(How)を指示し、宣言的は望む結果(What)を記述する
- SQL・HTML・map/filterは、すでに身近な宣言的アプローチである
- 命令的UIは画面を変更する手順を書き、状態と画面の不一致バグが起きやすい
- 宣言的UIは「状態がこうなら画面はこうなる」と宣言し、更新はフレームワークに任せる(UI = 状態の関数)
- 宣言的の代償は、細かな手順の制御が難しく、最終的にはフレームワーク内部の動作理解が必要になること
- 本質は優劣ではなく、誰が手順を所有するかという選択である

