2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

CI/CD だけじゃない。対で覚えるエンジニアリング用語、11ペア集めてみた。

2
Last updated at Posted at 2026-07-04

はじめに

CI/CD。

この2つ、片方だけを口にすることは、あまりない。CI と言えば CD が続くし、CD と言えば CI が前提にある。セットで初めて意味をなす。

エンジニアリングの世界には、こういう「対で語られる用語」がたくさんある。そしてよく見ると、対のあり方は一様じゃない。大きく2種類に分けられる。

1つは、セットで一つの仕組みを成す対。送る側がいれば受ける側がいる、という構造上の対。片方を理解すれば、もう片方の役割が予測できる。

もう1つは、似ているせいで混同される対。仕組みとしてセットなわけではなく、概念が近いために取り違えられる。こちらは対比して差分を押さえないと、正しく使い分けられない。

この記事では、対になる用語を11個、この2グループに分けて整理した。各ペアに Mermaid の図を付けたので、リファレンスとして辞書のように使ってもらってもいい。

用語の対応関係には独断が含まれる。「これは対じゃない」「こっちの方が対だ」があればコメントで教えてほしい。

対で動くペア ── 片方が分かれば、もう片方が読める

最初のグループは、セットで一つの仕組みを成すペア。片方の存在が、もう片方の存在を要求する。

発行 / 購読 ── Publisher / Subscriber(Pub/Sub)

メッセージを発行する側と、購読する側。

ポイントは、Publisher と Subscriber が直接お互いを参照しないこと。Publisher は「誰が受け取るか」を知らずにトピックへ発行し、Subscriber は「誰が送ったか」を知らずにトピックから受け取る。間にトピック(チャネル)が挟まることで、両者は疎結合になる。

この疎結合が実務で効くのは、主に次の3点。

  • 送信側と受信側を独立に増減できる。Subscriber を追加しても Publisher のコードは変わらない
  • 障害の分離。Subscriber が落ちていてもメッセージはトピックに滞留し、復旧後に処理できる(メッセージブローカーが永続化する場合)
  • 非同期化。Publisher は配送完了を待たずに次の処理へ進める

Google Cloud Pub/Sub や Firebase Cloud Messaging、Kafka のトピックモデルは、いずれもこの構造の実装。直接呼び出し(RPC)との使い分けの基準は「送信側が受信側の完了を知る必要があるか」にある。

クライアント / サーバ ── Client / Server

要求する側と、応える側。

Web の最も基本的な対。Client は要求を出し、Server は応答を返す。

注意すべきは、Client / Server がマシンの属性ではなく、通信ごとの役割だということ。上の図の API サーバは、ブラウザに対しては Server だが、DB に問い合わせる瞬間は Client になっている。マイクロサービス構成では、ほぼすべてのサービスが Server であり同時に Client でもある。

だから「このサーバは Client を兼ねる」という言い方は正確には冗長で、正しくは「この通信において、どちらの役割か」を都度特定する。障害調査でタイムアウトの原因を追うとき、この視点がないと「どの通信の、どちら側で詰まっているか」を切り分けられない。

要求 / 応答 ── Request / Response

Client/Server が「誰が」なら、こちらは「何を」やり取りするか。

基本は1リクエストに1レスポンスの1対1対応。ただし、この対応が崩れるパターンを知っておくと設計の幅が広がる。

  • fire-and-forget:レスポンスを待たない。ログ送信やメトリクス送出など、失敗を許容できる処理向き
  • ストリーミング:1リクエストに複数レスポンス。gRPC の server streaming、LLM のトークン逐次返却が典型
  • Server Push:リクエストなしにサーバから届く。SSE や WebSocket の push

崩すかどうかの判断基準は「Client が結果を待つ必要があるか」「結果が一度に確定するか、逐次生成されるか」の2軸。たとえば LLM の応答は逐次生成されるからストリーミングが合理的で、決済の確定は一度に確定するから素朴な 1対1 でいい。

同期 / 非同期 ── Sync / Async

待つか、待たないか。

Sync は結果が返るまでその場で止まる。Async は「あとで結果を受け取る」約束(Dart の Future、JavaScript の Promise)だけを先に受け取り、先へ進む。Go は goroutine とチャネルでこの対を表現していて、言語ごとに設計思想の違いが出る部分でもある。

よくある誤解は「Async にすれば速くなる」というもの。Async が短縮するのは待ち時間の使い方であって、処理そのものの所要時間ではない。I/O 待ち(ネットワーク、ディスク)が支配的な処理なら、待っている間に別の仕事ができるので全体のスループットは上がる。逆に CPU バウンドな処理を async にしても速くならない。ここを混同すると、効果のない async がコード全体に伝播して読みづらくなるだけの結果になる。

押し付け / 取りに行く ── Push / Poll

情報を送りつけるか、取りに行くか。

Push は変化があった瞬間にサーバから送る。WebSocket やモバイルのプッシュ通知が典型。Poll は Client が定期的に問い合わせる。cron で叩く定期バッチや、単純な setInterval での取得がこれにあたる。

トレードオフは明確で、次の3点で比較できる。

  • 遅延:Push は即時。Poll はポーリング間隔ぶん最大で遅れる
  • 実装コスト:Push は常時接続の管理・再接続・スケールが重い。Poll はただの HTTP リクエストで済む
  • 無駄なトラフィック:Poll は「更新なし」の問い合わせを大量に発生させる。Push は変化時のみ

判断の起点は「許容できる遅延はどれくらいか」。数分の遅れが許されるダッシュボードなら Poll で十分。チャットの新着表示のように秒単位が要るなら Push を選ぶ。中間解として、Poll の接続を保留するロングポーリングもある。

確定 / 巻き戻し ── Commit / Rollback

確定するか、なかったことにするか。

トランザクションの対。一連の操作を「全部成功(Commit)」か「全部なし(Rollback)」のどちらかに倒す。この性質が原子性(atomicity)で、ACID の A にあたる。

この対が保証するのは「中途半端な状態を外に見せない」こと。典型例が送金処理。「A口座からの引き落とし」と「B口座への入金」は2つの UPDATE だが、片方だけ成功した状態は業務として存在してはいけない。だから2つを1トランザクションに束ね、途中で失敗したら Rollback で引き落とし前に戻す。

実務で意識すべきは、トランザクションの範囲設計。広く取りすぎるとロック競合でスループットが落ち、狭く取りすぎると不整合が漏れる。「どこからどこまでを不可分にするか」の線引きが、この対を使う上での本題になる。

対比で理解するペア ── 似ているから、混同される

次のグループは毛色が違う。セットで動くのではなく、概念が近いせいで取り違えられるペア。片方を理解するには、もう片方との差分を押さえるしかない。

認証 / 認可 ── Authentication / Authorization

エンジニアが最も混同する対の代表格。

Authentication(認証)は「あなたは誰か」を確かめる。ID とパスワード、OAuth、パスキーなど手段は問わず、本人性の確認がこれ。Authorization(認可)は「あなたは何をしてよいか」を決める。ログインは前者、管理者だけが削除ボタンを押せるのは後者。

混乱の元は、どちらも略すと Auth になること。だから業界では AuthN(認証)と AuthZ(認可)と書き分ける。

差分は HTTP ステータスコードにも現れている。401 Unauthorized は認証の失敗(誰だか分からない)、403 Forbidden は認可の失敗(誰かは分かるが権限がない)。名前と実態がねじれていて紛らわしいが、この対応を覚えておくと API のエラー設計で迷わない。

順序も固定されている。認証なしの認可はありえない。誰だか分からない相手に権限は割り当てられないから、必ず Authentication が先、Authorization が後。

並行 / 並列 ── Concurrency / Parallelism

日本語だと一文字違いで、なお混同しやすい。

Concurrency は「複数のことを同時に扱う構造」。Parallelism は「複数のことを同時に走らせる実行」。前者はプログラムの設計の話、後者はハードウェアの話で、レイヤーが違う。

Rob Pike の整理が分かりやすい。Concurrency は同時に多くを扱うこと(dealing with)、Parallelism は同時に多くをこなすこと(doing)。この区別から次が導ける。

  • シングルコアでも Concurrency は成立する。タスクを細かく切り替えれば「同時に扱っている」ことになる
  • Parallelism は物理的に複数の実行ユニット(コア)がないと成立しない
  • Concurrency な設計は Parallelism の前提になるが、保証はしない

Go を書くなら避けて通れない対。go キーワードが与えるのは Concurrency(goroutine という「同時に扱う単位」)であって、それが実際に並列実行されるかは GOMAXPROCS とコア数、スケジューラが決める。「goroutine を増やしたのに速くならない」と悩んだら、まずこの区別に立ち返るといい。

コンパイル時 / 実行時 ── Compile-time / Runtime

エラーがいつ出るかの境界。

型エラーや構文エラーは Compile-time に出る。null 参照や配列の境界外アクセスは Runtime に出る。両者の決定的な違いは検出の確実性で、Compile-time エラーはビルドすれば必ず見つかるのに対し、Runtime エラーは該当するコードパスをその入力で通らない限り発覚しない。テストで拾えなければ本番で出る。

だから「エラーは早く出るほど安い」。修正コストは、コンパイル時 < テスト時 < 本番障害の順で跳ね上がる。Compile-time に倒せるものを Runtime に残さない、というのが型で縛る思想の核心。

TypeScript を書くときは特にこの境界を意識する必要がある。TypeScript の型は Compile-time にしか存在せず、トランスパイル後の JavaScript には残らない。つまり API レスポンスのような外部入力に対しては、型注釈だけでは何も守られない。Runtime のバリデーション(zod 等)を別途置くか、as で握り潰した型が実行時に不整合を起こすかの二択になる。境界(外部入力の入口)でバリデーションし、内側は型で守る、という役割分担が定石。

文 / 式 ── Statement / Expression

値を返さないか、返すか。

Statement は実行されるが、それ自体は値を持たない。Expression は評価されて値になる。判定基準はシンプルで、「変数に代入できるか」「関数の引数に渡せるか」を考えればいい。

if が文か式かは言語で分かれ、そこに言語の設計思想が出る。JavaScript の if は文なので const x = if (cond) {...} とは書けず、式版として三項演算子が別に用意されている。一方 Rust の if は式で、let x = if cond { 1 } else { 2 }; と書ける。Kotlin や Ruby もこちら側。

「すべてが式」に寄せた言語ほど、コードは値の変換の連なりとして読めるようになる。中間変数への再代入が減り、let の右辺に処理が収まる。関数型言語が Expression 寄りなのは、プログラムを「値から値への写像」と捉える思想の帰結で、偶然ではない。

許可リスト / 拒否リスト ── Allowlist / Denylist

デフォルトをどちらに倒すか。

Allowlist は「これだけ通す、あとは全部拒否」。Denylist は「これだけ拒否、あとは全部通す」。

セキュリティの定石は Allowlist、つまりデフォルト拒否(default deny)。理由は、想定外への挙動が逆だから。Denylist は「攻撃パターンを列挙する」方式なので、列挙漏れ=素通しになる。新種の攻撃、エンコーディングの変種、思いつかなかった入力は、すべて「リストにない」ので通ってしまう。Allowlist なら、想定外は「リストにない」ので落ちる。失敗したときに安全側に倒れる(fail-safe)のは Allowlist の方だ。

Denylist が選ばれるのは、正当な入力の全列挙が現実的でない場合。たとえば公開 Web サービスの IP 制限を Allowlist にはできない。「原則 Allowlist、列挙不能なときだけ Denylist」が判断の順序になる。

補足として、かつては WhiteList / BlackList と呼ばれていたが、色に善悪を結びつける含意を避けるため、Allowlist / Denylist への置き換えが進んだ。Chromium も Android もコードベースの用語を移行済み。機能そのままに名前だけ差し替えた事例として、命名の観点でも参照価値がある。

おわりに

対になる用語を11個、2つの軸で並べた。

整理してみると、同じ「対」でも性質が違うのがわかる。Pub/Sub や Request/Response は、セットで動いて初めて意味をなす対。Authentication/Authorization や Concurrency/Parallelism は、似ているせいで混同され、差を知って初めて使い分けられる対。

この分類は覚え方に直結する。前者は片方の役割からもう片方を導出できるので、構造(図)ごと覚えるのが効率的。後者は差分こそが本体なので、「何が違うか」を一文で言えるようにしておくのが実用的だ(例:AuthN は誰か、AuthZ は何をしてよいか)。

他にも対になる用語はたくさんある。Map/Reduce、Serialize/Deserialize、Mount/Unmount ── 「これも対だ」と思うペアがあれば、ぜひコメントで教えてほしい。

2
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?