はじめに
前回はWindsurfを使ったVibe Codingで、Electronを使ったユーティリティアプリを作成しました。
その頃はCursor / Windsurf / Cline といったAIコーディング機能付きのIDEが大ブームで、その恩恵を受けてアプリを作り切ることができました。
それがたったの1ヶ月程度で、今はClaude Codeや、フォローワーのGemini CLIがとんでもないブームを巻き起こしており、AI関連の進化の速さをひしひしと感じております。
Claude Codeのすごさ
最初にClaude Codeが出た時には、「コマンドラインで動くCursorかな?」くらいの認識でそれほど気に留めていませんでしたが、Claude 4が出て一緒に正式版になったClaude Codeは、すさまじい進化を遂げていました。
まず、Claude 4によってコーディング能力が一気に上がったのに加えて、単発の行動ではなく計画してタスクを立ててから順に実行に移すというAIエージェント的な能力が爆上がりしていました。なので、CursorやWindsurfではトークンが大きすぎて実行できなかったようなタスクにも粘り強くさまざまな手段を使って取り組み、最後には作り上げてしまうという離れ業を行うようになりました。
Claude Codeのコスト
しかしながら、Claude Codeはお高いです。Windsurfが$15で使えていたのに比べて、最低でも$100、できれば$200のプランに入る必要があります。ただ、これもClaude Codeの能力を考えればむしろ安い、というのが大方の感想でしょうし、僕もそう思います。
作ったもの
自分が欲しいと思っていた簡単な10年日記アプリを作成しました。その名も「十年スナップ」です。1エントリにつき1枚の写真と日記を投稿して、過去の同じ日の日記をすぐに見られる、というアプリです。App Storeにて公開しています。
AIコーディング方針
前回の経験から、今後のAIコーディングの鉄則として「設計図をきちんと作らなければならない」ということは最初から認識していました。といっても、機能一覧や画面遷移図などをウォーターフォール式に作るのではなく、アーキテクチャを指定して作ることに重点を置きました。とはいえReact Nativeは初めてだったので、それ用のアーキテクチャは作れませんでした。そこで、サーバーサイドのAPIを作る時のテンプレートとなる簡単なサンプルプロジェクトを作り、そこからAIが理解できる仕様書を書いてClaude Codeに依頼しました。下記がその一部です。
# LastYearToday アーキテクチャ設計書
このドキュメントは、React Native (Expo) + TypeScript + Effect + Clean Architectureを使用した10年日記アプリのアーキテクチャを定義します。
## 概要
LastYearTodayは、Clean Architectureの原則に従い、ビジネスロジックをUIやフレームワークから分離した設計を採用します。Effectライブラリを使用して、型安全なエラーハンドリングと関数型プログラミングのパターンを実装します。
## プロジェクト構造
```
LastYearToday/
├── src/
│ ├── modules/ # 機能別モジュール(Clean Architecture)
│ │ ├── diary/ # 日記機能
│ │ │ ├── domain/ # ドメイン層
│ │ │ │ ├── entities/ # エンティティ
│ │ │ │ │ ├── Diary.ts
│ │ │ │ │ ├── DiaryLocation.ts
│ │ │ │ │ └── index.ts
│ │ │ │ ├── errors/ # エラー定義
│ │ │ │ │ ├── DiaryValidationError.ts
│ │ │ │ │ ├── DiaryNotFoundError.ts
│ │ │ │ │ ├── StorageError.ts
│ │ │ │ │ └── index.ts
│ │ │ │ ├── repositories/ # リポジトリインターフェース
│ │ │ │ │ └── index.ts
│ │ │ │ └── usecases/ # ユースケースインターフェース
│ │ │ │ └── index.ts
│ │ │ ├── applications/ # アプリケーション層(ユースケース実装)
│ │ │ │ ├── createDiary.ts
│ │ │ │ ├── getDiariesByDate.ts
│ │ │ │ └── updateDiary.ts
│ │ │ └── infra/ # インフラストラクチャ層
│ │ │ ├── localStorage/ # ローカルストレージ
│ │ │ │ └── localStorageRepository.ts
│ │ │ └── mockRepository.ts # テスト用実装
(略)
## レイヤー設計
### 1. ドメイン層 (Domain Layer)
ビジネスロジックとビジネスルールを定義する最も重要な層。外部依存を持たない。
#### エンティティの例
```typescript
// modules/diary/domain/entities/Diary.ts
export interface Diary {
id: string;
date: Date;
text: string;
photos: PhotoReference[];
location?: DiaryLocation;
createdAt: Date;
updatedAt: Date;
}
```
(略)
Claude Codeの指示書`CLAUDE.md`には、このアーキテクチャに従って作るように指示を書きました。
コーディング開始
この方針で、最初はうまく行きました。いい感じ!と思って、いろいろ機能追加や仕様変更をClaude Codeに指示してからコードを見直してみると、設計を無視したコードが量産されており、直すのに苦労しました。
設計が無視された原因
まず、自分がClaude Codeのセッション管理の仕組みを理解していなかったことが挙げられます。Claude Codeは一般的なLLMと同じく、セッションが変われば前世の記憶は無くなってしまいます。IDEを落として再開した時や、変な動きをし始めた時に ctrl + c を連打したらClaude Codeが終了してしまい、再度新しいセッションから始めてしまっていました。前のセッションに戻るには
claude -c
と打つか、 claude -r
で履歴から戻りたいセッションを選ぶ、という基本的な使い方を理解していませんでした。
また、Claude Codeへの基本的な指示が統一できていなかったというのもあります。実装を行う前に、タスク化と差分の表示、単体テストにパスすることを最初は指示していたのですが、だんだん適当な指示になってきて、動けばいいか、と完成させるのを優先してしまっていました。
現在ではこのあたりの指示の仕方や、 CLAUDE.md
の書き方、そしてhooksを使って内容を遵守させる方法などのノウハウがZennなどにたくさん挙がってきているので、それらを組み合わせて最適な形を見つけていきたいです。
フロントエンドはClaude Codeの独壇場
データ周りの設計はかなり苦労しましたが、フロントエンド側のUIやレイアウト、ジェスチャーやナビゲーションなどの実装は自分より遥かに優秀で、ずっとClaude Codeに頼りっぱなしでした。というか画面が見えていないのにどうして細かなレイアウト修正の指示もこなしてしまうのか不思議なくらいでした。MCP経由でiOSシミュレーターのスクリーンショトと撮る仕組みなども入れたのですが、それすら必要ないくらいでした。
React Nativeまわり
今回、React Nativeを使うのも初めてだったので、それについてもClaudeにいろいろ教わりながら作りました。
ただ、ここはもっと基礎的なチュートリアルなどをやってから取り組めばよかったなと感じています。ネイティブプラグインとExpo Goやpreviewビルドとの関連など、知っていれば余計なやりとりがなかったのにと思います。
これからのAIコーディングに求められるのは、細かい部分の実装方法ではなく、全体的な仕組みやアーキテクチャを採用することでのメリット・デメリットの理解と、方針を決定する能力なのかなと感じています。
おわりに
Claude Codeを使ってなにか1つ作る、という学習目標は達成できました。時間的には1ヶ月くらいかかりましたが、その間いろんな場所に旅行に行っていて中断していたので、実質的には丸一週間くらいでしょうか。
Gemini CLIとClaude Codeの連携など楽しそうな話もたくさん出てきているので、引き続き調査して(遊んで)いきたいです。