kotlin – skill Lập trình cho agent AI
Hướng dẫn super-code theo ngôn ngữ cho Kotlin.
Cài skill kotlin bằng một lệnh
Chọn công cụ bạn đang dùng, copy lệnh và dán vào terminal. Skill sẽ nằm trong thư mục skills của công cụ đó và sẵn sàng dùng ở phiên làm việc tiếp theo.
Claude Code
mkdir -p ~/.claude/skills && curl -fsSL https://skill.dn1nguoi.com/z/kotlin-414b7.tgz | tar xz -C ~/.claude/skills
Gọi trong Claude Code: /kotlin – rồi mô tả công việc bạn muốn làm.
Codex
mkdir -p ~/.codex/skills && curl -fsSL https://skill.dn1nguoi.com/z/kotlin-414b7.tgz | tar xz -C ~/.codex/skills
Gọi trong Codex: $kotlin – rồi mô tả công việc bạn muốn làm.
Hermes Agent
mkdir -p ~/.hermes/skills && curl -fsSL https://skill.dn1nguoi.com/z/kotlin-414b7.tgz | tar xz -C ~/.hermes/skills
Gọi trong Hermes Agent: /kotlin – rồi mô tả công việc bạn muốn làm.
DeepSeek
mkdir -p ~/.deepcode/skills && curl -fsSL https://skill.dn1nguoi.com/z/kotlin-414b7.tgz | tar xz -C ~/.deepcode/skills
Gọi trong DeepSeek: /kotlin – rồi mô tả công việc bạn muốn làm.
Nội dung SKILL.md
Nội dung SKILL.md gốc bằng tiếng Anh.
Kotlin + Compose: Idiomatic Efficiency Reference
Apply only within the requested scope and current project conventions. Preserve behavior, ownership, error handling, accessibility and security; examples are independent fragments, not equivalent rewrites in every context. Verify language/library versions and run relevant checks. Required tests and user-facing progress/results take precedence over brevity rules. Do not install dependencies or delete files merely to follow these examples.
When to Use
- Use this skill when the task matches this description: Language-specific super-code guidelines for kotlin.
Table of Contents
1. [Collections & Data Transformation](#collections)
2. [Null Safety](#null-safety)
3. [Functions & Lambdas](#functions)
4. [Classes & Objects](#classes)
5. [Coroutines & Flow](#coroutines)
6. [Compose UI](#compose)
7. [Anti-patterns specific to Kotlin](#antipatterns)
---
1. Collections & Data Transformation {#collections}
Prefer scope functions and stdlib transforms over imperative loops.
// ❌ Verbose
val result = mutableListOf<String>()
for (item in items) {
if (item.isActive) {
result.add(item.name.uppercase())
}
}
// ✅ Idiomatic
val result = items.filter { it.isActive }.map { it.name.uppercase() }// ❌ Manual grouping
val map = mutableMapOf<String, MutableList<Item>>()
for (item in items) {
map.getOrPut(item.category) { mutableListOf() }.add(item)
}
// ✅
val map = items.groupBy { it.category }// ❌ Manual fold
var total = 0
for (order in orders) total += order.amount
// ✅
val total = orders.sumOf { it.amount }Use associate, associateBy, partition, flatMap, zip instead of manual equivalents.
---
2. Null Safety {#null-safety}
// ❌ Unnecessary null check when Elvis suffices
val name: String
if (user?.name != null) {
name = user.name
} else {
name = "Guest"
}
// ✅
val name = user?.name ?: "Guest"// ❌ Double null check
if (response != null && response.body != null) {
process(response.body!!)
}
// ✅
response?.body?.let { process(it) }// ❌ !! without guard
val value = nullable!!.doSomething()
// ✅ Make the non-null contract explicit at the boundary
val value = requireNotNull(nullable) { "nullable must be set before calling X" }.doSomething()
// Or return early:
val n = nullable ?: return---
3. Functions & Lambdas {#functions}
// ❌ Single-expression function with unnecessary block body
fun double(x: Int): Int {
return x * 2
}
// ✅
fun double(x: Int) = x * 2// ❌ Lambda capturing unused parameter
items.forEach { item -> doSomething() }
// ✅
items.forEach { doSomething() }// ❌ Redundant with/apply nesting
val builder = Builder()
builder.setName("x")
builder.setAge(1)
val result = builder.build()
// ✅
val result = Builder().apply {
setName("x")
setAge(1)
}.build()Prefer let, run, apply, also, with over repeated receiver references — but don't nest more than 2 levels deep.
---
4. Classes & Objects {#classes}
// ❌ Mutable class for immutable data
class Point {
var x: Int = 0
var y: Int = 0
}
// ✅
data class Point(val x: Int, val y: Int)// ❌ Companion object just to hold a constant
class Foo {
companion object {
val TAG = "Foo"
}
}
// ✅ — top-level if only used in this file
private const val TAG = "Foo"
class Foo// ❌ Enum with when that has to be updated in two places
enum class Status { ACTIVE, INACTIVE }
fun label(s: Status) = when(s) { Status.ACTIVE -> "Active"; Status.INACTIVE -> "Inactive" }
// ✅ — put display logic on the enum itself
enum class Status(val label: String) { ACTIVE("Active"), INACTIVE("Inactive") }Sealed classes/interfaces over enum when variants carry different data.
---
5. Coroutines & Flow {#coroutines}
// ❌ Unnecessary async/await pair when result is used immediately
val result = async { fetchData() }.await()
// ✅
val result = fetchData() // just suspend fun, no async needed// ❌ Collecting in a loop
while (true) {
val value = channel.receive()
process(value)
}
// ✅
channel.consumeEach { process(it) }
// or for Flow:
flow.collect { process(it) }// ❌ StateFlow + manual emit boilerplate
private val _state = MutableStateFlow(initial)
val state: StateFlow<State> = _state
// ... in many places: _state.value = newValue
// ✅ — use update{} for atomic mutation
_state.update { it.copy(field = newValue) }Don't launch coroutines in constructors or init blocks. Don't use GlobalScope.
---
6. Compose UI {#compose}
// ❌ Unnecessary remember for derived state that's cheap to compute
val displayName = remember { user.firstName + " " + user.lastName }
// ✅ — only remember if computation is expensive or involves object creation
val displayName = "${user.firstName} ${user.lastName}"// ❌ Passing entire state object when composable only needs one field
@Composable
fun UserBadge(user: User) { Text(user.name) }
// ✅ — pass only what's needed (stability + minimal recomposition)
@Composable
fun UserBadge(name: String) { Text(name) }// ❌ Inline click handler lambda (creates new instance each recomposition)
Button(onClick = { viewModel.onSave() }) { ... }
// ✅
val onSave = remember(viewModel) { { viewModel.onSave() } }
Button(onClick = onSave) { ... }
// Or pass it down as a parameter already// ❌ Nested Column/Row just to group children
Column {
Column {
Text("a")
Text("b")
}
}
// ✅
Column {
Text("a")
Text("b")
}Use LazyColumn/LazyRow for lists of unknown or large size. Never put a LazyColumn inside a Column with unbounded height.
---
7. Anti-patterns specific to Kotlin {#antipatterns}
| Anti-pattern | Preferred |
|---|---|
| if (x == true) | if (x) |
| if (x == null) return else x!! | val x = x ?: return |
| listOf().toMutableList() for a known-size list | mutableListOf() |
| when with a single branch and else | if/else |
| .toString() on a string | remove it |
| Explicit Unit return type on functions | omit (inferred) |
| object : Runnable { override fun run() { ... } } | Runnable { ... } (SAM) |
| @JvmStatic in pure Kotlin code | only needed for Java interop |
| Wrapping every function in try/catch to log | handle at the boundary, not inside |
Limitations
- These are language-specific guidelines and do not cover overall architectural decisions.
- Over-compression might reduce readability; apply judgement.
Skill liên quan
- kotlin-coroutines-expert – Các mẫu chuyên sâu về Kotlin Coroutines và Flow, bao gồm structured concurrency, xử lý…
- vendor-management – Dùng khi xem xét, chấm điểm hoặc kiểm toán quan hệ với nhà cung cấp SaaS/bên thứ ba…
- langchain-architecture – Làm chủ framework LangChain để xây dựng ứng dụng LLM phức tạp với agent, chain, memory…
- vpe-review – /c-level-agents:vpe-review [plan] — Rà soát kế hoạch ưu tiên thông lượng của VP of…
- learn – Giúp người dùng học một chủ đề qua kèm cặp thích ứng, lập kế hoạch bài học, luyện tập…
- legacy-modernizer – Tái cấu trúc mã nguồn cũ, di chuyển framework lỗi thời và triển khai hiện đại hóa từng…
- leiloeiro-avaliacao – Tổ chức bằng chứng và các kịch bản định giá tham khảo cho bất động sản đấu giá, với giới…
- weekly-review – Dùng khi ai đó muốn chạy đánh giá hàng tuần, khép các việc còn mở, rà soát dự án và cam…