AIを使ってRxJava → Coroutine移行を、1人で数十モジュール爆速で終わらせた話
自己紹介と背景
去年の6月にSansanに転職して、AndroidとKotlin MultiplatformをメインにやっているエンジニアのPJH(パク ジョンフン)です。
それ以前はチームラボで同じくAndroidとKotlin Multiplatformをメインにしてテックのスペシャリストをしていました。
今回は現職で取り組んだRxJava → Coroutine移行について、自分目線で具体的に振り返ります。
作業完了からは結構時間が経ってしまっていますが、会社のテックブログ(こちら)と内容が一部重なりますが、こちらは個人として何を考え、どう動いたかにフォーカスした記事です。
背景と課題:数十モジュール、どう捌く?
このプロジェクトのスコープは数十個のモジュールにまたがるRxJava → Coroutine移行。設計と技術選定は自分が担当しました。
規模が大きいため、最初は複数のAndroidエンジニアにアサインする想定でした。
ところが着手してみると、想定より遥かに速いペースで実装できていることに気づきました。
並行して複数モジュールを同時に進められることも分かったため、最終的に全工程を1人で完遂する判断をしました。
ここで自分が立てた個人目標が、このプロジェクトの核心です。
「複数のAI Agentを並行稼働させ、実質的に複数人分の速度を出す」
正直しんどかったところ
技術的な話の前に、まず本音を書いておきます。
このプロジェクト、最初の設計フェーズが一番しんどかったです。「どこまでAIに任せられるか」が全く分からない状態からのスタートだったので、ある程度は手を動かしながら検証するしかありませんでした。
また、AIが間違えたときの判断が地味に疲れます。 変換結果がパッと見で正しそうなのに実は微妙にズレている、みたいなケースが初期はちょくちょくあって、「これは本当に自分が全部レビューできるのか?」と不安になる瞬間もありました。
ただ、そのしんどさを乗り越えるために試行錯誤した結果が、後述する「変換ルールの設計」につながっています。
AI活用戦略:並行稼働させるための設計
まず「AIに任せられる範囲」を測定した
いきなり全部AIに投げても精度は上がりません。
最初は検証を兼ねながら、どこまでAIが対応できるかを丁寧に測定しました。
この測定作業、正直地味で時間もかかります。
でもここをサボると後で全部自分に返ってくるので、焦らず向き合いました。
その結果、大まかに分けると:
| 担当 | 割合 | 内容 |
|---|---|---|
| AI Agent | 約8割 | ルール化できる変換処理 |
| 人間(自分) | 約2割 | 構造的な判断が必要な箇所 |
この2割は単純作業ではなく、文脈や設計の意図を理解した上で対処が必要な箇所です。
ただ、本質を把握していれば8割のAIがしている作業と比べると時間はそれほどかかりません。
タスクを「AI並行稼働できる粒度」に分解した
元々はモジュール単位でタスクが定義されていましたが、それだとAI Agentを並行で走らせにくい。
そこで、より細かく・互いに独立した単位に分解しました。
この分解作業は、実は**「誰かに作業を引き継ぐとしたら?」という視点で考える**とうまくいきました。
曖昧な塊のままでは誰にも渡せないし、AIにも渡せない。逆に言えば、人間のチームメンバーに渡せる粒度なら、AIにも渡せる。
これにより、3〜5個のAI Agentを同時に稼働させることが可能になりました。
うまく機能すれば、実質3〜5人分の開発速度が出る計算です。
技術的ソリューション:AIが迷わない変換ルールを作る
AI精度の鍵は、「迷いなく変換できる明確なルール」を事前に設計しておくことです。
RxJava ↔ Coroutine の対応を体系化
自分はこれまでの経験から Result 型や runCatching を多用してきました。
RxJavaとCoroutineの構造を改めて整理した結果、ある確信に至りました:
Result/Flow+suspend funの組み合わせで、RxJavaの全表現をカバーできる
この発見は、自分にとってかなり重要な気づきでした。
「RxJavaとCoroutineは別物」という先入観を持っていると、移行は「書き直し」になってしまいます。
でも構造的な類似性を軸に考えると、「対応関係の整理」として捉えられる。
この視点の転換が、AI活用の精度を大きく上げました。
具体的にやったこと
① RxJava → Coroutine のAPIマッピングを明文化
どのオペレータがどの関数・クラスに対応するかを整理し、AIが参照できる形にしました。
これは自分の頭の中にあった暗黙知を言語化する作業でもあって、チームで共有できるドキュメントにもなりました。
② 移行後のコードサンプルを用意
AIに「こう書いてほしい」という具体的な例を示すことで、出力のブレを大幅に削減しました。
サンプルがあると、レビュアーも「このパターンと同じか」で判断できるので、レビュー速度も上がります。
③ @Deprecated で移行前後の形を明示
@Deprecated(
message = "Use suspend fun with Result instead",
replaceWith = ReplaceWith("newSuspendFun()")
)
fun oldRxJavaFun(): Observable<T> { ... }
これは単にAIへの指示だけでなく、他のエンジニアへの案内にもなるので一石二鳥でした。
移行途中の状態でも「何をどう変えるべきか」がコードを読めば分かる状態にしておくことで、後から入ってきたメンバーも迷わずに作業できます。
これにより、AIはほぼマニュアル的に意図した形(Result or Flow + suspend fun)へ変換できるようになりました。
また、既存のRxJavaラッパー関数・クラスも元の構造を維持したまま置き換えられたため、差分が最小限になり、可読性も保てました。
「自分だけが分かる」にならないために
実はこのプロジェクトを進めながら、ずっと気にしていたことがあります。
「自分が突っ走って、周りが置いてけぼりにならないか?」 ということです。
1人で高速に進めると、どうしても「文脈が自分の頭の中だけにある」状態になりがちです。
特にAIを使った作業は、プロセスが見えにくい。後から「なんでこうなってるの?」と聞かれたときに答えられる状態を意識しました。
そのために意識したのは以下の3点です:
- 変換ルールをドキュメントとして残す(自分用ではなく、チーム用として)
-
@Deprecatedなどのコード上のヒントで、意図をコードに埋め込む - レビュープロセスを「知識がなくても判断できる形」に設計する
結果として、このアプローチは他のエンジニアにも再現可能な形になりました。
自分がいなくなっても、同じルールと設計で他のメンバーが続きを進められる状態です。
成果
- 数十モジュールの移行を1人で完遂
- AI Agentを3〜5個並行稼働させることで、実質数倍の開発速度を実現
- 変換ルールの明文化により、レビューがほぼ機械的に行えるようになり、レビューコストも大幅に削減
- 移行後のコードは構造的な一貫性が保たれ、差分が最小限
- ドキュメントとコード上のヒントにより、他のメンバーへの引き継ぎも容易な状態に
まとめ
大規模移行を1人で爆速で進めるために効いた要素を整理すると:
① タスク分解 → AIが並行稼働できる粒度・独立性を確保する
② スコープ分離 → AIと人間の担当範囲を最初に明確化する
③ 変換ルール整備 → AIが迷わず動ける明確な指針を作る
④ レビュー設計 → 認知負荷を下げる仕組みを最初から組み込む
⑤ チームへの配慮 → 自分だけが分かる状態を作らない
「AIに丸投げ」ではなく、AIが最大限力を発揮できる環境を人間が設計する。そして、その設計はチーム全体にとって使いやすいものであるべきだと、今回改めて感じました。