SiamCafe.net Blog
Technology

Kotlin Coroutines Team Productivity

kotlin coroutines team productivity
Kotlin Coroutines Team Productivity | SiamCafe Blog
2026-04-07· อ. บอม — SiamCafe.net· 9,787 คำ

Kotlin Coroutines Productivity

Kotlin Coroutines Team Productivity Async Structured Concurrency Flow StateFlow Testing suspend CoroutineScope Production

FeatureCoroutinesRxJavaCallback
Readabilityเหมือน Sync CodeChain operatorsNested callbacks
Error Handlingtry-catch ปกติonError operatorError callback
CancellationStructured (อัตโนมัติ)Disposable (manual)Manual flag
TestingrunTest + TestDispatcherTestSchedulerยาก
Learning Curveต่ำ (คล้าย Sync)สูง (operators มาก)ต่ำ แต่ซับซ้อนเร็ว
BackpressureFlow (built-in)Flowableไม่มี

Coroutines Fundamentals

# === Kotlin Coroutines ===

# // Basic coroutine builders
# import kotlinx.coroutines.*
#
# fun main() = runBlocking {
#     // launch: Fire-and-forget
#     val job = launch {
#         delay(1000)
#         println("World!")
#     }
#     println("Hello,")
#     job.join()
#
#     // async: Return value
#     val deferred = async {
#         fetchUserFromAPI()
#     }
#     val user = deferred.await()
#
#     // Parallel execution
#     val (user, orders) = coroutineScope {
#         val userDeferred = async { fetchUser(userId) }
#         val ordersDeferred = async { fetchOrders(userId) }
#         Pair(userDeferred.await(), ordersDeferred.await())
#     }
#
#     // withContext: Switch dispatcher
#     val result = withContext(Dispatchers.IO) {
#         database.query("SELECT * FROM users")
#     }
# }
#
# // suspend function
# suspend fun fetchUser(id: String): User {
#     return withContext(Dispatchers.IO) {
#         apiClient.get("/users/$id")
#     }
# }
#
# // Structured Concurrency
# suspend fun processOrder(orderId: String) = coroutineScope {
#     val payment = async { processPayment(orderId) }
#     val inventory = async { updateInventory(orderId) }
#     val notification = async { sendNotification(orderId) }
#     // If any fails, all are cancelled automatically
#     Triple(payment.await(), inventory.await(), notification.await())
# }

from dataclasses import dataclass

@dataclass
class CoroutineBuilder:
    builder: str
    returns: str
    use_case: str
    cancellation: str
    example: str

builders = [
    CoroutineBuilder("launch",
        "Job (ไม่มี Return Value)",
        "Fire-and-forget เช่น Log Analytics UI Update",
        "Cancel ผ่าน job.cancel()",
        "launch { sendAnalytics(event) }"),
    CoroutineBuilder("async",
        "Deferred (Return Value)",
        "Parallel execution รอผลลัพธ์",
        "Cancel ผ่าน deferred.cancel()",
        "val user = async { fetchUser() }.await()"),
    CoroutineBuilder("withContext",
        "T (Return Value, switch context)",
        "สลับ Dispatcher เช่น IO → Main",
        "Cancel ตาม Parent Scope",
        "withContext(IO) { db.query() }"),
    CoroutineBuilder("coroutineScope",
        "T (Structured scope)",
        "กลุ่ม Coroutines ที่ต้อง Cancel ด้วยกัน",
        "Cancel ทั้งหมดเมื่อ 1 ตัว Fail",
        "coroutineScope { async{} + async{} }"),
    CoroutineBuilder("runBlocking",
        "T (Block current thread)",
        "Main function, Test only อย่าใช้ใน Production",
        "Block Thread จริงๆ",
        "fun main() = runBlocking { ... }"),
]

print("=== Coroutine Builders ===")
for b in builders:
    print(f"  [{b.builder}] Returns: {b.returns}")
    print(f"    Use: {b.use_case}")
    print(f"    Cancel: {b.cancellation}")
    print(f"    Example: {b.example}")

Flow Patterns

# === Kotlin Flow ===

# // StateFlow (State Management)
# class UserViewModel : ViewModel() {
#     private val _uiState = MutableStateFlow(UiState.Loading)
#     val uiState: StateFlow = _uiState.asStateFlow()
#
#     fun loadUser(id: String) {
#         viewModelScope.launch {
#             _uiState.value = UiState.Loading
#             try {
#                 val user = repository.fetchUser(id)
#                 _uiState.value = UiState.Success(user)
#             } catch (e: Exception) {
#                 _uiState.value = UiState.Error(e.message)
#             }
#         }
#     }
# }
#
# // Flow operators
# repository.getUsers()
#     .map { users -> users.filter { it.isActive } }
#     .distinctUntilChanged()
#     .debounce(300)
#     .flowOn(Dispatchers.Default)
#     .catch { e -> emit(emptyList()) }
#     .onCompletion { println("Done") }
#     .collect { activeUsers -> updateUI(activeUsers) }
#
# // SharedFlow (Events)
# class EventBus {
#     private val _events = MutableSharedFlow()
#     val events: SharedFlow = _events.asSharedFlow()
#     suspend fun emit(event: Event) = _events.emit(event)
# }

@dataclass
class FlowType:
    type_: str
    behavior: str
    replay: str
    use_case: str
    alternative: str

flows = [
    FlowType("Flow (Cold)",
        "สร้างใหม่ทุกครั้งที่ collect ไม่เก็บค่า",
        "ไม่มี", "API Call, Database Query, File Read",
        "RxJava Observable"),
    FlowType("StateFlow (Hot)",
        "เก็บค่าล่าสุดเสมอ Emit ค่าใหม่เมื่อเปลี่ยน",
        "1 (ค่าล่าสุด)", "UI State, Configuration, Settings",
        "LiveData, BehaviorSubject"),
    FlowType("SharedFlow (Hot)",
        "Broadcast Event ให้หลาย Collector",
        "กำหนดเอง (0, 1, N)", "Event Bus, Navigation, Toast/Snackbar",
        "PublishSubject, EventBus"),
]

print("=== Flow Types ===")
for f in flows:
    print(f"  [{f.type_}] {f.behavior}")
    print(f"    Replay: {f.replay}")
    print(f"    Use: {f.use_case}")
    print(f"    Alt: {f.alternative}")

Testing

# === Coroutine Testing ===

# // Test suspend function
# @Test
# fun `fetchUser returns correct user`() = runTest {
#     val repo = UserRepository(FakeApiClient())
#     val user = repo.fetchUser("123")
#     assertEquals("John", user.name)
# }
#
# // Test Flow with Turbine
# @Test
# fun `uiState emits loading then success`() = runTest {
#     val viewModel = UserViewModel(FakeRepository())
#     viewModel.uiState.test {
#         assertEquals(UiState.Loading, awaitItem())
#         viewModel.loadUser("123")
#         assertEquals(UiState.Loading, awaitItem())
#         assertEquals(UiState.Success(testUser), awaitItem())
#         cancelAndIgnoreRemainingEvents()
#     }
# }
#
# // Test with delay
# @Test
# fun `debounced search works`() = runTest {
#     val viewModel = SearchViewModel()
#     viewModel.search("kot")
#     advanceTimeBy(200) // ยังไม่ถึง debounce 300ms
#     assertEquals(emptyList(), viewModel.results.value)
#     advanceTimeBy(200) // ผ่าน 300ms แล้ว
#     assertEquals(listOf("kotlin"), viewModel.results.value)
# }

@dataclass
class TestTool:
    tool: str
    purpose: str
    api: str
    example: str

tools = [
    TestTool("runTest",
        "รัน Test ที่มี suspend function",
        "runTest { ... }",
        "runTest { val result = repo.fetch(); assert(result) }"),
    TestTool("TestDispatcher",
        "Control Dispatcher ใน Test ควบคุมเวลา",
        "StandardTestDispatcher / UnconfinedTestDispatcher",
        "Dispatchers.setMain(testDispatcher)"),
    TestTool("advanceTimeBy",
        "ข้ามเวลาใน Test ไม่ต้องรอ delay จริง",
        "advanceTimeBy(1000)",
        "viewModel.search(); advanceTimeBy(300)"),
    TestTool("Turbine",
        "Test Flow ง่ายมาก await แต่ละ emission",
        "flow.test { awaitItem(); awaitComplete() }",
        "stateFlow.test { assertEquals(Loading, awaitItem()) }"),
    TestTool("Mockk coEvery",
        "Mock suspend function",
        "coEvery { repo.fetchUser(any()) } returns testUser",
        "coVerify { repo.fetchUser(\"123\") }"),
]

print("=== Testing Tools ===")
for t in tools:
    print(f"  [{t.tool}] {t.purpose}")
    print(f"    API: {t.api}")
    print(f"    Example: {t.example}")

เคล็ดลับ

Kotlin Coroutines คืออะไร

Async Code suspend function CoroutineScope launch async withContext Flow Structured Concurrency Cancel Android Ktor Spring Boot

ช่วยเพิ่ม Productivity อย่างไร

อ่านง่าย ลด Bug Race Condition Test ง่าย runTest ลดเวลาเขียน 30-50% Error try-catch Cancel อัตโนมัติ เรียนรู้เร็ว IDE Debug

Flow คืออะไร

Cold Async Stream emit collect map filter StateFlow State Management SharedFlow Event Broadcasting flowOn catch onCompletion Operator

Testing ทำอย่างไร

runTest TestDispatcher advanceTimeBy Turbine Flow awaitItem awaitComplete Mockk coEvery coVerify suspend function UnconfinedTestDispatcher

สรุป

Kotlin Coroutines Team Productivity suspend launch async Flow StateFlow Structured Concurrency Testing runTest Turbine Production

📖 บทความที่เกี่ยวข้อง

Docker Multi-stage Build Team Productivityอ่านบทความ → Kotlin Coroutines Pod Schedulingอ่านบทความ → SigNoz Observability Team Productivityอ่านบทความ → Kotlin Coroutines CQRS Event Sourcingอ่านบทความ → AWS App Runner Team Productivityอ่านบทความ →

📚 ดูบทความทั้งหมด →