このサイトは、只今WEB業界で活躍中のデザイナー、プログラマーの方々の情報を集めたweb統合情報サイトです。

Archives Details

効率の良い AI駆動開発について考える

AI・Bot・algorithm

2025.11.09

どもです。

最近AIに頼りすぎて、思考能力が低下しているのではないかと悩んでいる今日このごろなのですが、皆さん如何お過ごしでしょうか。

とはいえ、AI駆動開発が当たり前となっている昨今切っても切れない存在となっておりますね。

今日は、既存プロダクトへの導入や、AI開発の進め方や自分自身がソースについて理解するためのAI活用などをと。

 

既存プロダクトへの導入

AI駆動開発というと何かと「0 → 1」の例でバイブコーディングの方法だったりが多いのですが、既存プロダクトへの導入や「99 → 100」へのブラッシュアップの方法など自分ながらの手順を紹介できればと思っております。

まず、既存プロダクトに導入するのですが、専ら今はAIエージェント戦国時代。

Claude codeが良いだの、cusorが良いだの、Github copilotが良いだの、devinが良いだのと、AIエージェントさんも天下を取ろうと活動が活発な状況で、どれが最適で優秀なのかは日々日々変化する状況です。

そんな状況の中で「Github copilotの最適なセッティング」など個別エージェントのconfig設定なんてしていると間に合いません。色んなAIエージェントを使うことになった場合 AIエージェント用のドキュメントも乱立してしまいます。

そのために、AIエージェント共通のドキュメントを用意するのですが、

AI用のディレクトリがあるだけでもAIコーディングエージェントの精度が飛躍的に向上するようです。

また、同じスレッドで長いやり取りを行っているとトークンの上限に達してしまい、新しくスレッドを作成してやり取りを行うことになるのですが、その際メモリも解放され最初からやり取りしないといけなくなったりする羽目にならないように、タスク進捗などもファイルに落として置くことが良いでしょう。

中身は

  • 要件定義/仕様書
  • プロジェクト構造/データ構造
  • 開発進捗用タスク
  • 技術スタック
  • 最新のドキュメント情報 etc…

と言った感じで、コンテキストエンジニアリングにおける「Write(記述/外部メモの利用)」に相当するものらしく、Spec駆動開発でも採用されているみたいです。

こういう形で、AI リーダブルなドキュメントを置くことによって、バイブコーディングの精度も向上が見込めるようです。

最近は、最低限こちらのドキュメントを作成するようにしております。

ai_docs
├── architecture.md
├── data-struture.md
├── directory-struture.md
├── implementation-tasks.md
├── requirement.md
└── tech-stack.md

docsの名前が良いというのも見かけるのですが、Github pagesのデフォルトがdocsディレクトリだったりして使用済みの場合も多々ありますので、当方はai_docsと命名してファイルを作成しております。

作成の際も、AIエージェントに任せる形です。「ソースを解析して上記の形でファイルを作成して」とお願いした結果。

https://github.com/retrodig/damdara/tree/main/ai_docs

こちらのレポジトリ見覚えある方もいらっしゃるのではないでしょうか。

そう。以前 Rustでつくる ふっかつのじゅもん の記事で作成したレポジトリで、途中で飽きてしまって(いけないいけない)しばらく放置していたのですが、久々手を付けようと思ったのですが、進捗がどこまでだったのか(分かってはいましたが)自分自身のためにも一度まとめたいなとAIエージェント用にドキュメントを生成しました。

この次のステップとして「Webでも扱える様に、WASM化」する予定だったのですが、これもどこまで行っていたかうる覚えだったので、Claude codeの方に「まずは、implementation-tasksの方に書き出してみて」とお願いしました。

そう、前述でもあったようにAIエージェントに作業させる場合、トークン上限でやり取りが最初からってことも多々ありますので、作業させる前は最低限「task」のドキュメントを生成して進捗も管理するのを心掛けていたりします。

今回「WASM化」を進めるに当たって作成してもらったドキュメントが良い感じにまとまっていたので順番に見ていきたいと思います。

生成(追加)されたタスクドキュメント

https://github.com/retrodig/damdara/blob/main/ai_docs/implementation-tasks.md#architecture-changes

 

Architecture Changes項目以下が該当する箇所になるのですが、まず 1. WASM Module Structure を見てみると、

// src/wasm.rs (NEW)と

との様に新規でファイル作成する流れになっています。 アトリビュートでwasm_bindgenを指定しWASMで使用できるようにしております。

続けて 2. Web-Specific I/O Implementations では、WebInput (NEW): を新規作成する流れですね。

// src/input/web_input.rs (NEW)
pub struct WebInput {
    pending_actions: VecDeque<PlayerAction>,
}

impl WebInput {
    pub fn queue_action(&mut self, action: PlayerAction) {
        self.pending_actions.push_back(action);
    }
}

impl PlayerInput for WebInput {
    fn get_player_action(&mut self, _: &mut dyn FnMut()) -> PlayerAction {
        self.pending_actions.pop_front()
            .unwrap_or(PlayerAction::Attack)
    }
}

 

InputもWasm用で用意していたつもりがしていなかったのが把握できました。

Outputに関しては、CLIでは即時Printlnで出力しているところをWasmではバッファとして保持し任意のタイミングで出力します。

// src/output/buffer_output.rs (EXISTING - VERIFIED READY)
pub struct BufferOutput {
    buffer: Vec<String>,
}
// ✅ Already implements MessageOutput trait
// ✅ Already captures messages for later retrieval

 

self.messages.display();
self.messages.clear();

 

実行に関しては共通の処理で、traitによって処理が分岐されます。

CLI

impl MessageOutput for CliOutput {
    fn output(&mut self, message: &str) {
        println!("{}", message);
    }
}

Web

impl MessageOutput for BufferOutput {
    fn output(&mut self, message: &str) {
        self.buffer.push(message.to_string());
    }
}

traitの力が十分に発揮するところ。

続けて、

3. JavaScript/TypeScript Interface

TypeScript Definitions (generated by wasm-bindgen):

は、TypeScriptの定義ファイル作成の流れですね。

// pkg/damdara.d.ts (GENERATED)
export class WasmGame {
  constructor();

  // Player management
  create_player(name: string): PlayerState;
  generate_password(): string;
  load_from_password(password: string): PlayerState;
 ....

ここからは実際にタスクとして分割されています。

Task 6.1: Project Setup

Estimated Effort: 1 day Priority: Critical (Blocker for others)

Cargo.tomlに必要なクレートを追加していく流れです。

[dependencies]
wasm-bindgen = "0.2"
serde = { version = "1.0", features = ["derive"] }
serde-wasm-bindgen = "0.6"

[dev-dependencies]
wasm-bindgen-test = "0.3"

[lib]
crate-type = ["cdylib", "rlib"]  # Add cdylib for WASM

更にWASM targetとして、wasm32-unknown-unknownを追加。

[build]
target = "wasm32-unknown-unknown"

wasm-packもインストール

cargo install wasm-pack

npm packageも追加となります。続いて、タスク6.2になります。

Task 6.2: Core WASM Module

Estimated Effort: 3 days Priority: High Dependencies: Task 6.1

ありがたいことに推定所要時間も出してくれています。

こちらのタスクでは主に、Web側はWasmGameのstructを設け、メソッドを追加しそちらを操作していく流れになりそうですね。

#[wasm_bindgen]
pub struct WasmGame {
    player: Option<Player>,
    output_buffer: BufferOutput,  // ✅ Already exists!
}

#[wasm_bindgen]
impl WasmGame {
    #[wasm_bindgen(constructor)]
    pub fn new() -> Self {
        Self {
            player: None,
            output_buffer: BufferOutput::new(),
        }
    }

    pub fn create_player(&mut self, name: &str) -> Result<JsValue, JsValue> {
        let player = Player::new(name);
        let state = serde_wasm_bindgen::to_value(&player.summary())
            .map_err(|e| JsValue::from_str(&e.to_string()))?;
        self.player = Some(player);
        Ok(state)
    }
}

それにしてもこれに3日工数見積はどうなのでしょう。。工数については最後考えていきましょう。

続いて、

Task 6.3: Web Input Implementation

Estimated Effort: 2 days Priority: High Dependencies: Task 6.2

ですが、ウェブ用の入力受付のweb_input.rsもwasmで扱えるように調整する流れですね。

#[cfg(target_arch = "wasm32")]
pub mod web_input;
pub struct WebInput {
    action_queue: VecDeque<PlayerAction>,
    number_queue: VecDeque<usize>,
}

続けて

Task 6.4: Battle Integration

Estimated Effort: 4 days Priority: High Dependencies: Task 6.3

こちらでは戦闘の処理が行える様にWasmGameのstructに諸々を紐づけていきます。

// Battle requires lifetime for input/output references
// Solution: Use 'static lifetime with heap allocation
pub struct WasmGame {
    player: Option<Player>,
    monster: Option<Monster>,
    web_input: Box<WebInput>,      // Heap-allocated for stable address
    buffer_output: Box<BufferOutput>,
    battle: Option<Battle<'static>>, // 'static lifetime
}

続けて

Task 6.5: Master Data Export

Estimated Effort: 2 days Priority: Medium Dependencies: Task 6.2

こちらのタスクでは各々のマスターデータを返却する処理を追加する流れですね。

こちらはモンスター一覧。

#[wasm_bindgen]
pub fn get_monster_list() -> JsValue {
    serde_wasm_bindgen::to_value(&MONSTER_MASTER).unwrap()
}

#[wasm_bindgen]
pub fn get_monster(id: u8) -> JsValue {
    serde_wasm_bindgen::to_value(&MONSTER_MASTER[id as usize]).unwrap()
}

その他にも、アイテム、呪文、ステータスなどを返却しウェブで扱えるようにします。

続いて、

Task 6.6: Error Handling

Estimated Effort: 1 day Priority: High Dependencies: Task 6.2

こちらでは、エラーハンドリングを追加する流れですね。

#[derive(Serialize)]
pub struct WasmError {
    message: String,
    code: String,
}

キャッチしたエラーもJsValueとして返却します。

fn to_js_error(msg: &str) -> JsValue {
    JsValue::from_str(msg)
}

と、大体内部のコードの改修はこの辺りまでで、ここからはビルドタスクやテストを作成する流れになっている様子です。

Task 6.7: Build Configuration

Estimated Effort: 1 day Priority: High Dependencies: Task 6.1

wasm-packのbuild scriptを用意。

#!/bin/bash
wasm-pack build --target web --out-dir pkg

Cargo.tomlに追加。

[profile.release]
opt-level = "z"     # Optimize for size
lto = true
codegen-units = 1
panic = "abort"     # Reduce binary size

gitignoreも追加します。

pkg/
target/wasm32-unknown-unknown/

 

Task 6.8: Testing

Estimated Effort: 3 days Priority: High Dependencies: Tasks 6.2-6.6

続いてテストを作成する流れなのですが、ここまでが優先度高のタスクぽいです。

wasmのテストに関しては、「wasm-bindgen-test」を用いて実行します。

#[cfg(test)]
mod wasm_tests {
    use wasm_bindgen_test::*;

    #[wasm_bindgen_test]
    fn test_create_player() {
        let mut game = WasmGame::new();
        let result = game.create_player("ゆうてい");
        assert!(result.is_ok());
    }
}

様々なテストケースを準備し、

wasm-pack test --headless --firefox
wasm-pack test --headless --chrome

firefox,chromeをヘッドレスで実行できるように準備します。

 

Task 6.9: Example Web Application

Estimated Effort: 5 days Priority: Medium Dependencies: Task 6.8

こちらでは、実際にウェブで利用するシーンを想定したexamplesを用意する流れとなっています。

import init, { WasmGame } from './pkg/damdara.js';

async function run() {
    await init();
    const game = new WasmGame();

    // Create player
    const player = game.create_player("ゆうてい");
    console.log(player);

    // Start battle
    game.start_battle(0); // Slime

    // Player attacks
    const result = game.player_action("attack");
    const messages = game.get_messages();
    messages.forEach(msg => console.log(msg));
}

run();

開発サーバーもviteを使う形です。

{
  "scripts": {
    "dev": "vite",
    "build": "vite build"
  }
}

 

Task 6.10: Documentation

Estimated Effort: 2 days Priority: Medium Dependencies: Task 6.9

こちらのタスクでは、上記のWasmの仕様に関して、ドキュメント化する流れとなっています。

Wasm用として、WASM.mdを新たに設けるのは良いですね。

 

Task 6.11: CI/CD Integration

Estimated Effort: 2 days Priority: Low Dependencies: Task 6.8

こちらでは、GitHub Actions workflowを設ける流れですね。

良いですね。pushやプルリクマージでwasm成果物がビルドされ、npmパッケージとしてpublishも行う様子です。

 

Task 6.12: Performance Optimization

Estimated Effort: 2 days Priority: Low Dependencies: Task 6.9

最後のこちらはパフォーマンスに関してです。

パフォーマンス向上のためBundle sizeが小さくなるように工夫したり、OS依存のところをWasm側も考慮しクレートに置換するような流れぽいです。

そして最後に、単体テスト、結合テスト、クロスプラットフォームテスト、パフォーマンステストが追加されていく流れぽいです。

 

ということで、タスクに関しては主にこのような流れで、ありがたいことに最後、工数見積(各週のスケジュール)も出してくれています。

Timeline Estimate

Total Duration: 2-3 weeks (assuming full-time work)

Week 1:

  • Day 1-2: Tasks 6.1-6.2 (Setup + Core module)
  • Day 3-4: Task 6.3 (Web input)
  • Day 5: Task 6.4 start (Battle integration)

Week 2:

  • Day 6-8: Task 6.4 complete (Battle integration)
  • Day 9: Task 6.5 (Master data export)
  • Day 10: Task 6.6 (Error handling)

Week 3:

  • Day 11: Task 6.7 (Build config)
  • Day 12-14: Task 6.8 (Testing)
  • Day 15-17: Task 6.9 (Example app)
  • Day 18-19: Task 6.10 (Documentation)
  • Day 20-21: Tasks 6.11-6.12 (CI/CD + optimization)

全部で、21日ほど。と、こんなにかかるか? 遅くても1週間あれば実装完了になりそうな気がするが、

ある程度バッファを大きく取ったスケジュールで見積もってくれているみたいですね。

 

既存プロダクトのリファクタリング案

という感じで、半ば放置してたプロジェクトを自分が思い出したい気持ちも含め、AI駆動開発を本格的に導入してみました。

まず大事なのは、AIリーダブルなドキュメントの配置。それは固有のAIエージェントに依存しないようにディレクトリを設け、Spec駆動開発でも用いられているフォーマットに沿ったドキュメントを用意します。

続いて、作業を行う際はタスクファイルで管理していくのを徹底します。

これらによって、例え同スレッドでずっとやり取りを行いトークンの上限に達し新たにスレッドを作成しなしても途切れることなく作業を進めて行きことができるでしょう。

今回は、機能追加として「Wasm対応」を追加していく流れだったのですが、機能追加のみならず「リファクタリング案を出して」と指示するだけでも、上記のような形でリファクタリング案をまとめてくれるので、そちらからAI駆動開発導入を進めるのも良いかもしれません。

AI駆動開発を本格的に行う流れになり、「書く」ということよりも専ら「読む」作業が増えて来たのですが、その「読む」ことすらAIに任せれば、基本指示するだけで開発が進んで行くのではないでしょうか。

と、言いつつもどんどん思考する回数が減り、脳が劣化していっているのを感じている今日このごろで段々と不安も覚えだしたので、AIを全く使わないAI デトックスデーを設けるのも良いのでは。と企んでおります。

と、言った感じで今日はここまで、

ではではぁ。

またまたぁ。

 

 

Comment

Related Article

効率の良い AI駆動開発について考える

2025.11.09

AIのために働け。AI リーダブルコーディングな未来。

2025.05.21

5分で覚える Flutter Flameで作る Wave Function Collapse – 波動関数崩壊アルゴリズム

2023.12.20

TypeScriptでStateMachine

2021.05.16

パックマン 解析プログラム動画から見る 追跡アルゴリズム

2020.09.23

5分で覚えるAI Minimax(ミニマックス)法とalpha-beta法

2016.05.14

JavaScriptでユークリッド距離とピアソン相関係数

2016.05.03

LINE BOT API Trial で WordPress + LINE BOT の Web帳BOT を作ってみました。

2016.04.30

CATEGORY LIST

LATEST NEWS

効率の良い AI駆動開発について考える

AI・Bot・algorithm

2025.11.09

MacとClaude Codeで構築する cc65(NES)開発環境

Game

2025.10.24

Three.js - ShaderMaterialで、ブレンドシェイプ(MorphTarget)アニメーション対応

JavaScript

2025.10.15

ゲーム開発に必要な基本数学入門

Rust

2025.08.15

Godot 4 & WebAssemblyで様々なデータフォーマットを処理

Godot

2025.07.06

Godot 4 & WebAssemblyで、Hello WebAssembly! - godot-wasm

Godot

2025.06.21

Godot 4 & Rust 始め方

Rust

2025.06.19

ご、ごめん。。今はFlutterの気分じゃないんだ。。

Flutter

2025.05.30

AIのために働け。AI リーダブルコーディングな未来。

AI・Bot・algorithm

2025.05.21

Rustでつくる ふっかつのじゅもん

Rust

2025.04.29

Tauri(Rust) × AI で作る GitGUIクライアントアプリ その5

Rust

2025.04.14

う、動くぞ! Mac mini Apple M4 Pro で PS3ソフトを遊ぶ。RPCS3 Mac版を起動

Game

2025.04.12

RANKING

Follow

SPONSOR

現在、掲載募集中です。



Links

About Us

WEBデザイナーの、WEBデザイナーによる、WEBデザイナーの為のサイト。「みんなで書こう!」と仲間を募ってみたが、結局書くのは自分だけとなってしまいました。日々のメモを綴っていきます。

Entry Profile

Graphical FrontEnd Engineer
- Daisuke Takayama

MAD CITY 北九州市で生まれ育つ。20代はバンド活動に明け暮れ、ふと「webデザイナーになりたい。」と思い、デジタルハリウッド福岡校入学。卒業後、数々の賞を受賞、web業界をざわつかせる。
現在、主に、ゲーム制作中心に港区六本木界隈で活動中。

FOLLOW US