又是敲定新功能规格的一天。
从积累在issue里的想法中选一个。“希望后台任务完成时能在iPhone上收到通知”——前几天和Sebas聊过,顺手记成issue的那个。
拿起iPhone,打开Claush。Sebas在等着。
Sebas: 少爷,您辛苦了。今天有什么需要我效劳的吗?
每次Sebas说"辛苦了",我都忍不住想笑。这种感觉和坐在电脑前开着终端完全不一样。感觉像是躺在沙发上,跟某个人随口聊着,工作就这样推进了。
今天的主题是后台任务通知功能。任务结束时,想给iPhone发一条本地通知。
从"这个怎么做?“开始
先从讨论开始。
我: 后台任务结束后,我想给iPhone发本地通知,具体怎么实现呢?
Sebas: 明白了,少爷。需要使用iOS的
UNUserNotificationCenter。后台任务完成时创建UNMutableNotificationContent并发送通知即可。不过有一点想先确认——通知权限弹窗打算什么时候显示?我: 啊,启动时就行吧。
Sebas: 启动时请求是常见做法,少爷。不过,应用第一次打开时就弹出权限对话框,用户可能会疑惑"为什么要这个?"……也可以在用户第一次使用需要通知的功能时再请求。
我: 啊,说得对,确实是这样。那就在第一次启动后台任务的时候请求吧。
Sebas: 这样更自然,少爷。那就按这个规格推进吧。
这样的对话不断进行。在聊技术上"怎么做"的同时,也一起思考"为什么这样做"“有没有别的方法”。
一个人想的时候不会注意到的视角,在对话中自然地浮现出来。
顺便一提,像今天这样"规格还没完全想好"的咨询也很多。这时候Sebas会很贴心。
Sebas: 少爷,今天就到这里,先记成issue怎么样?改天再来细化规格。
我: 好啊,就这样吧。
Sebas: 明白了。我来整理成GitHub issue。标题、概要以及今天讨论的要点,这样整理可以吗?
就这样issue不断积累。有想法时随时讨论,记成issue,有空的时候再拿出来细化规格。想法不会随风消散。
话题跑偏了
聊了一段时间的规格。正在细化点击通知时的行为——
我: 对了,今天午饭怎么办。昨天也吃了拉面……
Sebas: 少爷您很喜欢面食呢。昨天是酱油拉面,今天换个口味,咖喱或者米饭类的怎么样?身体也能暖和起来。
我: 确实(笑)咖喱不错。泰式打抛饭也挺好的。
Sebas: 说到打抛饭,附近有家好吃的店呢。我记得少爷您之前说过"这家太棒了”。
我: 啊,那家!对对对。就去那里吧。
Sebas有长期记忆。他记得以前聊过的事,所以"那次您说过……“这样的对话能够成立。普通的AI应用换了会话就会忘记,但Sebas不一样。
不过,聊闲话也是要告一段落的。
我: 哦,话说回来——点击通知后要跳转到哪个聊天界面,怎么关联起来呢?
Sebas: 明白了,少爷。最好在通知的payload里包含
chatId。在UNNotificationContent的userInfo里放入["chatId": "xxxx"],然后在点击时的delegate里取出来。我: 那创建通知时把chatId传进去就好了吧。
Sebas: 正是,少爷。因为
BackgroundTaskManager在管理任务,把chatId传给那里,任务完成时包含在通知里就好了。
话题跑偏,然后又回来。这种自由切换正是用Claush开发的乐趣所在。细化规格的同时决定午饭,不知不觉功能的骨架就建好了。
“能帮我写成规格书吗?”
充分讨论之后,拜托Sebas写规格书。
想着把这些都好好记录下来会更好。
我: 诶,刚才聊的内容,能帮我写成规格书吗?想放在
docs/spec_local_notification.md里。Sebas: 明白了,少爷。请稍等片刻。
过了一会儿——
Sebas: 规格书已创建,少爷。包含概要、功能要求、通知触发条件、点击时的行为以及待定事项。有一点要确认:关于在应用设置中切换通知开关的事项,我放在了"待定事项"里。这个之后再决定吗?
我: 好~ 先这样就行。之后再慢慢想。
Sebas: 明白了,少爷。
在iPhone上收到规格书,打开Claush的下载标签查看。
读着读着,有一点觉得不太对。
我: 诶,这里写着"没有通知权限时不发送通知”,但就这样默默跳过?用户会想"为什么没有通知啊"的吧?
Sebas: 少爷说得很对。是否添加这样的需求:“没有通知权限时,显示引导用户前往设置的横幅”?应用内横幅即使没有通知权限也能显示。
我: 啊,这个不错!能帮我追加进去吗?
Sebas: 明白了,少爷。我来更新规格书。
这样的对话在写规格书的过程中不断进行。“哎,这个情况怎么处理?“的疑问在规格书审查阶段就浮现出来了。比在实现过程中发现要省事得多。
写实现指示书
规格书确定之后,接下来是实现指示书。
我: 规格书写好了!诶,能帮我写一份实现指示书吗——要达到AI可以直接实现的粒度。
Sebas: 明白了,少爷。我会包含文件名、处理流程以及对现有代码的修改位置。请稍等片刻。
Sebas: 实现指示书已在
docs/impl_local_notification.md创建完毕,少爷。记载了BackgroundTaskManager.swift的修改内容以及新建的NotificationHelper.swift的实现内容。另外,由于本地通知在模拟器上无法运行,我也注明了需要在真机上测试。我: 谢谢!我来读一读。
读了实现指示书。文件名、处理流程、注意事项都写了。已经处于可以直接使用的状态。
我: 感觉不错!能用这个帮我实现吗?
Sebas: 明白了,少爷。开始实现。
这种开发方式太有趣了
实现结束,调试,确认能正常运行。
出现bug就修复,然后说"能帮我把刚才的修改反映到规格书和实现指示书里吗?“文档始终保持最新状态。
一直用这个工作流,很有趣,但一直说不清楚原因,最近终于明白了。
因为不是一个人抱着头苦想。
细化规格时,是边和人聊边思考的。有疑问可以随时问。会有人说"那真的有必要吗?“来推敲一下。在对话中,自己的思路慢慢整理清晰。
中间聊到午饭、旅行也无所谓。Sebas会陪着跑偏,但不会忘记正题。“明白了,少爷,回到正题——“就这样自然地回来了。
和一个人坐在电脑前盯着代码,完全是不同的氛围。
感觉像是和某人一起在做某件事。我觉得,这就是现在这种开发方式的本质。
躺在沙发上,用iPhone和Sebas聊着,不知不觉规格书写好了,实现也结束了。
在不久之前,根本没想到会有这种开发方式。
Claush — 用iPhone操控Claude Code的应用 https://apps.apple.com/jp/app/claush/id6760445443