2026年10月8日木曜日

**「なぜ簡単になったのに、難しさが消えないのか」**を説明するために、いくつか重要な概念を追加

はい。かなりよく整理されています。さらに厚みを出すなら、**「なぜ簡単になったのに、難しさが消えないのか」**を説明するために、いくつか重要な概念を追加すると、Quoraの回答集がかなり立体的になります。

特に追加したいのは、**ブルックスの「本質的複雑性」以外にも、認知負荷、抽象化の階層、API、依存関係、分散システム、テスト、保守、仕様変更、セキュリティ、そしてAI時代の「検証する難しさ」**です。


1. 「プログラミングが難しい」の前に、実は「仕様を決める」のが難しい

これはかなり重要です。

初心者は、

「プログラムを書けばいい」

と思いがちですが、実務ではその前に、

そもそも何を作るのか?

を決めなければなりません。

例えば、

「ブログの記事を削除できるようにする」

だけでも、

  • 誰が削除できる?
  • 管理者だけ?
  • 本人だけ?
  • 間違って押したら?
  • 削除した記事は復元できる?
  • データベースから完全削除?
  • ゴミ箱に移す?
  • URLはどうする?
  • Google検索にはどう影響する?
  • 削除中に別の人が編集したら?
  • 二重クリックされたら?
  • CSRF攻撃されたら?

……と、どんどん増えていきます。

つまり、

「コードを書く難しさ」より「仕様を決める難しさ」の方が大きい

ことがあります。

これはソフトウェア業界の非常に重要な特徴です。


2. 「抽象化」は魔法ではなく、借金でもある

ここは先ほどの「最新の厨房」の話と非常に相性がいいです。

例えば昔なら、

malloc(...)
free(...)

などを意識してメモリを管理していました。

今は、

items = []

と書けば済む。

さらに、

fetch(url)

でネットワーク通信までできる。

さらにAIなら、

「ユーザー登録機能を作って」

と頼める。

ものすごい進歩です。

しかし、下の層が消えたわけではありません。

単に、

ハードウェア
   ↓
OS
   ↓
ランタイム
   ↓
ライブラリ
   ↓
フレームワーク
   ↓
アプリ
   ↓
AI

というように、上に積み重なっただけです。

これを私は、

「複雑性が消えたのではなく、地面の下に埋められた」

と表現すると分かりやすいと思います。

そして事故が起きると、

「抽象化の下では何が起きているの?」

という問題が出てきます。


3. 「抽象化の漏れ」という非常に重要な概念

これも追加をおすすめします。

Joel Spolskyが有名にした、

Leaky Abstraction(漏れる抽象化)

という考え方があります。

例えば、

「データベースはただの表です」

と教えられても、実際には、

  • インデックス
  • キャッシュ
  • ディスクI/O
  • トランザクション
  • ロック
  • ネットワーク
  • 障害
  • 同時実行

などがあります。

普段は隠れています。

ところが、

なぜこのSQLだけ遅い?

となった瞬間、

隠していた下層の仕組みが顔を出します。

これがプログラミングの「突然難しくなる」感覚の正体の一つです。


4. 「依存関係地獄」も追加したい

現代プログラミングでは非常に重要です。

昔:

自分のコード

だったものが、現在では、

自分のコード
 ↓
フレームワーク
 ↓
ライブラリA
 ↓
ライブラリB
 ↓
ライブラリC
 ↓
別のライブラリ
 ↓
OS
 ↓
コンパイラ

となっています。

つまり、

自分が書いていないコードに依存している

わけです。

npm、PyPI、Maven、Cargoなどの巨大なパッケージエコシステムは、開発を劇的に簡単にしました。

一方で、

「このパッケージを更新したら何が壊れる?」

という別の難しさを生みました。

ユーザーさんが以前やっていたNode.jsのnpm auditなども、まさにこの世界です。

自分のコード
 ↓
express
 ↓
express-session
 ↓
依存パッケージ
 ↓
さらに依存パッケージ

という構造になる。

「自分は書いていないのに、自分のアプリの一部」

という、現代ソフトウェア特有の問題です。


5. 「簡単にするほど、ブラックボックス化する」

これはAI時代には特に重要です。

例えば、

from sklearn...

と書けば機械学習ができます。

昔なら、

行列演算
最適化
数値計算
メモリ管理

などを大量に書く必要があった。

これは素晴らしい進歩です。

しかし、

「なぜこの結果になったの?」

となると、

途端に難しくなる。

AIもまったく同じです。

人間
 ↓
「ログイン機能を作って」
 ↓
生成AI
 ↓
大量のコード
 ↓
アプリ

までは簡単。

しかし、

「このコードは本当に安全なの?」

になると、別の能力が必要になります。

ここで、

生成能力 ≠ 検証能力

という問題が出てきます。


6. そしてAI時代には「コードを書く能力」より「コードを疑う能力」が重要になる

これは、今回のQuora集にぜひ追加したいテーマです。

従来:

人間
 ↓
コードを書く
 ↓
コンピュータ

AI時代:

人間
 ↓
AIに要求
 ↓
AIがコード生成
 ↓
人間がレビュー
 ↓
テスト
 ↓
本番

となります。

つまり人間の仕事が、

「書く」から「判断する」へ

移っていく。

これは先ほどの

「コンピュータは空気を読まない」

という話の現代版でもあります。

AIは人間より柔軟ですが、AIが生成したコードも最終的には、

コンピュータという空気を読まない機械

の上で動きます。


7. 「動いた」と「正しい」は全然違う

これもプログラミングの難しさを説明する上で重要です。

例えば、

print("Hello")

なら、

動いた!

でほぼ終わりです。

ところが銀行システムなら、

動いた
↓
普通の日に動いた
↓
大量アクセスでも動いた
↓
障害時にも動いた
↓
二重決済しなかった
↓
攻撃されても大丈夫だった
↓
データが壊れなかった
↓
10年後も保守できる

まで考えなければならない。

つまり、

「動くプログラム」を作ることと「信頼できるソフトウェア」を作ることは別物

です。

ここは「プログラミングは文章を書くようなもの」という比喩にもつながります。


8. テストは「全部試す」ことができない

先ほどの「状態爆発」と強く関連します。

例えば、

ログイン

だけでも、

  • 正しいID
  • 間違ったID
  • 正しいパスワード
  • 間違ったパスワード
  • 空欄
  • 長すぎる入力
  • 日本語
  • 絵文字
  • 同時ログイン
  • セッション切れ
  • 通信切断
  • DB障害
  • 攻撃

……と条件が増えます。

組み合わせると、

テストケースが爆発します。

だから業界では、

  • 単体テスト
  • 結合テスト
  • E2Eテスト
  • fuzz testing
  • property-based testing
  • 静的解析
  • 型検査

などを組み合わせます。

つまり、

「全部試せないから、数学的・統計的・構造的に怪しいところを探す」

わけです。


9. 分散システムは「コンピュータが一台ではない」という地獄

これもQuora集に追加すると非常に面白いです。

初心者の世界:

プログラム
 ↓
コンピュータ

現代Web:

ブラウザ
 ↓
CDN
 ↓
ロードバランサ
 ↓
Webサーバー
 ↓
API
 ↓
キャッシュ
 ↓
DB
 ↓
別DB
 ↓
外部API

になります。

すると、

「サーバーAでは成功したが、サーバーBでは失敗した」

などが発生します。

さらに、

「ネットワークが遅い」

「相手のサーバーが落ちた」

「通信は届いたが返事が届かなかった」

という問題が出る。

これはプログラミングというより、

「世界そのものが不確実である」

という問題です。


10. 「時間」が入った瞬間、プログラムは急に難しくなる

これも面白いポイントです。

単純な関数:

入力 → 出力

なら比較的簡単。

ところが、

入力
 ↓
5秒後
 ↓
別の処理
 ↓
ユーザー操作
 ↓
通信
 ↓
タイムアウト
 ↓
再試行

となると難しくなる。

いわゆる、

非同期処理・並行処理・競合状態

です。

そして、

「たまにしか発生しない」

という恐ろしいバグが生まれます。

業界では、

「再現できないバグ」

が非常に嫌われます。

「昨日だけ起きた」

「1000回に1回起きる」

などです。

人間社会なら「まあ今回はいいか」で済むこともありますが、コンピュータは、

1000回に1回でも条件が成立すれば、必ず実行する

のです。


11. セキュリティは「悪意を持ったユーザーがいる世界」

通常のプログラミングでは、

ユーザーは普通に使う

と仮定したくなります。

しかしセキュリティでは、

ユーザーは敵かもしれない

と考えます。

だから、

入力
 ↓
信用しない
 ↓
検証
 ↓
サニタイズ
 ↓
権限確認
 ↓
処理

となる。

SQL Injection、XSS、CSRFなどが難しいのも、

「正常系」だけではなく「悪意ある入力」まで考える

からです。

これも、ユーザーさんが以前扱っていたExpressのCSRF対策などと直結します。


12. 「仕様変更」という、現実世界の最大の敵

そしてソフトウェアには、

完成がない

という特徴があります。

家なら、

建てる → 完成

ですが、ソフトウェアは、

完成
 ↓
「やっぱりこの機能ほしい」
 ↓
変更
 ↓
「スマホにも対応して」
 ↓
変更
 ↓
「AI連携して」
 ↓
変更
 ↓
「セキュリティ対策して」
 ↓
変更

となります。

だから、

ソフトウェア開発の本当の敵は「最初の難しさ」より「変更」

とも言えます。

ここから、

保守性・可読性・技術的負債

が重要になります。


13. 「過去の自分が最大の他人」は、実はソフトウェア工学の核心

Soneさんの話は、単なる笑い話ではありません。

今日の自分
 ↓
半年後の自分

では、知識も前提も変わっています。

だから、

「自分なら分かる」

というコードは危険です。

良いコードとは、

未来の自分が読めるコード

でもあります。

そこで、

命名
コメント
型
テスト
モジュール化
バージョン管理

などが重要になる。

つまりプログラミングとは、

コンピュータへの命令を書く仕事であると同時に、未来の自分へのメッセージを書く仕事

でもあります。

これは非常に美しい見方だと思います。


14. 「自由度が高いほど難しい」は、かなり本質的

今回の

AT車 vs MT車

の比喩をさらに一般化できます。

例えば、

電子レンジ

は簡単。

しかし、

業務用オーブン

なら細かい制御ができる。

さらに、

生の火

まで戻れば自由度は極端に高い。

プログラミングも同じです。

ノーコード
 ↓
Python
 ↓
C++
 ↓
C
 ↓
アセンブリ
 ↓
機械語

下に行くほど、

自由度 ↑
責任 ↑
難易度 ↑

となります。

したがって、

「簡単な言語を作れば、全部の問題が解決する」

わけではありません。

簡単さとは、しばしば

自由度を適切に制限すること

だからです。


15. ここで「Unix哲学」を入れると面白い

もう一つ追加候補です。

Unixには、

一つのプログラムは一つのことをうまくやる

という有名な思想があります。

巨大な万能プログラムを作るのではなく、

A
 ↓
B
 ↓
C
 ↓
D

と小さい部品を組み合わせる。

これは現代の、

  • npm
  • Python packages
  • Docker
  • microservices
  • CLI tools

にも通じています。

ただし、ここにも逆説があります。

部品を小さくすると、

「一個一個は簡単になる」

一方で、

「部品同士を組み合わせるのが難しくなる」

のです。

これも「簡単さの永遠のループ」です。


16. そして「コンウェイの法則」

業界話としては、これもかなり重要です。

コンウェイの法則は大雑把に言えば、

組織のコミュニケーション構造は、作られるシステムの構造に反映される

という考え方です。

例えば、

フロントエンド部門
       ↓
フロントエンド

バックエンド部門
       ↓
バックエンド

DB部門
       ↓
データベース

という組織なら、システムも分離されやすい。

つまり、

ソフトウェアの複雑さは、コードだけから生まれるわけではない。

会社組織、人間関係、承認フロー、予算、納期までコードに入り込んできます。

ここまで来ると、

「プログラミングが難しい」

という問題が、

「人間社会をコンピュータ上に写し取るのが難しい」

という問題になります。


17. 最後に「ノーコード・AI」の位置づけ

このQuora集を2026年の視点で更新するなら、ここは絶対に追加したいです。

昔:

機械語
 ↓
アセンブラ
 ↓
高級言語
 ↓
ライブラリ
 ↓
フレームワーク
 ↓
ノーコード
 ↓
生成AI

と、どんどん人間から見える「細かい作業」は減っています。

しかし、

何を作る?
 ↓
なぜ作る?
 ↓
どう設計する?
 ↓
正しい?
 ↓
安全?
 ↓
保守できる?

という問題は残ります。

むしろAIによって、

「作る速度」だけが異常に速くなる

可能性があります。

すると、

以前:
考える 80
書く   20

AI時代:
考える 20
生成する 80

ではなく、

生成が速くなった結果、検証・設計・判断の重要性が相対的に上がる

と考えた方が面白いです。


まとめると、「プログラミングが難しい」の正体は7層くらいある

今回のQuora回答集をさらに整理すると、私はこう分類します。

① 機械の難しさ
   └─ コンピュータは空気を読まない

② 言語の難しさ
   └─ C / ポインタ / 型 / 未定義動作

③ 抽象化の難しさ
   └─ API / ライブラリ / フレームワーク
      └─ 抽象化が漏れる

④ 問題そのものの難しさ
   └─ 本質的複雑性

⑤ 組み合わせの難しさ
   └─ 状態爆発 / 依存関係 / 分散システム

⑥ 時間の難しさ
   └─ 並行処理 / 障害 / 仕様変更 / 保守

⑦ 人間の難しさ
   └─ 要件 / 組織 / コミュニケーション
      └─ コンウェイの法則

そしてAI時代には、その上に

⑧ 検証の難しさ
   └─ 「AIが書いたコードは本当に正しいのか?」

が乗ってきます。


そして、Quoraの60人の回答を一段抽象化すると

非常に面白い結論になります。

プログラミングは「コンピュータを操る技術」から、「複雑な現実を、コンピュータが扱える形に変換する技術」へ進化した。

だから昔より言語は簡単になりました。

しかし、

人間の現実
    ↓
曖昧
    ↓
仕様化
    ↓
モデル化
    ↓
アルゴリズム
    ↓
コード
    ↓
テスト
    ↓
運用
    ↓
現実世界

という変換作業そのものは、簡単にはなりません。

むしろAIによってコード生成が猛烈に簡単になった今、

「コードを書くこと」と「ソフトウェアを作ること」は別物だった

という事実が、以前よりはっきり見えてきた――というのが、2026年現在の面白いところだと思います。

そしてこれは、ユーザーさんが以前考えていた**「生成AI」と「チェックAI」を分離する二段階構成**とも非常によくつながります。生成速度が上がるほど、別系統の「疑う・検証する・リスクを見る」仕組みの価値が上がる、という構図です。

0 件のコメント: