BLE5 の Extended Advertising を使って AI コーディングを試していく

ちょっと、執筆と新人研修が重なりあってしまったので、ブログの更新が滞ってしまっているのですが、ぼちぼち再開します。
コーディング的には ExcelUnoLike の続きをしたいところですが、どうもあれこれと設計を見直したくなって重たくなりそうなので、先に BLE5 を使ったツールのほうを試していきます。

プログラマから見た AI コーディングの懸念

普段使いのコーディングでは VSCode + GitHub Copilot を使って「AI ペアプロ」という形で進めていきます。AI ペアプロなので、常にプログラマが並走しています。AI に任せっきりというわけでもなく、AI が出力してきたコードを鵜呑みするわけでもなく、ある程度ですが AI コードを常にレビューしながら進めていきます。まあ、いろいろ面倒になって、ちょっとだけ動作確認した後に Git にコミットしてしまうことも多いのですが、場合によっては 1 日分の AI コードを戻してしまうことも多いです。

BLE 絡みと Web API 絡みでプロトタイプ的なコードを結構書いてきたのですが、それ以上の品質に AI コーディングが辿り着くのか?というと、現状では何とも言えません。このあたりは、私が「AI ペアプロ」に留まっている理由でもあり、巷のテクニカルな記事をみると大規模で手間のかかる AI コーディングならば良さそうなのですが、こう一歩ずつ試してくようなプロトタイプ型のコーディングではやっぱり「AI ペアプロ」のほうがよさそうな気がします。

とはいえ、手元で「Claude Code」を入れて(実際には Claude Cowork 用に入れたのですが)試してみると、ああ、確かに Web アプリケーションならば、仕様書を与えてコーディングさせることは可能っぽいです。というか、逆に言えば「AI ペアプロ」的な使い方は Claude Code だとやり辛いです。逆に言えば、夜間に一括でできるようなバッチ的な処理には非常に向いています。おそらく、単体テストの自動化と再帰的なコード修正がやり辛いのは、ここのバッチ的な処理が原因かもしれません。

という訳で、ここまでが愚痴…

AI ペアプロ型とバッチ型の両方を試してみる

恐らく一長一短があると思うのですが、

  • VSCode + GitHub Copilot を使った「AI ペアプロ」型
  • Claude Code を使った「バッチ型」

の両方を試してみます。巷のブログ記事だと、「Web サイトが一瞬でできました」タイプが多いので、仕様が決まったら一気に作る Claude Code のほうが向いているような気もしますが、そのあたりの非 Web アプリの場合はどうなのか?というお試しです。

本来ならば要件定義からスタートしたほうがいいのですが、今回は機能要件レベルからスタートしてみます。機能要件をまとめるときの諸々は Copilot などの Chat ツールを使っています。

## 機能要件

- BLE5 の Extended Advertising を利用して、Android 端末同士でチャットができる
- チャットの内容は、テキストメッセージとする
- iBeacon のようにブロードキャストでメッセージを送信し、受信側はそれを受け取って表示する
- BLE5 通信の届く範囲内であれば、複数の端末が同時にチャットに参加できる

チャットツールなんて「チャットツールを作って」と AI に頼めばさっくりと作ってくれる典型的なパターンなのですが、今回は WEB サーバーを使わないし、Firebase も使わないパターンです。しかも、Android 端末同士限定で、BLE5 の Extended Advertising を使います。Extended Advertising 形式だと、iBeacon のようにブロードキャスト通信ができます。実運用的にはコネクション型を使ったほうがいいのですが、このあたりは趣味的に BLE5 を使ってみることにします。

このあたり、AI にとって難関なのは「物理的な Android を動かさないといけない」というパターンです。これ、バッチ型のほうに非常に不利なのですが、なんとかクリアできるように考えていきたいです。実は AI ペアプロ型の場合も問題が多くて、テストをするときに「AI が提案するコードを人間が動かし続ける」という使役的なパターンが何度となく続きます。確かに、ペアプロなのですから、コード役とドライビング役が交代してもいいのですが、なかなかこれは辛いです。FolkBears の改修しているときに何度となく発生しています。同じパターンは、Web API を作成したときの React での UI のプロトタイプでも発生します。プロトタイプ的に作る場合にはどこかで諦めればいいのですが、製品として品質を上げる場合にはどこまでやるのかが不明になってしまいます。
ここを自分的には何とかしたいところですね。

このあたり、

  • テスト工程を含めて、これも自動化できるように考える
  • 例えば、ログ取得など、単体テスト、結合テストを AI 任せにできるだろうか?

という課題も含めていきます。
クリアすべきテスト項目も AI ペアプロ的にあるいはバッチ的に追加します。

設計する

ここ 1 年ほど AI コーディング(バイブコーディングも含めて)を試してきた結果、経験上、仕事で使う場合には軽く「設計」をしておくと方向性が定まってよい、と結論に至っています。仕様書駆動(spec駆動)ほど詳細に書くわけでもなく、先の「機能要件」ほど大雑把なままではなく、という中間的な位置です。
結局のところ、ウォーターフォール開発にせよアジャイル開発にせよ、途中での変更や見直しからは逃れられないので、そのあたりの余地&人的な手間を考慮する必要がでてきます。
特に、単独でのAI コーディングの場合には、伝達コスト(コミュニケーションコスト)を抑えることができるので、派手な設計書は必要ありません。まあ、多人数での開発の場合には、レビューなどが必要となるのである程度の文書化が必要になるのですが…今回は Android アプリなので小規模なものを対象とします。

実は、機能要件を渡せば VSCode + GitHub Copilot の組み合わせでも結構なところまでできてしまいます。UI なり、メッセージ形式なり、通信フローなりを、既存のものからうまく引っ張ってくるので、ある程度動くものが素早くできあがります。なので、「プロトタイプ的に」作るのは、機能要件だけでも結構 ok です。
ただし、最近の技術ブログや SNS でも話題になっているように、これをどうやってテストしていくのか、将来機能追加があるときにどうやって品質を保証していくのか、という問題がでてきます。このあたりは、開発するアプリ/製品の寿命や運用形態にもよるので、その都度考える必要がでてくるのですが、少なくとも AI コーディングで機能要件だけ渡して、一気に作って貰って放置するのはダメです。
なんらかの設計方式を与えてしまったほうがコードのスタイルが揃い、後での修正や機能追加がやりやすくなります。

クラス設計

  • 機能要件を満たすように、クラス設計を書いて。

とプロンプトを打って、クラス設計を出力させます。

## クラス設計

BLE Extended Advertising を使った「ブロードキャスト型チャット」を成立させるため、責務を以下のように分離する。

### 1. クラス一覧

| クラス名 | 種別 | 主な責務 |
|---|---|---|
| ChatActivity | UI | メッセージ一覧表示、送信入力、画面イベント処理 |
| ChatViewModel | Presentation | UI 状態管理、送信要求、受信イベント購読 |
| ChatRepository | Domain/Application | 送受信ユースケース統合、履歴の仲介 |
| BleChatService | BLE Facade | BLE 初期化、Advertiser/Scanner の開始停止管理 |
| BleAdvertiserManager | BLE Tx | Extended Advertising による送信データの分割・送出 |
| BleScannerManager | BLE Rx | 広告パケット受信、再構成、重複排除 |
| PacketAssembler | Protocol | 受信パケットの順序復元、メッセージ復元 |
| PacketFragmenter | Protocol | テキストメッセージの分割、ヘッダ付与 |
| MessageCodec | Protocol | 文字列とバイト列の変換、バージョン管理 |
| CryptoManager | Security | 暗号化/復号(任意有効化)、鍵管理窓口 |
| DuplicateFilter | Reliability | MessageId による重複受信抑止 |
| PeerRegistry | Session | 参加端末の最終受信時刻管理(参加者把握) |
| ChatMessage | Model | チャット本文、送信者 ID、時刻、MessageId |
| AdvPacket | Model | 1広告単位データ(MessageId、Seq、Total、Payload) |
| AppLogger | Cross-cutting | ログ収集(テスト・障害解析用) |
| ErrorHandler | Cross-cutting | BLE 例外、権限エラー、復旧リトライ判断 |


### 2. 主要クラス詳細

#### ChatActivity
- 責務
- メッセージ一覧表示
- 送信ボタン押下イベントを ViewModel に委譲
- BLE/権限状態の表示
- 主なメソッド
- `onCreate()`
- `observeUiState()`
- `onSendClicked(text: String)`

このクラス設計は最初のたたき台になるものなので、中身を確認していきます。この中身は、適当なクラス設計のテンプレート文書があればそれにフォーマットを合わせてくれます。プランモードで慎重にしてもいいのですが、AI ペアプロ型の場合は、いったん設計の部分で止めておくほうが無難です。まあ、Android & Kotlin のプロジェクトになじみがないとか、BLE 通信のところに知見がないと、設計段階で戸惑ってしまうのですが、今回はある程度 Android アプリを作ったことがあるという前提になります。

今回は、初期型として作りたいので、チャットの返答やクラス設計のサマリを見ていくつかの機能を削っておきます。

  • 暗号化 CryptoManager の機能は削除して。
  • Kotlin の Jetpack Compose を使う場合、ChatViewModel は必要?
  • Compose を利用する前提にして、テストしやすい方式に変更して。
  • 回転 ChatRoute は考えずに、縦置き(ポートレート)の画面構成にして。
  • メッセージは 100 文字以内とするため、PacketAssembler と PacketFragmenter を削除して。
  • ブロードキャストするメッセージは10秒だけ送信する。

大まかなクラス設計ができたら、シーケンス図を使って確認します。

シーケンス図

1年前の FolkBears の改修のときにはフローチャートを手作業で書くしかなかったのですが、いまだと Mermaid 形式で書いてくれます。

  • 主な送受信のフローを、シーケンス図に追加して。
## シーケンス図

### 1. メッセージ送信

mermaid
sequenceDiagram
actor User as User
participant Screen as ChatScreen
participant Activity as MainActivity
participant Repo as ChatRepository
participant Service as BleChatService
participant Codec as MessageCodec
participant Advertiser as BleAdvertiserManager

User->>Screen: メッセージ入力 / 送信押下
Screen->>Activity: onSend(text)
Activity->>Repo: publishMessage(ChatMessage)
Repo->>Service: send(chatMessage)
Service->>Codec: encode(chatMessage.text)
Codec-->>Service: payload
Service->>Advertiser: broadcast(AdvPacket)
Advertiser->>Advertiser: startAdvertising()
Advertiser-->>User: Extended Advertising で送信開始
Advertiser->>Advertiser: 10秒タイマー開始
Advertiser->>Advertiser: stopAdvertising()
Advertiser-->>User: 送信停止
  • メッセージ送信時に BLE OFF にした時の動作を追加。
  • メッセージ受信時に BLE OFF を追加。
  • いくつかのエラーを処理を追加しておきます。

この時点で、「agents\概要設計.md」ファイルは、300 行を超え始めているので、きちんとチェックするにはちょっと手間な量になってきています。シーケンス図やクラス図は、設計の正しさをチェックするためなので、AI コーディングの場合はチェックした後は削除してもよいかもしれません。人間だけでチェックする場合は、設計書として残さないとコーディングのときに困ってしまうのですが、AI コーディングの場合はあまり関係ありません…というか、シーケンス図通りに AI がコーディングするとは限らないという意味ですね。

FolkBears の改修のときは AI にコードからシーケンス図を作って貰ったので、コードを吐き出してからシーケンスをチェックしてもよいかもしれません。

軽く UI 設計をしておく

実際のところは Figma とか使って UI デザインをしたほうがいいのですが、今回はプロトタイプ的に作るので、テキストベースで UI 設計をしてもらいます。コードとしては Jetpack Compose で書いてもらうことにします。

## UI 設計

### 1. 画面レイアウト(ポートレート固定)

画面を上から 3 つの固定領域で構成する。ヘッダと入力領域は固定高さ、メッセージ領域が残りの高さをすべて占有する。

┌─────────────────────────────────────┐
│ ヘッダ(固定) │ ← StatusBar 直下
│ [● BLE 状態] [👥 参加者数] [⟳ スキャン中] │
├─────────────────────────────────────┤
│ │
│ メッセージ一覧(可変・スクロール可) │ ← weight(1f) で拡張
│ │
│ ┌───────────────────────────────┐ │
│ │ HH:MM senderId │ │ ← 受信メッセージ(左寄せ)
│ │ メッセージ本文 │ │
│ └───────────────────────────────┘ │
│ │
│ ┌─────────────────────┐│
│ │ senderId HH:MM ││ ← 自分のメッセージ(右寄せ)
│ │ メッセージ本文 ││
│ └─────────────────────┘│
│ │
├─────────────────────────────────────┤
│ 入力領域(固定) │
│ [TextField(テキスト入力)] [送信ボタン] │
└─────────────────────────────────────┘

これもどこまでコードに反映されるか分からないのですが…正確にコードに反映されないのであれば、UI 設計としてはどこまで細かく指定できるのか?ということになりますね。

UI 設計は Claude Code に読み込ませる必要もあるため、Copilot で作ったものをそのまま貼り付けておきます。

ここで、おおまかな概要設計ができたので、これを GitHub Copilot に読み込ませてコーディングをしていきます。

カテゴリー: 開発 パーマリンク

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

*