はじめに

はじめまして。
jamboでFlutter を用いたアプリ開発を進めているinoueです。

この記事を書こうと思ったきっかけは、
個人開発と実務開発のギャップに強く戸惑った経験があったからです。

  • どこに何のコードが書いてあるのかわからない
  • 通話機能がどのような仕組みで実装されているのか
  • APIとはそもそも何なのか

こうしたことが理解するのに時間がかかり、
実装が思うように進まない状態が続きました。

自分自身の振り返りも含めて、
この経験を記事として共有することにしました。

💪 結論:一番しんどかったのは「技術」ではなく「全体像」

UdemyやYouTubeなどの教材で自己学習をしていた頃は、
とりあえずコードを書いて、動いたら嬉しい。
それだけで十分な達成感がありました。

コードの量も少なく、
「このコードがどこで使われているのか」を
自分の中で把握できていたと思います。

しかし、会社に入社し実務のアプリ開発に関わるようになると、
状況は大きく変わりました。

他人が書いたコードを読んで理解する必要があり、
ファイル数やコード量も一気に増えました。
さらに、API連携や、これまで触れたことのなかった
通話機能まわりのコードが含まれていたことで、

  • この処理は何をしているのか
  • どこから呼ばれているのか
  • アプリ全体の中でどんな役割を持っているのか

を把握するのに、かなり時間がかかりました。

振り返ってみると、
自分が一番しんどかったのは個々の技術そのものではなく、
アプリ全体の構成や処理の流れを理解することだったと感じています。

📖 SwiftUI / Flutterを触り始めた頃に感じた違和感

SwiftUI / Flutter を触り始めた当初、
UIまわりのコード自体は比較的シンプルで、
「どのコードがどのUIに対応しているか」は理解できていました。

ただ、実務ではファイル数が多く、
目的のコードにたどり着くまでに時間がかかり、
処理の流れを追いながらコードを読むことができていませんでした。

そのため、処理の流れを追いながらコードを読むことができず、
「この画面で何が起きているのか」を
自分の言葉で説明できない状態でした。

結果として、
表面的には実装できているのに、実務のコードは理解できない
という違和感を強く感じていました。

その後、Devin という AI 開発支援ツールを活用して、
アプリ全体の構成や各ファイルの役割、
コードがどのような流れで呼ばれているのかを整理しながら理解することで、
他の人が書いたコードを把握するまでにかかる時間を、
以前よりも大きく短縮できるようになりました。

実装の補助としてだけでなく、
「このアプリはどういう構造になっているのか」を理解するための
整理役として使えた点が、自分にとっては特に大きかったと感じています。

参考:

✍️ Agora SDK(音声・ビデオ通話)で詰まったポイント

通話機能については新規実装ではなく、
既存の通話SDKまわりの不具合修正から取り組みました。

当時特に問題になっていたのは、

  • 終了処理が不完全で、次回の通話が正常に動作しない
  • 相手がチャンネルに参加しているのに映像が表示されない

といった点です。

終了処理まわりの問題

通話画面を閉じても、

  • Agoraのチャンネルから正しく退出できていない
  • CallKit の通話状態が切れていない
  • オーディオセッションやエンジンが残ったままになっている

といった状態が発生しており、
その結果、次回の通話がつながらない、音声や映像が出ないといった問題が起きていました。

UI上は通話が終了しているように見えても、
内部的には通話中のままになっているケースもあり、
原因の切り分けが難しかったです。

相手がchannelに入っているのに映らない問題

もう一つ詰まったポイントが、
相手がチャンネルに参加しているにもかかわらず映像が表示されない問題です。

onUserJoined のイベントは発火しているものの、

  • remoteUid の管理不足
  • 描画タイミングとUIライフサイクルの不整合

などが原因で、映像が表示されない状態になっていました。

イベントは来ているのに画面に何も映らないため、
どこに問題があるのか分かりづらく、調査に時間がかかりました。

通話の状態管理やSDKイベントとアプリ側の状態更新の関係、
終了処理をどこまで行えばいいのかといった
全体の構造と状態遷移を理解できていなかったこと が、
一番詰まったポイントだったと感じています。

以降は、通話状態を明示的に管理し、
終了処理を一箇所に集約することで、
同様の不具合を防げるようになりました。

📚 API連携で理解できなかったこと

API連携に関しては、Repository・Service・ViewModel といった層に分かれた構成になっていましたが、
当初はそれぞれの役割を正しく理解できていませんでした。

「なぜこの処理は Service に書くのか」
「なぜ ViewModel から直接 API を叩かないのか」
といった設計意図が分からず、
ファイルを行き来しながらコードを追うのに時間がかかっていました。

特に、APIのリクエストからレスポンスを受け取り、
画面に反映されるまでの流れを把握できていなかったため、

  • 今どの層でデータを加工しているのか
  • どこでエラーや状態を管理しているのか

が曖昧なまま実装を進めてしまっていました。

振り返ってみると、
ファイルが分かれていた理由は複雑にするためではなく、
責務を明確にし、変更に強い構造にするためだったと理解しています。

役割ごとに処理を分けて捉えるようになってからは、
API連携の流れが追いやすくなり、
他の人が書いたコードも読みやすくなりました。

🗣️ まとめ

未経験から実務のアプリ開発に入って感じたのは、
アプリ全体の構成や処理の流れを把握できているかどうかが、
実装のしやすさに大きく影響するということでした。

SwiftUI / Flutter のUI実装や、
API連携、通話SDK(Agora)といった技術自体は、
調べながらであれば部分的に実装することはできていました。
しかし、

  • この処理はどこから始まっているのか
  • どの層で何を責務として担っているのか
  • 状態はどこで管理され、どうUIに反映されているのか

といった全体像を掴めていない状態では、
コードを読んでも理解に時間がかかり、
不具合の原因特定や修正が難しくなることを実感しました。

Repository / Service / ViewModel といった構成や、
通話SDKにおける状態管理・終了処理も、
「なぜこの分け方なのか」「なぜこの流れなのか」を意識することで、
他の人が書いたコードを読み解きやすくなったと感じています。

また、Cursor や Codex などの AI エージェントを使うことで
実装スピードは向上しましたが、
任せすぎるとコードの理解が追いつかなくなる場面もありました。

設計や責務の整理は自分で行い、
AIは実装や思考を補助する役割として活用し、的確なプロンプトを投げることで
スピードと理解を両立できるようになってきたと思います。

7ヶ月経った今でも試行錯誤の途中ですが、
実装を点ではなく流れとして捉えること
そしてファイル単位で責務を意識することが、
実務コードを理解する上で重要だと感じています。