Atlas / Skills / affaan-m / Android Clean Architecture

Android Clean ArchitectureSAFE

skills/affaan-m/android-clean-architecture

The agent harness performance optimization system. Skills, instincts, memory, security, and research-first development for Claude Code, Codex, Opencode, Cursor and beyond.

Verdict
SAFE
Grade
B
Trust score
89 /100
Version
—
Hosts
—
License
MIT
Stars
262,423
01

Overview

The agent harness performance optimization system. Skills, instincts, memory, security, and research-first development for Claude Code, Codex, Opencode, Cursor and beyond.

Read from source at commit e9ca581a4f44OBSERVED · 2026-09-19
02

What it tells the agent

The instruction file, verbatim from the audited commit — this is the text the model reads, and the surface the audit's instruction layer examines. Quoted here so you can judge it without cloning anything.

---
name: android-clean-architecture
description: Android と Kotlin Multiplatform プロジェクトのクリーンアーキテクチャパターン — モジュール構造、依存関係ルール、UseCase、Repository、データ層パターン。
origin: ECC
---

# Android クリーンアーキテクチャ

Android と KMP プロジェクトのクリーンアーキテクチャパターン。モジュール境界、依存関係の逆転、UseCase/Repository パターン、Room・SQLDelight・Ktor を使用したデータ層設計をカバーします。

## 起動タイミング

- Android または KMP プロジェクトモジュールの構造化
- UseCase、Repository、DataSource の実装
- 層間のデータフロー設計(ドメイン、データ、プレゼンテーション)
- Koin または Hilt による依存性注入のセットアップ
- 層状アーキテクチャでの Room、SQLDelight、Ktor の使用

## モジュール構造

### 推奨レイアウト

```
project/
├── app/                  # Android エントリポイント、DI ワイヤリング、Application クラス
├── core/                 # 共有ユーティリティ、基底クラス、エラー型
├── domain/               # UseCase、ドメインモデル、リポジトリインターフェース(純粋 Kotlin)
├── data/                 # リポジトリ実装、DataSource、DB、ネットワーク
├── presentation/         # スクリーン、ViewModel、UI モデル、ナビゲーション
├── design-system/        # 再利用可能な Compose コンポーネント、テーマ、タイポグラフィ
└── feature/              # フィーチャーモジュール(大規模プロジェクト向けのオプション)
    ├── auth/
    ├── settings/
    └── profile/
```

### 依存関係ルール

```
app → presentation, domain, data, core
presentation → domain, design-system, core
data → domain, core
domain → core(または依存関係なし)
core → (なし)
```

**重要**: `domain` は `data`、`presentation`、またはどのフレームワークにも依存してはいけません。純粋な Kotlin のみを含みます。

## ドメイン層

### UseCase パターン

各 UseCase は 1 つのビジネス操作を表します。クリーンな呼び出しサイトのために `operator fun invoke` を使用します:

```kotlin
class GetItemsByCategoryUseCase(
    private val repository: ItemRepository
) {
    suspend operator fun invoke(category: String): Result<List<Item>> {
        return repository.getItemsByCategory(category)
    }
}

// リアクティブストリーム向けフローベースの UseCase
class ObserveUserProgressUseCase(
    private val repository: UserRepository
) {
    operator fun invoke(userId: String): Flow<UserProgress> {
        return repository.observeProgress(userId)
    }
}
```

### ドメインモデル

ドメインモデルはプレーンな Kotlin データクラス — フレームワークのアノテーションなし:

```kotlin
data class Item(
    val id: String,
    val title: String,
    val description: String,
    val tags: List<String>,
    val status: Status,
    val category: String
)

enum class Status { DRAFT, ACTIVE, ARCHIVED }
```

### リポジトリインターフェース

ドメインで定義し、データで実装する:

```kotlin
interface ItemRepository {
    suspend fun getItemsByCategory(category: String): Result<List<Item>>
    suspend fun saveItem(item: Item): Result<Unit>
    fun observeItems(): Flow<List<Item>>
}
```

## データ層

### リポジトリ実装

ローカルとリモートのデータソース間を調整する:

```kotlin
class ItemRepositoryImpl(
    private val localDataSource: ItemLocalDataSource,
    private val remoteDataSource: ItemRemoteDataSource
) : ItemRepository {

    override suspend fun getItemsByCategory(category: String): Result<List<Item>> {
        return runCatching {
            val remote = remoteDataSource.fetchItems(category)
            localDataSource.insertItems(remote.map { it.toEntity() })
            localDataSource.getItemsByCategory(category).map { it.toDomain() }
        }
    }

    override suspend fun saveItem(item: Item): Result<Unit> {
        return runCatching {
            localDataSource.insertItems(listOf(item.toEntity()))
        }
    }

    override fun observeItems(): Flow<List<Item>> {
        return localDataSource.observeAll().map { entities ->
            entities.map { it.toDomain() }
        }
    }
}
```

### マッパーパターン

マッパーはデータモデルの近くに拡張関数として保持する:

```kotlin
// データ層
fun ItemEntity.toDomain() = Item(
    id = id,
    title = title,
    description = description,
    tags = tags.split("|"),
    status = Status.valueOf(status),
    category = category
)

fun ItemDto.toEntity() = ItemEntity(
    id = id,
    title = title,
    description = description,
    tags = tags.joinToString("|"),
    status = status,
    category = category
)
```

### Room データベース(Android)

```kotlin
@Entity(tableName = "items")
data class ItemEntity(
    @PrimaryKey val id: String,
    val title: String,
    val description: String,
    val tags: String,
    val status: String,
    val category: String
)

@Dao
interface ItemDao {
    @Query("SELECT * FROM items WHERE category = :category")
    suspend fun getByCategory(category: String): List<ItemEntity>

    @Upsert
    suspend fun upsert(items: List<ItemEntity>)

    @Query("SELECT * FROM items")
    fun observeAll(): Flow<List<ItemEntity>>
}
```

### SQLDelight(KMP)

```sql
-- Item.sq
CREATE TABLE ItemEntity (
    id TEXT NOT NULL PRIMARY KEY,
    title TEXT NOT NULL,
    description TEXT NOT NULL,
    tags TEXT NOT NULL,
    status TEXT NOT NULL,
    category TEXT NOT NULL
);

getByCategory:
SELECT * FROM ItemEntity WHERE category = ?;

upsert:
INSERT OR REPLACE INTO ItemEntity (id, title, description, tags, status, category)
VALUES (?, ?, ?, ?, ?, ?);

observeAll:
SELECT * FROM ItemEntity;
```

### Ktor ネットワーククライアント(KMP)

```kotlin
class ItemRemoteDataSource(private val client: HttpClient) {

    suspend fun fetchItems(category: String): List<ItemDto> {
        return client.get("api/items") {
            parameter("category", category)
        }.body()
    }
}

// コンテントネゴシエーション付き HttpClient セットアップ
val httpClient = HttpClient {
    install(ContentNegotiation) { json(Json { ignoreUnknownKeys = true }) }
    install(Logging) { level = LogLevel.HEADERS }
    defaultRequest { url("https://api.example.com/") }
}
```

## 依存性注入

### Koin(KMP フレンドリー)

```kotlin
// ドメインモジュール
val domainModule = module {
    factory { GetItemsByCategoryUseCase(get()) }
    factory { ObserveUserProgressUseCase(get()) }
}

// データモジュール
val dataModule = module {
    single<ItemRepository> { ItemRepositoryImpl(get(), get()) }
    single { ItemLocalDataSource(get()) }
    single { ItemRemoteDataSource(get()) }
}

// プレゼンテーションモジュール
val presentationModule = module {
    viewModelOf(::ItemListViewModel)
    viewModelOf(::DashboardViewModel)
}
```

### Hilt(Android のみ)

```kotlin
@Module
@InstallIn(SingletonComponent::class)
abstract class RepositoryModule {
    @Binds
    abstract fun bindItemRepository(impl: ItemRepositoryImpl): ItemRepository
}

@HiltViewModel
class ItemListViewM
03

Trust audit

SAFEgrade B · trust 89/100 Nothing in the source contradicts what it says it does. Grade A is reserved for packages that have also passed the behavioural sandbox.

LayerWhat it checksResult
L0Provenance & inventoryPASS
L1Static analysis of the codeNA
L2Instruction surface (what it tells the agent)PASS
L3Class-specific surfacePASS
L4Behavioural (sandbox)SKIPPED

What the source does

Filesystem
none-observed
Network
none-observed
Shell
none-observed
Dependencies
pinned
Secrets in source
none-found

Findings (0)

No findings outside the package's declared scope.

Gates applied: no_behavioural_pass.

Audited 2026-09-19 · audit v0.4.1 · source sha e9ca581a4f44full audit observations/trust-audit/skill/affaan-m__android-clean-architecture.json · Report an issue / request a re-scan
04

Audit history

Every audit this skill has had.

DateSourceVerdictGradeScoreChange
2026-09-19e9ca581a4f44SAFEB89first audit
05

Questions

What does the Android Clean Architecture skill do?

The agent harness performance optimization system. Skills, instincts, memory, security, and research-first development for Claude Code, Codex, Opencode, Cursor and beyond.

Is Android Clean Architecture safe to install?

The audit found nothing in the source that contradicts what it says it does, and graded it B (89/100). Grade A is held back for packages that have also passed a sandboxed behavioural run, which is why a clean skill reads B.

What can Android Clean Architecture access on my machine?

The audit observed no filesystem, network or shell use at all in its source.

How current is this page?

The grade is for one exact copy of the source (e9ca581a4f44), read on 2026-09-19. The repository is watched, and a new audit runs when it changes — this is the first audit.

Advertisement