必须将业务逻辑全部移出Controller,放到Service或Action中;检查Controller是否只接收参数、调用原子、返回响应,剥离if/switch/await db等嵌入逻辑,改用事件驱动、派生原子或Action封装副作用,最终确保其仅含DTO处理与原子操作。
☞☞☞AI 智能聊天, 问答助手, AI 智能搜索, 多模态理解力帮你轻松跨越从0到1的创作门槛☜☜☜

当你用Atoms工具(如Unity Atoms或Jotai风格的原子化状态管理框架)生成初始代码后,发现Controller层的业务逻辑与实际需求不符,需要在不破坏原子结构前提下安全调整处理流程。
确认原子与Controller的职责边界
先打开生成的Controller文件,检查它是否只做三件事:接收请求参数、调用原子操作(如setAtom、triggerEvent)、返回响应。如果里面混有数据计算、条件分支、数据库查询等,说明职责越界了——【必须把业务逻辑全部移出Controller,放到Service或Action中】。
这一步不做干净,后续每次修改都会触发连锁重写,因为Controller本不该知道“用户余额不足时扣款失败”这种规则。
定位并剥离嵌入式业务逻辑
在Controller方法体内搜索关键词:if、switch、for、.find、.filter、new Date()、await db.、JSON.parse。这些大概率是不该出现在这里的业务判断或数据加工。
把匹配到的代码块整段剪切,粘贴到对应Service类的新方法里,例如将“根据设备类型计算货道最大容量”逻辑从VendingMachineController移到VmTypeService.calculateChannelCapacity(vmTypeId)。
注意:剪切前确保该逻辑不依赖Controller内部的request、response、model对象——若依赖,需改为接收明确参数(如vmTypeId、nodeId),否则无法解耦。
重连原子与业务动作
方法一:用事件驱动替换直调
原Controller中直接调用service.process() → 改为发布一个Atoms Event(如PaymentRequestedEvent),由独立Listener监听并触发service.process()。
方法二:用派生原子封装状态转换
若逻辑涉及状态推导(如isOrderCancelable = order.status === 'paid' && !order.refunded),在原子定义侧新建derived atom,Controller只读取该原子值,不参与计算。
方法三:在Action中注入原子并执行副作用
创建PaymentAction类,构造函数接收PaymentEvent、PaymentService、PaymentStatusAtom;execute()内先调Service,再setAtom更新UI状态。Controller只需dispatch(PaymentAction)。
验证控制器回归纯净
第一步:删掉Controller里所有非DTO参数、非原子操作、非响应构造的代码行。
第二步:检查剩余代码是否满足以下任一模式:
① @PostMapping("/pay") → 接收PayDTO → trigger(PayEvent) → return success()
② @GetMapping("/status") → read(OrderStatusAtom) → return ResponseEntity.ok(status)
③ @PutMapping("/{id}") → update(DeviceConfigAtom, id, config) → return noContent()
第三步:运行单元测试,确认Controller层测试用例仍能通过且不报NPE——【若报错,说明还有隐式依赖未清除】。

















