※ChatGPTを使用して記事を作成しています。
「完璧なアーキテクチャを作ろう」
──そう言い出したのは、チームの誰でもない。私自身だった。
クリーンアーキテクチャ、MVVM、UseCase分離、Repository層、DI…。
教科書通りの“理想の設計”を目指したはずが、いつしか誰も手を動かせない構造になっていた。
今回は、設計を信じすぎて開発が止まった話をしたい。
理想への憧れが始まりだった
Android開発歴10年以上。数多くの失敗を経て、私は「設計さえ正しければ、開発はスムーズに進む」と信じていた。
そこで、ある新規プロジェクトでこう提案した。
「今回はクリーンアーキテクチャでいこう。ViewModelはUIだけ、UseCaseでロジックを切り出して、Repositoryでデータを抽象化する。」
チームメンバーも賛同してくれた。
見た目は整然とした構造図。依存関係の流れも美しい。
その時点では、完璧な設計に見えた。
しかし──理想を追いすぎた設計は、やがて自分たちを縛る檻になっていった。
クリーンすぎて動かない
初期の実装はこうだった。
// UseCase層
class GetUserProfileUseCase(
private val repository: UserRepository
) {
suspend operator fun invoke(userId: String): Result<User> {
return repository.getUserProfile(userId)
}
}
// Repository層
interface UserRepository {
suspend fun getUserProfile(userId: String): Result<User>
}
// 実装
class UserRepositoryImpl(
private val remoteDataSource: UserRemoteDataSource,
private val localDataSource: UserLocalDataSource,
) : UserRepository {
override suspend fun getUserProfile(userId: String): Result<User> {
return remoteDataSource.getUserProfile(userId)
}
}
完璧に見える。
だが、これを何十個も実装し始めると話が変わってくる。
- UseCaseが大量発生してフォルダが肥大化
- Repositoryも抽象・実装のペアで倍増
- メソッドを1つ追加するたびに4ファイルを修正
リファクタリングが怖くなり、「小さな変更をするだけでもPRがでかくなる」状態に。
まるで設計そのものが作業効率を奪っていた。
チームが設計に縛られた瞬間
ある日、若手メンバーが「新しいAPI対応を追加したい」と言った。
だが、その修正には UseCase、Repository、DataSource の3層に手を入れねばならなかった。
その結果、レビューコメントが飛び交った。
「UseCase名が不適切」
「Repositoryは抽象化されすぎ」
「この責務はDomainではなくDataでは?」
気づけば議論の大半が“設計論”になっていた。
本来の目的である「機能を早く届ける」が、どこかに消えていた。
現場で起きた副作用
開発が進むにつれて、別の問題も出てきた。
- 画面ごとに似たようなUseCaseが乱立
- 同じ処理でも層をまたぐためにデバッグが困難
- 新メンバーが構造を理解するまで数日かかる
- 単体テストは書けるが、結合テストが破綻
とくに痛感したのは、「現場では完璧より、理解しやすい構造のほうが価値がある」ということだった。
“目的”を見失った設計の危険性
あるとき、ふと我に返った。
「そもそも、なぜクリーンアーキテクチャにしたんだっけ?」
答えは、「保守しやすくするため」だった。
でも現実はその逆。
変更コストは倍増し、スピードは半減。
設計が「目的」ではなく「宗教」になっていた。
いつの間にか、設計のために設計していたのだ。
現実的な落とし所:80点の設計でいい
その後、私は思い切って設計を見直した。
全層構造を保ちながらも、ルールを柔軟にした。
- Repositoryは必要なときだけ抽象化
- 小規模画面はViewModel内で完結してOK
- UseCaseは共通ロジックのみ定義
- テスト容易性よりも「理解しやすさ」を優先
結果、コード量が約20%削減。
チームのレビュー時間も大幅に短縮した。
重要なのは、「100点を目指さず、80点で走り続ける設計」に切り替えたことだ。
動いて改善できるコードこそ、本当に“クリーン”な設計だと気づいた。
教訓:設計は地図であって目的地ではない
- クリーンアーキテクチャは手段であって正解ではない
- 理想の構造を守るより、「誰でも理解できるコード」が強い
- 現場の状況に合わせて“崩す勇気”を持つ
- 設計は「守るため」ではなく「進めるため」にある
アーキテクチャとは、チームの成長に合わせて変わる生き物だ。
最初に決めた形を守ることが目的になった瞬間、開発は止まる。
柔軟でいることこそ、エンジニアとしての成熟だと思う。
エピローグ
振り返れば、この「Android開発失敗談」シリーズは、自分の10数年の試行錯誤をそのまま記録したようなものだった。
Jetpack Composeの無限リコンポーズも、WorkManagerの闇も、Fragmentのライフサイクルの罠も──
結局は「理解したつもり」でいた自分が招いた結果だった。
でも、失敗したからこそ学べた。
そして、同じ失敗を繰り返さないように書き残すことが、次の世代のエンジニアへの“恩返し”になると思っている。

