AIが書いたコードは静かにアプリを壊す — “動く”ことに満足した開発の行き着く先 —

 

🧑🏻‍💻 1. 「動くコード」を生み出すAIの魔法と、その落とし穴

最近の開発現場では、「AIにコードを書かせる」のが当たり前になってきた。
ChatGPTやGitHub Copilotに「○○を実装して」と伝えれば、数秒で動くコードを出してくれる。
それをコピーして貼り付ければ、ビルドも通り、アプリも動く。
——まるで魔法のようだ。

けれど、実はこの“動くコード”こそがアプリを静かに壊していく。
なぜなら、そのコードは「なぜ動くのか」を誰も理解していないからだ。
AIは文脈を「設計思想」ではなく「統計的パターン」で捉える。
だから動作優先で、構造や責務を無視したコードを出すことがある。

その結果、「とりあえず動いたからOK」というコードが少しずつ積み上がる。
数カ月後、いざ修正しようとしたとき、
「この処理、誰がどうしてこう書いたんだっけ?」
——誰も答えられない。
そんな“ブラックボックス化”が静かに進んでいく。

 

🧑🏻‍💻 2. 小さな歪みが積もって、アプリの寿命を縮める

AIが生成するコードは、局所的には正しい。
しかし全体で見れば、設計のバランスを壊していることが多い。

たとえばMVVM構造のアプリで、AIが「便利なショートカット」としてUI層から直接データベースにアクセスするようなコードを出す。
確かに動く。けれど、これは明確に“構造違反”だ。
一見問題ないように見えても、
こうした「小さな歪み」が何十箇所も積み重なると、アプリは急速に脆くなる。

特にAIは“最短距離”で解決しようとする。
テストやエラーハンドリングは省かれ、
依存ライブラリも無自覚に増える。
それでも最初は動くため、気づかない。
だが、ある日突然ビルドが通らなくなったり、
AndroidやiOSのバージョン更新で全体が壊れたりする。

原因を追っても、「どこから手をつければいいのか」が分からない。
AIが生み出した“つぎはぎ構造”が、まるで崩れかけた積み木のように、
どこを直しても全体がぐらつく。
——それが「AIがアプリの寿命を縮める」という現象の正体だ。

 

🧑🏻‍💻 3. AIと共存するために、設計を“守る人間”が必要になる

AIを完全に排除することは現実的ではない。
むしろ、うまく使えば開発効率は飛躍的に上がる。
問題は、「AIに書かせたあとをどう扱うか」だ。

たとえば、AIに出させたコードは必ずレビューする。
一人開発でも“レビュー時間”を意識的に取る。
「動くかどうか」ではなく、「構造的に正しいか」を基準に見る。
さらに、AIへの指示(プロンプト)も工夫する。
「なぜこの方法なのか」「設計上のリスクは?」と質問を加えるだけで、
AIの出力品質は大きく変わる。

AIはあくまで“補助輪”だ。
自転車を前に進ませることはできても、
どの道を走るべきかまでは決めてくれない。

これからのエンジニアは、
AIを“使う人”ではなく“指揮する人”になる必要がある。
AIの力で速く動く一方で、
人間が「構造を守るブレーキ役」を担う。
そのバランスこそが、アプリを長生きさせる秘訣だ。

 

🧑🏻‍💻 まとめ:AIは便利な酸素、でも吸いすぎると毒になる

AIは開発のスピードを何倍にも引き上げる。
しかし、構造を無視したまま使えば、
そのスピードでアプリの寿命を削り取る。

“動く”ことだけをゴールにしてしまうと、
“生き続ける”ための土台が壊れていく。

AIが生み出すコードは、確かに速く、便利で、魅力的だ。
でも、それを理解し、守り、磨き続けるのは人間の役割だ。
アプリの未来は、AIの性能ではなく、
それを正しく使う開発者の構造への愛情にかかっている。


Jetpack Compose 1.7+ でクリップボードコピーをどう書く?

 

🧑🏻‍💻 LocalClipboard と suspend 関数の組み合わせ

Compose 1.7 以降では、従来の ClipboardManager が非推奨になり、代わりに LocalClipboard + 非同期コピー が公式に推奨されています。

以下はシンプルなサンプルです。rememberCoroutineScope を使い、クリックイベントで非同期コピーを行っています。


val clipboard = LocalClipboard.current
val scope = rememberCoroutineScope()

Box(modifier = Modifier.clickable {
    scope.launch {
        val clipData = ClipData.newPlainText(uuid, uuid)
        clipboard.setClipEntry(clipData.toClipEntry())
    }
})

👉 Jason Ernst: Android ClipboardManager Deprecated: How to fix

 

🧑🏻‍💻 ViewModel 側でコピー処理をまとめる

世界的に著名な Android 開発者 Chris Banes や Jake Wharton のサンプルコードでは、UI 層から直接 Clipboard を操作せず、ViewModel に処理をまとめる パターンが多く見られます。

このアプローチを取ることで、UI の再コンポーズと Clipboard 操作が分離でき、よりテストしやすい設計になります。


class NoteViewModel : ViewModel() {
  fun copy(block: suspend () -> Unit) {
    viewModelScope.launch {
      block()
    }
  }
}

UI 側では以下のように呼び出せます:


IconButton(
  onClick = { 
    viewModel.copy {
      clipboard.setText(item.text)
    }
  }
) {
  Icon(Icons.Default.ContentCopy, contentDescription = null)
}

Clipboard 拡張関数を定義しておくと便利です。


suspend fun Clipboard.setText(text: String) { 
    val clipData = ClipData.newPlainText(text, text).toClipEntry() 
    setClipEntry(clipData)
}

 

🧑🏻‍💻 まとめ

ClipboardManager は非推奨 → LocalClipboard + suspend が公式推奨。

UI 層はイベントを投げるだけ、コピー処理は ViewModel で完結。

Coroutine scope を ViewModel 内で扱うことで UI の再コンポーズに影響しない。

ViewModel が clipboard を直接握るのは避けたほうがベター。
(非 UI 層に UI 依存を持ち込むことになるため)

拡張関数で共通処理化すれば再利用性が高まる。

つまり、

「UI はシンプルに」「コピー処理は ViewModel に集約」

これが現代的な Compose + Clipboard のベストプラクティスです。


【macOS】「Toggle Sticky Selection」を設定したい!

JetBrains系IDE(Android Studio、IntelliJ IDEA、PyCharm、WebStorm など)では、「Sticky Selection(固定選択)」という便利なモードがあります。これは、カーソルを移動するだけでテキスト選択を継続できるモードで、範囲選択を効率化できます。

通常は「Toggle Sticky Selection」にショートカットを割り当てて使いますが、デフォルトでは設定されていないため、手動でキーを割り当てる必要があります。たとえば、筆者は Control + Space に割り当てようとしました。しかし、ここで問題が発生しました。

 

🤔 Control + Space を設定しようとすると、IMEが切り替わってしまう

ショートカット設定画面で「Toggle Sticky Selection」に Control + Space を登録しようとすると、なぜか入力欄が反応せず、MacのIME(日本語入力)が英語に切り替わってしまいます。

つまり、IDEのエディタがそのキー入力をキャッチする前に、macOSのシステムが先に反応してしまっているのです。

これは macOS のデフォルト設定で、Control + Space は「入力ソースの切り替え」に使われているからです。Macで複数の言語(たとえば日本語と英語)を切り替えている人にはおなじみのショートカットですね。

このままでは、IDEエディタ側でショートカット登録ができません。そこで、macOS側の設定を変更する必要があります。

 

🤔 macOSのショートカット設定を変更して回避する

macOS のシステム環境設定から、ショートカットの競合を解消しましょう。


1.「システム設定」アプリを開く

2. サイドバーから 「キーボード」 を選択

3. 右側にある 「キーボードショートカット…」 をクリック

4. サイドメニューから 「入力ソース」 を選択

5. 「前の入力ソースを選択」 に割り当てられている ^ スペース(Control + Space) をクリック

表示されたチェックを外す、もしくは他のショートカットに変更

これで macOS 側が Control + Space を使わなくなるため、IDE側の設定画面で正しくこのキーを登録できるようになります。

 

🤔 無事にショートカット登録が可能に!あとは設定するだけ

macOS 側の干渉がなくなれば、IDE側の設定画面で Control + Space を「Toggle Sticky Selection」に自由に割り当てられるようになります。


1. IDE の「設定(Preferences)」を開く

2. Keymap(キーマップ) を選択

3. 検索バーに「Sticky Selection」と入力

4. 「Toggle Sticky Selection」を右クリック → Add Keyboard Shortcut

5. Control + Space を入力 → OK

設定後、エディタ上で Control + Space を押すと Sticky Selection モードに入り、矢印キーなどでカーソルを動かすたびに選択範囲が伸びていくことを確認できます。

 

🧑🏻‍💻 まとめ:macOSの干渉を避ければ自由にカスタムできる

Control + Space は便利なショートカットですが、macOS のデフォルト設定でIME切り替えに使われているため、IDEのエディタではそのままでは登録できません。

しかし、macOS の「キーボードショートカット」設定から「入力ソースの切り替え」を無効化または変更すれば、競合を回避できます。

この一手間を加えることで、自分の作業スタイルにあったショートカット環境が整います。エディタをもっと快適に使うためにも、こうした細かい調整はぜひ試してみてください 🎉