早晨不是从咖啡开始,而是从合并请求开始
\n\n早上 7:45。手机震动——不是闹钟,而是 GitLab 发来通知:你昨天的合并请求通过了 CI/CD 流水线。在水壶烧开的同时,我打开笔记本电脑,看到了绿色的勾号。今天的第一场胜利。早上好,Kotlin。
\n\n我叫阿列克谢,是一家产品公司的 Kotlin 开发者。过去三年,我使用 Kotlin 开发 Android 应用,也偶尔用 Ktor 写后端。如果你认为程序员的工作就是永无止境的“Hello World”,那么今天我将打破这个神话。欢迎来到我真实的工作日。
\n\n8:30 —— 每日站会:同步与上下文
\n\n第一件事是每日站会。我们在 Zoom 上开会,但没有多余的“昨天-今天-问题”。我们很简洁:完成了什么,计划做什么,是否有阻塞。今天我负责为用户开发 推送通知 功能。
\n\n——昨天完成了 NotificationService 的重构,用协程重写了代码。今天我要接入 Firebase Cloud Messaging 并测试 Flow。没有阻塞。
顺便说一句,许多最佳架构想法正是在站会上诞生的。例如,上周一位同事建议用 Kotlin Flow 替换 RxJava —— 我们因此减少了 40% 的样板代码。现在看起来是这样的:
\n\n// 代替旧的 RxJava:\n// Observable.just(data).subscribeOn(Schedulers.io())\n\n// 使用 Kotlin Flow:\nfun observeNotifications(): Flow<Notification> = flow {\n val service = NotificationService()\n while (true) {\n emit(service.getNextNotification())\n delay(5000) // 每 5 秒轮询一次\n }\n}.flowOn(Dispatchers.IO)\n\n差异显而易见:可读性、类型安全,而且没有回调地狱。
\n\n9:15 —— 开发:用 Kotlin 编写代码
\n\n站会后,我投入代码中。今天的任务是实现传入推送通知的处理。我使用 Kotlin 协程 和 StateFlow 来管理 UI 状态。这是我的 ViewModel:
\n\nclass PushViewModel(\n private val repository: NotificationRepository\n) : ViewModel() {\n\n private val _uiState = MutableStateFlow<PushUiState>(PushUiState.Loading)\n val uiState: StateFlow<PushUiState> = _uiState.asStateFlow()\n\n fun loadNotifications() {\n viewModelScope.launch {\n repository.getNotifications()\n .catch { e ->\n _uiState.value = PushUiState.Error(e.message ?: "未知错误")\n }\n .collect { notifications ->\n _uiState.value = PushUiState.Success(notifications)\n }\n }\n }\n}\n\nsealed class PushUiState {\n object Loading : PushUiState()\n data class Success(val data: List<Notification>) : PushUiState()\n data class Error(val message: String) : PushUiState()\n}\n\n请注意:我使用 sealed class 来表示 UI 状态。这是现代 Kotlin Android 开发中的标准实践。没有 if-else 链——只有纯粹的静态类型。
\n\n顺便说一句,如果你是 Kotlin 新手,我建议关注 作用域函数:let、apply、also。它们能让代码更简洁。例如:
// 不使用作用域函数\nval user = User()\nuser.name = "Alex"\nuser.age = 30\nsaveUser(user)\n\n// 使用 apply\nval user = User().apply {\n name = "Alex"\n age = 30\n}\nsaveUser(user)\n\n11:00 —— 代码审查:向同事学习
\n\n午饭后(是的,我在 11 点吃午饭——这是远程工作的习惯),我打开同事的合并请求。他正在用 Kotlin Multiplatform 重写认证模块。阅读代码时,我发现了一个有趣的地方:
\n\n// 之前是 (