作業はMac 90%、設計はMac/Windows 50:50」— 初心者向け開発の基本:覚書

AI活用メモ
  • Macで開発しているが、最終的にWindows 11でも動かす必要がある
  • 「開発中はMacで、最後にWindows対応すればいい」と考えていたが、それで本当に大丈夫か不安
  • Codex/Claudeなどのコーディングエージェントと一緒に開発している

こういう人向けに、「作業時間の9割はMacで開発してよいが、設計だけは最初からWindowsを意識しておく」という考え方と、その具体的なやり方を解説します。

1. なぜ「作業配分」と「設計思想」を分けて考えるのか

クロスプラットフォーム開発でよくある誤解は、「Windows対応は最後にまとめてやればいい」という考え方です。これは半分正しく、半分危険です。

  • 作業量としては Macで動作確認しながら開発を進めるのが効率的(正しい)
  • 設計としては 「後からWindows対応すればいい」という前提でコードを書くと、Core(中核ロジック)の中にMac前提の処理が染み込んでしまう(危険)

一度Core全体にMac前提のロジックが染み込むと、後からの分離は「全部やり直し」に近い作業量になります。これを避けるために、作業配分は90:10でもよいが、設計上は常に50:50を意識する、という二段構えのルールが有効です。


2. 常設ルールとして最初に決めておくこと

プロジェクトの最初に、次のようなルールをドキュメント(README、CONTRIBUTING、あるいはAIエージェントへのシステムプロンプト)に明記しておきます。

開発・通常検証はmacOSで継続する。ただしWindows 11 x64対応を常に維持し、OS依存実装をCoreへ入れない。Windows固有部分はApp/Rendering層へ隔離する。

このルールには2つの要素があります。

ルールA:CoreにはOS依存コードを入れない

Core(ゲームロジック、データ処理、ビジネスルールなど、アプリの「頭脳」部分)は、macOSでもWindowsでも同じコードがそのまま動くように書きます。ファイルパスの扱い、フォントレンダリング、GPU API呼び出しなど、OSごとに異なる処理はCoreに置きません。

ルールB:OS固有処理はApp/Rendering層に隔離する

画面描画(Metal/DirectX/Vulkanなど)、ファイルダイアログ、ウィンドウ管理といったOS依存の処理は、Coreとは別の層(App層・Rendering層)にまとめます。Coreはこれらの層に対して「描いてほしい内容」や「保存してほしいデータ」を渡すだけで、実際にOSのAPIを呼ぶのはApp/Rendering層の役割です。

この構造は「ポート&アダプター(Ports and Adapters)」や「依存性逆転の原則」と呼ばれる、ソフトウェア設計の定石です。図で表すとこうなります。

┌─────────────────────────────┐
│           Core              │  ← OS依存ゼロ。Mac/Windows共通コード
│  (ゲームロジック等)         │
└──────────┬──────────────────┘
           │ インターフェース越しにやり取り
┌──────────┴──────────────────┐
│      App / Rendering層       │  ← ここにOS依存コードを集約
│  macOS実装  │  Windows実装    │
└──────────────────────────────┘

3. なぜ「設計だけ」50:50が必要なのか

「作業は90:10でいいのに、なぜ設計は50:50で考えるのか」という疑問が出ると思います。理由は、Coreの設計ミスは後から発見しづらく、修正コストが跳ね上がるからです。

具体的に、Coreに入り込みやすい「隠れたOS依存」の例を挙げます。

落とし穴Macでの挙動Windowsでの挙動
パス区切り文字/\/も一部使えるが混在は事故の元)
パスの長さ制限ほぼ気にしなくていい既定で260文字の制限(対策が必要な場合あり)
ファイル名の大小文字区別しない場合が多い区別しない場合が多いが挙動が微妙に違う
改行コードLFCRLFが混在しやすい
文字コードの既定値UTF-8前提が多いShift-JIS前提のツールが残っている場合あり
タイマー精度・スレッド挙動微妙に異なる微妙に異なる
日本語入力(IME)macOS方式Windows方式で挙動が異なる

これらは「明示的にOSのAPIを呼んでいる」わけではないので、レビューで見落とされがちです。だからこそ、Coreを書く瞬間から「これはWindowsでも同じ結果になるか?」と自問する習慣が必要になります。これが「設計は50:50」という意味です。作業時間の配分ではなく、思考の配分の話です。


4. Windows確認のタイミング設計

「最後にまとめて確認する」のではなく、リスクが低いうちに小さく確認するのがコツです。目安として次の3段階がちょうどいいバランスです。

ステップ1:主要マイルストーン通過後に「ビルド確認」

例えば「M7フェーズ終了後」など、大きな機能がひとまとまり終わったタイミングで、一度Windows版をビルドして起動するかどうかだけ確認します。ここではゲームプレイ全体を検証する必要はありません。「コンパイルが通る」「アプリが立ち上がる」の2点が確認できれば十分です。

ステップ2:Rendering層の実装直後に軽く確認

Rendering層(画面描画部分)は、Mac/Windowsの差が最も濃縮される場所です。この部分の実装が一区切りついたら、時間軸のマイルストーンを待たずに一度確認しておくと安全です。

ステップ3:Ver.1完成時に本格検証

全機能が揃った段階で、実際のプレイフローを通した本格的なWindows検証を行います。ここまでに小さな確認を挟んでいれば、この段階で見つかる問題は「細かい調整」程度に収まりやすくなります。

開発開始 ──────────────► M7終了 ──────────► Rendering実装後 ──────────► Ver.1完成
  (Mac中心)              [起動確認]           [軽い動作確認]              [本格検証]

5. ルールを「文章」だけでなく「仕組み」で守る

人間が気をつける、AIエージェントに指示する、だけでは長期的にルールが守られなくなることがあります。特に開発が進み、機能が増えてくるとレビューの目も粗くなります。そこで、次の2つの仕組みを併用すると安心です。

CIで継続的にWindowsビルドをチェックする

手動でのWindows起動確認は上記の3段階でよいですが、「コンパイルが通るか」だけは毎回のコミット/プルリクエストで自動チェックしておきます。GitHub Actionsなどで、画面表示なしの状態(ヘッドレスビルド)だけ確認するのは低コストで実現できます。これにより「気づいたら半年前からWindowsビルドが壊れていた」という事故を防げます。

アーキテクチャレベルでの強制(Lint / 静的チェック)

「Coreディレクトリの中でOS固有のAPIやライブラリをimportしたらエラーにする」という仕組みを、Lintや簡単なスクリプトで用意しておくと、ルールが文章だけで終わらずに機械的に守られます。例えば「Core/配下のファイルからWindows.hMetal関連のimportがあれば警告する」といったチェックです。


6. まとめ:初心者が押さえておくべき3点
  1. 作業配分と設計思想は別物。開発の9割をMacで行うのは合理的だが、Coreを書く時点では常に「Windowsでも同じ結果になるか」を考える。
  2. 層を分ける。OS依存コードはApp/Rendering層に隔離し、Coreはプラットフォーム共通のロジックだけを持つ。
  3. 確認は小さく・早く・複数回。「最後にまとめて」ではなく、「M7終了後の起動確認」「Rendering層実装後の軽い確認」「Ver.1完成時の本格検証」と段階的に行うことで、大きな手戻りを防ぐ。

この3点を最初に決めておくことで、Mac中心の開発スピードを落とさずに、Windows対応で「全部やり直し」になるリスクを大きく減らすことができます。

岡山のホームページ作成