📌 この記事は Zenn に投稿した内容のアーカイブです。

プログラマーを数年やっていると、おそらく全員が一度は同じことを考える。

「これ、他のプロジェクトでも使える形にしたい」

最初はただ動けばよかったコードが、だんだん気持ち悪く見えてくる。
コピペも増える。責務も混ざる。依存も汚くなる。

すると自然に、

  • 共通化したい
  • 抽象化したい
  • 再利用可能にしたい

という欲求が出てくる。

これは悪いことではない。むしろ健全だと思う。
“設計”を意識し始めた証拠だから。

ただ、この感覚はかなり危ない。

一歩間違えると、
簡単に「過剰設計」に転がり始める。

「将来使うかもしれない」

この一言が、
過剰設計の始まりになることはかなり多い。

今回は、自分がゲーム開発をやる中で感じた、

  • なぜ人は汎用化したくなるのか
  • なぜそれが失敗しやすいのか
  • 実際どう考えるとちょうどいいのか

について書いてみる。


汎用化したくなるのは、実はかなり自然なこと

例えば、最初の頃のコードってかなり局所的になる。

if (isBoss)
{
    hpBar.color = Color.red;
}

みたいな、「今必要だから書いたコード」が大量にある。

でも経験を積むと、
こういうコードを見るだけで“変更コスト”を想像するようになる。

「これ別のボス出たらどうするんだろう」
「色変えるたびに if 増えるの?」
「そもそも UI が敵情報知ってるのおかしくない?」

みたいなことを考え始める。

つまり汎用化欲求の正体って、単なる意識高い設計趣味ではなく、

“変更に弱いコードへの違和感”

なんだと思う。

だからある程度コードを書いた人ほど、自然と抽象化に向かう。


実際、汎用化にはかなり強いメリットがある

これは間違いない。

1. 「依存」に敏感になる

再利用を意識すると、まずベタ結合が気になり始める。

  • 直接参照
  • Singleton ベタ依存
  • MonoBehaviour 神クラス
  • Inspector 配線地獄

みたいなものを避けたくなる。

結果として、

  • 責務分離
  • Interface 化
  • データ駆動
  • 疎結合

みたいな方向へ進む。

こういう意識がないと、
人はかなり簡単に「今だけ動けばいいコード」を書く。

実際、「他でも使えるようにしよう」という意識がなければ、人はかなり簡単に“その場しのぎ”を書く。


2. 開発速度がある地点から急に変わる

ある程度経験を積んだ人の開発速度が異常に速く見えることがある。

あれ、単純にタイピングが速いわけじゃない。

大抵の場合、

「すでに持ってる」

から速い。

例えば、

  • ログ基盤
  • Pool
  • 非同期 Utility
  • UI 拡張
  • Editor 拡張
  • アニメーション補助
  • アセットロード周り

みたいなものを、自分用に持っている。

つまり毎回ゼロから作っていない。

ゲーム開発って結局、「毎回違うゲームを作ってるようで、毎回似た問題と戦ってる」ので、この差はかなり大きい。


でも、ここから簡単に壊れ始める

問題はここ。

汎用化思考って、あるラインを超えると急激にコストが増える。

過剰設計の厄介なところは、
作ってる本人がかなり気持ちよくなれること。

綺麗に抽象化できると、
「理解した感」が強く出る。

設計してる時って楽しい。

綺麗に抽象化できると「理解した感」がある。

でも実際の開発で価値があるのは、

“綺麗な構造”

ではなく、

“予定通りに完成すること”

だったりする。

ここを見失うと危ない。


過剰設計が始まる瞬間

自分の経験上、一番危険なのは、

「将来使うかもしれない」

が設計理由になった瞬間。

例えば本来必要なのが、

「画像を横にスライドする UI」

だけだったとする。

でも設計好きな人間はここで止まらない。

  • 無限ループ対応
  • 汎用アニメーション
  • 任意方向
  • 動的追加削除
  • 仮想化
  • 非同期ロード
  • カスタムイベント
  • 設定データ分離

みたいな方向へ行き始める。

で、数日後に完成したものを見ると、

今必要な機能、2割くらいしか使ってない

みたいなことが普通に起きる。

これ、本当に危険なのは「頑張ってる感」があること。

本人はサボってるわけじゃない。むしろ真面目。
でも成果物として見ると、必要以上に重い。


しかも「汎用化したコード」は意外と弱い

ここもかなり重要。

多くの人が最初誤解するけど、

汎用コード = 強いコード

ではない。

むしろ逆で、

汎用コードほど、前提条件に弱い

ことが多い。

例えば、自作の UI 基盤を作ったとする。

でも次プロジェクトで、

  • UI 構造が違う
  • 運用フローが違う
  • デザイナーの触り方が違う
  • 演出思想が違う

となった瞬間、急に噛み合わなくなる。

するとどうなるか。

頑張って「汎用化」したはずなのに、

結局プロジェクト専用改造が大量発生する

そして最終的に、

「これ最初から作った方が早くない?」

になる。

これはかなりある。


個人的に一番重要だと思ってること

ここ数年でかなり考え方が変わった。

昔は「最初から綺麗に設計する」が正義だと思ってた。

でも今はむしろ逆で、

“最初は多少汚くていい”

と思ってる。

もちろん無秩序でいいわけじゃない。

でも、最初から完成形を想像しすぎない方がいい。

なぜなら、ゲーム開発って想像以上に仕様が変わるから。

最初に考えていた「綺麗な構造」は、大抵途中で崩れる。

重要なのは、

「完璧な抽象化」ではなく

「壊しやすさ」だと思っている。

壊しやすさ

なんだと思う。


「3回目で抽象化する」はかなり合理的

有名な Rule of Three は、本当に実践的。
https://www.ikemo3.com/dic/rule-of-three/#3度目の法則とは

1回目は普通に作る。
2回目で違和感を覚える。
3回目で初めて抽象化する。

この順番を飛ばすと、

かなりの確率で事故る。

これ、単なる経験則じゃなくてかなり理にかなってる。

1回目では、「何が変化するか」が分からない。

でも3回同じ問題に遭遇すると、

  • 本当に共通な部分
  • 毎回違う部分
  • 将来変わりやすい部分

が見えてくる。

つまりその時点で初めて、“適切な抽象化”が可能になる。

逆に、最初から作る汎用設計って、

まだ存在していない問題に、
先回りして答えを作っている

ことが多い。

だから外れやすい。


結局、「拡張しやすさ」が一番大事

最近は、

“全部入り”

より、

“後から足しやすい”

をかなり重視してる。

つまり、

  • 責務が分かれている
  • 依存方向が綺麗
  • 置き換えやすい
  • 変更範囲が閉じている

みたいな状態。

最初から全機能を想定するより、

必要になった時に安全に伸ばせる

方が、結果的に長生きする。

特にゲーム開発は「完成前に仕様が変わる」のが普通なので、この思想の方がかなり現実的だと思う。


おわりに

プログラマーって、経験を積むほど「綺麗にしたい欲」が強くなる。

それ自体は悪くない。
むしろ成長してる証拠だと思う。

でも開発では、

  • 納期
  • 仕様変更
  • チーム事情
  • 運用コスト

みたいな、“現実”も常に存在する。

だから結局大事なのは、

「未来のための設計」と
「今作るべきもの」

のバランスなんだと思う。

最近は自分も、

「未来を作り込みすぎない」

ことをかなり意識している。

必要になったら伸ばす。

でも、
必要になる前には作り込まない。

最近は、それくらいがちょうどいいと思っている。

多分それくらいが、実際の開発ではちょうどいい。