🏯 コードの保存性を高める:流行の技術から『心臓部』を守る設計思想 自作コードの中の干し肉と野菜の分離
はじめに
フロントエンドのビルドツール、パッケージ、フレームワークは驚くほど速く世代交代します。
数年前のベストプラクティスが、数年後には非推奨になり、依存パッケージの更新や脆弱性対応に追われることも珍しくありません。
新しい技術を使うこと自体は悪くありません。
便利なライブラリを使えば、少ないコードで高度な機能を実現できます。
しかし、ここで一つ考えたいことがあります。
自分が書いたコードは、数年後も生き残れるだろうか?
私はこの問題を 「コードの保存性(Longevity)」 として捉えています。
保存性とは、
コードが“同じ環境で永遠に動くこと”ではなく、“環境が変わっても再生できること”
を指します。
そして保存性を高めるために重要なのは、
すべてを自作することではなく、依存の境界を設計すること。
1. 「みんな使っているから永遠に使える」とは限らない
DirectX / XNA の経験から学んだこと
私は以前、DirectXやXNAを使ったゲーム開発をしていました。
当時は巨大なプラットフォームであり、そこに合わせてコードを書けば長期間使えるように思えました。
しかし、プラットフォームは永遠ではありません。
- Managed DirectX → 廃止
- XNA → 廃止
- DirectX → 世代交代
技術が悪かったわけではありません。
当時は非常に便利で、多くのソフトウェアがその技術で作られました。
問題は、
「現在広く使われていること」と「自分のコードが将来も維持できること」は別の問題
という点です。
Three.jsのような巨大OSSでも同じです。
便利で強力ですが、APIや周辺環境の変化を利用者がコントロールすることはできません。
だからこそ、
「このライブラリがなくなっても、自分の重要なコードは残せるか?」
という視点が必要になります。
2. 問題は「依存すること」ではなく「依存の境界が消えること」
外部ライブラリを使うこと自体は悪くありません。
車輪の再発明を避けるためにはむしろ必要です。
問題になるのは、
外部ライブラリの仕様が自分のコードの内部まで浸透してしまうこと。
例えば、数学処理がライブラリ独自のベクトル型に完全依存していると、ライブラリ交換時にアプリケーションの根幹まで修正が必要になります。
つまり、
外部依存が悪いのではなく、依存がコード全体に染み込むことが悪い。
3. 「心臓部」と「表層」を分離する
私はコードを次のように分けて考えるのが好きです。
干し肉(保存食・心臓部)
長期的に変わりにくく、環境が変わっても意味を失いにくい普遍的なアルゴリズム・数理・データ構造。
野菜(生もの・表層)
技術やトレンド、実行環境の変化によって移り変わるため、将来的な交換を前提として設計するアルゴリズム・実装。
干し肉と野菜の違いは、自作か外部製かではありません。
- 「将来も残したいもの」なのか、「将来は交換してよいもの」なのかです。
- 干し肉は保存する。野菜は新鮮なものに交換する。
- その間に境界を設けることで、野菜が腐っても干し肉まで一緒に捨てずに済む。
┌─────────────────────────────────────┐
│ 外部環境(変化する) :野菜 │
│ UI / FW / ライブラリ / API │
└─────────────┬───────────────────────┘
│ 境界(Adapter)
┌─────────────▼──────────────────────┐
│ 内部ロジック(残す) :干し肉 │
│ 数学 / 物理 / アルゴリズム │
│ 独自データ構造 / ドメイン知識 │
└────────────────────────────────────┘
心臓部には、
- ベクトル・行列・四元数演算
- 数値計算
- シミュレーション
- 独自データ構造
- アプリ固有のアルゴリズム
など、長期保存したいコード を置きます。
これが自作コードの中の干し肉 です。干し肉は自分の固有の特性 となります。
表層は外部ライブラリに任せます。
Three.jsを使う場合でも、
「Three.jsで計算する」のではなく、「自分の計算結果をThree.jsに表示させる」
という関係にします。
実例
冷蔵庫概念図
[心臓部、保存食、干し肉] ← 保存する:低メンテナンス性
[境界、変換機、アダプター] ← 交換のための窓口
[表層、生もの、野菜] ← 交換する:高メンテナンス性
🧱 心臓部(保存したい領域)=自分のコントロール下
ここは自分の固有の特性、資産。
数学・物理・アルゴリズム・データ構造など、将来的にも大きく変える必要がなく、長期保存したい部分。
// 心臓部(保存したい領域)
// ここは自分のコントロール下にある純粋ロジック
const pos = physics.update(dt);
🎨 表層(交換可能領域)=Three.js のレンダリングメソッドの塊
Three.js のレンダリングは「生もの」なので、
心臓部からは黒箱に見えるが、作者にとっては「いつでも交換できる部品」 です。
これが自作コードの中の野菜 です。野菜はその時の新鮮な美味しいもの を選びます。
// 表層(交換可能領域)
// Three.js のレンダリングメソッドの塊(黒箱)
// → ここを交換すれば描画ライブラリを丸ごと入れ替えられる
renderer.drawSphere(pos);
そして、この renderer.drawSphere() の中身は Three.js の塊 として閉じ込めます。(概念説明用の簡略例)
// Three.js のレンダリングメソッドの塊(交換可能領域)
const renderer = {
drawSphere(position) {
// Three.js の生もの処理をここに全部閉じ込める
const geometry = new THREE.SphereGeometry(1, 32, 32);
const material = new THREE.MeshStandardMaterial({ color: 0x88ccff });
const mesh = new THREE.Mesh(geometry, material);
mesh.position.set(position.x, position.y, position.z);
scene.add(mesh);
threeRenderer.render(scene, camera);
}
};
🧩 この構造が「保存性」を最大化する理由
✔ 心臓部は Three.js を一切知らない :干し肉
physics.update(dt) は純粋ロジック。
Three.js の型も API も参照しない。
✔ 表層は Three.js の「生もの」を黒箱化 :野菜
renderer.drawSphere() の中に Three.js を閉じ込めることで、
Three.js が腐っても心臓部は無傷。
✔ Three.js を捨てるときは黒箱だけ交換すればよい
例えば Babylon.js に乗り換えるなら:
renderer.drawSphere = function(position) {
// Babylon.js の描画処理に差し替える
};
心臓部は変更範囲を表層側に限定しやすくなる。
4. 「自作すれば安全」ではない
ここで誤解してほしくないのは、
「外部ライブラリは危険だから全部自作しよう」ではない
ということです。
自作コードにもバグはありますし、将来自分が修正できなくなる可能性もあります。
重要なのは、
自分にとって重要な部分を、自分で理解し、修正し、移植できる状態にしておくこと。
自作はそのための手段の一つにすぎません。
5. OSSは「永遠」ではなく「修復可能性」が残る
OSSだから安全というわけではありません。
- 開発停止
- メンテナ不在
- API変更
- 依存ライブラリの消滅
- 脆弱性発見
などは普通に起こります。
しかしOSSには、
必要なら自分で修正・フォーク・移植できる材料が残る
という強みがあります。
つまり、
OSSは永遠ではないが、修復可能性が残る。
6. 要塞化とは「外部依存を閉じ込める」こと
要塞化とは、
外部ライブラリを一切使わないことではなく、交換可能な場所に閉じ込めること。
┌────────────────────┐
│ Three.js:野菜 │
└───────┬────────────┘
│
表示アダプタ
│
┌───────▼───────────────┐
│ 自作計算部 :干し肉 │
└───────────────────────┘
Three.jsをやめる場合も、表示アダプタだけ交換すれば済みます。
7. 保存性とは「環境が変わっても再生できること」
保存性は、
十年前の環境で動き続けることではなく、十年後の環境でも再生できること。
アルゴリズム、数式、データ構造、仕様、テストケースが残っていれば、別言語へ移植できます。
逆に巨大フレームワークの内部仕様に自分のロジックが埋まっていると、そのフレームワークが消えた瞬間に自分のコードまで消えます。採用したライブラリと自分のロジックの分離に手間取り、最悪の場合、一から作り直した方がいい場合になる可能性があります。したがって自分のコントロール内のロジックとコントロール外のロジックをあらかじめ分離しておくと、後々移植難易度が格段に下がります。
8. 「生もの」は交換可能領域に置く
フレームワークやツールは生ものです。
新しくなり、古くなり、流行が変わり、ときには消えます。
だからこそ、
保存食(数学・物理・アルゴリズム)と、生もの(UI・FW・ビルド環境)を同じ冷蔵庫に入れない。
【保存したいもの】
数学 / 物理 / アルゴリズム / データ構造 / 仕様
↓
長期保存領域
【交換してよいもの】
UI / 描画 / ビルド環境 / FW / 外部サービス
↓
交換可能領域
外側が腐っても、内側まで腐る必要はありません。
9. 流行に乗ることと、流行に資産を預けることは別
新しい技術はどんどん使えばいい。
便利なものは便利です。
ただし、
流行っているからといって、コードの中心までその技術に合わせる必要はない。
流行の技術を使うことと、
流行の寿命に自分の資産を預けることは別です。
まとめ
- 自分のコードの中でどの部分が干し肉(保存食) でどの部分が野菜(生もの) なのかはっきり見分ける。
- 干し肉は、外部依存を減らすだけでなく、外部依存があっても交換可能な境界の内側に閉じ込める。必要に応じて、ソースコードを確認・修正・移植できるOSSを選択する。
- 干し肉が自分の固有の特性・資産になります。
- 野菜は感謝して美味しく頂く。場合によっては新鮮なもっと美味しいものと取り換える。
- 干し肉、野菜、の切り分けは長期的に、移植の難易度が下がる可能性があります。
- まずは自分のコードの中で「干し肉」と「野菜」を仕分けするところから始めると、将来の自分が助かるかと思います。
作者
GitHub: https://github.com/NAS6mixfoolv
X(旧Twitter): https://x.com/NAS6_oxo
作者HP: https://nas6.net
気に入っていただけたら GitHub に ⭐ をいただけると嬉しいです!