[{"data":1,"prerenderedAt":924},["ShallowReactive",2],{"home-posts":3,"home-projects":871},[4,394,639],{"id":5,"title":6,"author":7,"body":8,"category":379,"date":380,"description":381,"extension":382,"headline":383,"image":7,"meta":387,"minRead":388,"navigation":389,"path":390,"seo":391,"stem":392,"__hash__":393},"blog\u002Fblog\u002Ffrom-booking-to-open-door.md","从一次预约到一扇门：无人门店系统如何可靠交付",null,{"type":9,"value":10,"toc":368},"minimark",[11,19,22,25,28,33,36,39,58,65,68,95,103,107,114,117,196,199,205,209,212,215,232,235,239,242,245,277,280,283,287,290,293,310,324,327,330,350,353,356,359,362,365],[12,13,14,15],"p",{},"做预约系统久了，我越来越觉得：",[16,17,18],"strong",{},"用户路径越短，背后的系统往往越复杂。",[12,20,21],{},"在无人门店里，用户只完成几个动作：选场地、选时间、付款、到店开门。看起来是一条很直的链路，但任何一个环节都连接着不同系统：小程序、支付平台、商家后台、预约服务、定时任务，以及真实世界里的门禁设备。",[12,23,24],{},"网页上的错误可以刷新，门打不开却是一次真实的服务失败。",[12,26,27],{},"这篇文章不讨论某个具体框架，而是整理我在预约与 IoT 项目中反复使用的一套思路：怎样把一条看似简单的用户路径，拆成能够可靠运行的系统。",[29,30,32],"h2",{"id":31},"先定义业务事实再设计页面","先定义业务事实，再设计页面",[12,34,35],{},"很多项目从页面开始：先画一个日历，再放一个支付按钮，最后补接口。这样做演示很快，但一进入真实运营，问题会集中出现。",[12,37,38],{},"更稳妥的起点，是先回答几个业务问题：",[40,41,42,46,49,52,55],"ul",{},[43,44,45],"li",{},"哪一个状态代表时段已经被占用？",[43,47,48],{},"用户支付成功，但回调尚未到达时，订单是什么状态？",[43,50,51],{},"退款成功后，时段何时重新释放？",[43,53,54],{},"用户提前到店，设备是否允许开门？",[43,56,57],{},"同一条开门指令被重复发送，会发生什么？",[12,59,60,61,64],{},"这些问题的答案不是 UI 状态，而是",[16,62,63],{},"领域事实","。页面、小程序和设备控制都应该消费同一套事实，而不是分别创造自己的判断。",[12,66,67],{},"以预约为例，我通常会把核心事实拆成四组：",[69,70,71,77,83,89],"ol",{},[43,72,73,76],{},[16,74,75],{},"订单事实","：待支付、已支付、已取消、退款中、已退款；",[43,78,79,82],{},[16,80,81],{},"履约事实","：未开始、可入场、进行中、已结束；",[43,84,85,88],{},[16,86,87],{},"资产事实","：余额、次卡、优惠券分别如何占用和退回；",[43,90,91,94],{},[16,92,93],{},"设备事实","：设备在线状态、授权时间窗、指令执行结果。",[12,96,97,98,102],{},"它们彼此有关，但不能混成一个巨大的 ",[99,100,101],"code",{},"status"," 字段。一个订单已支付，不等于现在允许开门；一次退款已发起，也不等于会员资产已经回滚完成。",[29,104,106],{"id":105},"状态机比大量-if-更可靠","状态机比大量 if 更可靠",[12,108,109,110,113],{},"当业务刚开始时，几个 ",[99,111,112],{},"if"," 足够解决问题。随着微信、支付宝、抖音和商家后台陆续接入，相同规则会在多个端重复出现，并慢慢产生差异。",[12,115,116],{},"我更倾向于把状态变化写成明确的转换：",[118,119,120,139],"table",{},[121,122,123],"thead",{},[124,125,126,130,133,136],"tr",{},[127,128,129],"th",{},"当前状态",[127,131,132],{},"事件",[127,134,135],{},"下一个状态",[127,137,138],{},"伴随动作",[140,141,142,157,170,183],"tbody",{},[124,143,144,148,151,154],{},[145,146,147],"td",{},"待支付",[145,149,150],{},"支付成功",[145,152,153],{},"已支付",[145,155,156],{},"确认时段、生成设备授权",[124,158,159,161,164,167],{},[145,160,147],{},[145,162,163],{},"超时",[145,165,166],{},"已取消",[145,168,169],{},"释放临时时段",[124,171,172,174,177,180],{},[145,173,153],{},[145,175,176],{},"商家同意退款",[145,178,179],{},"退款中",[145,181,182],{},"提交支付平台退款",[124,184,185,187,190,193],{},[145,186,179],{},[145,188,189],{},"退款成功",[145,191,192],{},"已退款",[145,194,195],{},"退回资产、撤销设备授权",[12,197,198],{},"这张表的价值不只是方便开发。产品、客服和工程师可以围绕同一套语言讨论异常：究竟是事件没有发生，还是转换失败，还是伴随动作没有完成。",[200,201,202],"blockquote",{},[12,203,204],{},"状态不是给页面显示的标签，而是系统对已经发生之事实的承诺。",[29,206,208],{"id":207},"把支付回调当成消息而不是一次请求","把支付回调当成消息，而不是一次请求",[12,210,211],{},"支付平台的回调可能延迟、重复，甚至先于前端的“支付成功”页面到达。系统如果假设每个请求只出现一次，线上很快就会出现重复扣减、重复通知和重复发放。",[12,213,214],{},"我的处理原则是：",[40,216,217,220,223,226,229],{},[43,218,219],{},"每一种外部事件都有稳定的业务唯一键；",[43,221,222],{},"先记录收到的原始事件，再执行状态转换；",[43,224,225],{},"状态转换必须具备幂等性；",[43,227,228],{},"耗时的副作用交给队列处理；",[43,230,231],{},"每个失败动作都可以单独重试。",[12,233,234],{},"例如支付成功后，确认订单、发通知、生成门禁授权不是一个不可拆分的大事务。订单确认属于核心状态变化；短信、数据统计和设备同步可以作为后续任务。这样，即使某个设备服务短暂不可用，也不会否定已经发生的支付事实。",[29,236,238],{"id":237},"设备控制要接受现实世界不可靠","设备控制要接受“现实世界不可靠”",[12,240,241],{},"纯软件系统里，我们容易把一次 HTTP 200 当作成功。但对门禁设备来说，接口返回成功可能只表示平台接收了指令，不代表门真的打开。",[12,243,244],{},"因此设备层需要比普通业务接口多几个概念：",[40,246,247,253,259,265,271],{},[43,248,249,252],{},[16,250,251],{},"统一设备身份","：不同厂商型号映射到内部设备 ID；",[43,254,255,258],{},[16,256,257],{},"统一操作语义","：开门、常开、关闭等动作有稳定接口；",[43,260,261,264],{},[16,262,263],{},"请求编号","：每次控制都有可追踪、可去重的编号；",[43,266,267,270],{},[16,268,269],{},"结果分层","：已接收、已下发、已执行、执行失败；",[43,272,273,276],{},[16,274,275],{},"人工兜底","：线上失败时，客服能够看到足够信息并采取替代方案。",[12,278,279],{},"接入多种门禁和控制器时，我不希望业务代码知道具体厂商。预约服务只表达“这个用户在这个时间窗拥有开门权限”，适配层再处理每种设备的协议差异。",[12,281,282],{},"这层隔离让更换设备供应商不至于侵入订单、会员和小程序代码。",[29,284,286],{"id":285},"多端一致不等于多端复制","多端一致，不等于多端复制",[12,288,289],{},"同一个预约业务可能同时存在于用户微信小程序、商家小程序、支付宝、抖音与 PC 后台。最危险的做法，是让每个端各自实现一遍业务判断。",[12,291,292],{},"真正应该复用的不是页面组件，而是：",[40,294,295,298,301,304,307],{},[43,296,297],{},"可用时段的计算规则；",[43,299,300],{},"价格、优惠和会员资产的计算结果；",[43,302,303],{},"订单允许执行的动作；",[43,305,306],{},"面向用户的状态解释；",[43,308,309],{},"错误码及恢复建议。",[12,311,312,313,316,317,316,320,323],{},"服务端返回的不应只有原始状态，还可以返回当前允许的操作。例如 ",[99,314,315],{},"can_pay","、",[99,318,319],{},"can_cancel",[99,321,322],{},"can_open_door","。前端仍然负责体验，但不再猜测业务规则。",[29,325,326],{"id":326},"为运营留下可观察性",[12,328,329],{},"系统稳定，不只是“没有报错”。对于交易和设备联动，我至少会保留三条可追踪链路：",[69,331,332,338,344],{},[43,333,334,337],{},[16,335,336],{},"业务链路","：用户、订单、支付单、退款单和会员资产；",[43,339,340,343],{},[16,341,342],{},"任务链路","：事件何时进入队列、执行几次、最终结果是什么；",[43,345,346,349],{},[16,347,348],{},"设备链路","：授权、控制指令、厂商响应和设备回报。",[12,351,352],{},"当客服说“用户付了钱但门打不开”，工程师应该能从订单出发，在几分钟内定位到具体环节，而不是登录几台服务器翻找没有关联 ID 的日志。",[12,354,355],{},"可观察性不是项目完成后的附加工作。它决定了系统出问题时，团队是否有能力恢复服务。",[29,357,358],{"id":358},"最后",[12,360,361],{},"一套无人门店系统真正交付的，不是几个页面，也不是一组接口，而是一条从数字订单延伸到物理空间的承诺。",[12,363,364],{},"要兑现这份承诺，需要先定义业务事实，用状态机约束变化，用幂等和异步任务吸收外部不确定性，再通过统一设备层与可观察性应对现实世界。",[12,366,367],{},"用户最终只需要看到一件事：预约完成，走到门前，门如期打开。",{"title":369,"searchDepth":370,"depth":370,"links":371},"",2,[372,373,374,375,376,377,378],{"id":31,"depth":370,"text":32},{"id":105,"depth":370,"text":106},{"id":207,"depth":370,"text":208},{"id":237,"depth":370,"text":238},{"id":285,"depth":370,"text":286},{"id":326,"depth":370,"text":326},{"id":358,"depth":370,"text":358},"工程实践","2026-08-16","用户看到的是一次预约和一次开门，系统背后却要让订单、支付、时段与设备状态在多个端保持一致。","md",[384,385,386],"从一次预约到一扇门：","无人门店系统","如何可靠交付",{},9,true,"\u002Fblog\u002Ffrom-booking-to-open-door",{"title":6,"description":381},"blog\u002Ffrom-booking-to-open-door","XHGy8dldzOWbk-dnnm0xGA_mKKdweYRbW9tHL6_px94",{"id":395,"title":396,"author":7,"body":397,"category":630,"date":631,"description":632,"extension":382,"headline":7,"image":7,"meta":633,"minRead":634,"navigation":389,"path":635,"seo":636,"stem":637,"__hash__":638},"blog\u002Fblog\u002Frefactor-without-stopping.md","重构存量系统：不要停下来换引擎",{"type":9,"value":398,"toc":621},[399,402,405,408,414,417,420,423,437,440,443,446,449,452,455,458,484,487,490,493,496,499,510,513,516,519,522,539,542,545,548,551,568,571,576,579,582,599,602,605,609,612,615,618],[12,400,401],{},"工程师很容易被“重写”吸引。",[12,403,404],{},"旧代码缺少边界，页面依赖 jQuery，接口返回不一致，改一个字段会影响三个系统。面对这样的代码库，重新选一套技术、从空目录开始，感觉既干净又高效。",[12,406,407],{},"但长期运行的业务系统通常不能停下来等你换引擎。它每天有预约、支付、报告和运营人员在使用，重构必须与需求交付同时发生。",[12,409,410,411],{},"我曾参与一个长期运行的医疗预约产品线：后端持续使用 Laravel，诊所后台从 jQuery 逐步迁移到 Vue 2，后来再演进到 Nuxt 2。这个过程让我确认了一件事：",[16,412,413],{},"存量系统重构的核心，不是替换技术，而是逐步重建边界。",[29,415,416],{"id":416},"先理解系统为什么变成现在这样",[12,418,419],{},"旧代码并不一定来自糟糕的工程能力。它往往是多年的业务压力、人员变化和当时技术条件共同留下的结果。",[12,421,422],{},"在修改之前，我会先画出四类关系：",[40,424,425,428,431,434],{},[43,426,427],{},"哪些模块直接创造业务价值；",[43,429,430],{},"哪些数据被多个系统共同读写；",[43,432,433],{},"哪些流程与外部平台强绑定；",[43,435,436],{},"哪些代码虽然难看，却已经稳定运行多年。",[12,438,439],{},"最后一类尤其重要。重构不是以“代码是否优雅”排序，而应该综合考虑变更频率、故障影响和维护成本。",[12,441,442],{},"一个半年不会变化的旧页面，即使内部不够漂亮，也可能不值得优先处理。相反，一段每周都要修改、每次都容易出错的订单逻辑，才是应该先建立边界的地方。",[29,444,445],{"id":445},"不要同时改变所有变量",[12,447,448],{},"一次大重写通常同时改变语言、框架、数据模型、接口和部署方式。任何问题出现时，团队很难判断究竟是哪一层造成的。",[12,450,451],{},"渐进式重构要刻意控制变量。",[12,453,454],{},"以页面迁移为例，可以先保持后端接口和部署不变，只把一个高频模块从 jQuery 改为 Vue；等组件结构与状态管理稳定后，再统一接口；最后才考虑路由和服务端渲染框架。",[12,456,457],{},"我常用的顺序是：",[69,459,460,466,472,478],{},[43,461,462,465],{},[16,463,464],{},"先包住变化","：为最混乱的外部调用加适配层；",[43,467,468,471],{},[16,469,470],{},"再明确契约","：稳定请求参数、响应结构和错误语义；",[43,473,474,477],{},[16,475,476],{},"然后迁移页面","：新需求只写在新结构中，旧页面按价值逐步替换；",[43,479,480,483],{},[16,481,482],{},"最后清理旧入口","：确认流量和功能都已迁移，再删除旧实现。",[12,485,486],{},"这不是最快的写法，但它让每一步都可以验证、回退，也让业务持续运行。",[29,488,489],{"id":489},"用新需求支付重构成本",[12,491,492],{},"单独申请几个月“只做重构”，在大多数业务团队里并不现实。更可行的方式，是把重构和真实需求绑定。",[12,494,495],{},"如果下一个需求要改预约表单，就顺便把表单校验从散落的 DOM 操作收进组件；如果要增加新的报告类型，就先抽出报告生成的任务接口；如果要接入一个新客户端，就借此统一已有 API 的认证和错误码。",[12,497,498],{},"这个策略有三个好处：",[40,500,501,504,507],{},[43,502,503],{},"每次重构都有明确业务收益；",[43,505,506],{},"新边界会立即接受真实场景检验；",[43,508,509],{},"团队不需要维护一套“重构中的理想系统”和一套“仍在赚钱的旧系统”。",[12,511,512],{},"当然，不能借每个小需求无限扩大范围。一次迭代只改善与当前变化直接相关的边界，其余问题记录下来，等待合适时机。",[29,514,515],{"id":515},"数据库是最后需要冲动的地方",[12,517,518],{},"前端页面可以逐页替换，数据库结构却连接着报表、脚本、异步任务和多个客户端。一张看起来命名不合理的表，背后可能有很多隐形依赖。",[12,520,521],{},"对于数据层，我更倾向于：",[40,523,524,527,530,533,536],{},[43,525,526],{},"先增加新字段，而不是立刻修改旧字段语义；",[43,528,529],{},"使用迁移脚本补齐历史数据；",[43,531,532],{},"在一段时间内同时读写新旧结构；",[43,534,535],{},"用校验任务比较两套数据结果；",[43,537,538],{},"确认所有消费者迁移后，再停止旧结构写入。",[12,540,541],{},"这是一种“扩展—迁移—收缩”的过程。它会产生短期重复，但把高风险的一次切换拆成了多个可观察步骤。",[29,543,544],{"id":544},"接口是最值得优先稳定的边界",[12,546,547],{},"当系统拥有 Web、管理后台和移动端时，接口质量会直接决定重构难度。",[12,549,550],{},"一个稳定的接口边界至少应该回答：",[40,552,553,556,559,562,565],{},[43,554,555],{},"字段是否有明确含义和单位；",[43,557,558],{},"缺失、空值与零是否能区分；",[43,560,561],{},"错误是否有机器可读的代码；",[43,563,564],{},"客户端是否需要理解数据库实现；",[43,566,567],{},"新字段加入时是否破坏旧客户端。",[12,569,570],{},"我不追求一开始就设计出永远不变的接口，而是让变化显式发生。必要时保持版本兼容，或者由服务端提供过渡字段，而不是要求所有客户端在同一天更新。",[200,572,573],{},[12,574,575],{},"存量系统里，好的架构不是从未改变，而是改变时不会把所有人绑在同一个发布窗口里。",[29,577,578],{"id":578},"每一步都要能证明更好了",[12,580,581],{},"“代码看起来更现代”不是充分的重构结果。每个阶段都需要可验证信号，例如：",[40,583,584,587,590,593,596],{},[43,585,586],{},"同类线上故障是否减少；",[43,588,589],{},"新功能需要修改的文件是否变少；",[43,591,592],{},"页面加载和交互性能是否改善；",[43,594,595],{},"新成员理解模块需要多久；",[43,597,598],{},"发布是否更小、更频繁、更容易回退。",[12,600,601],{},"自动化测试当然重要，但存量系统很难一开始就拥有完整覆盖。可以先保护最关键的业务规则，再增加接口契约测试、迁移校验和少量端到端流程。",[12,603,604],{},"测试也应该跟着边界一起生长。",[29,606,608],{"id":607},"接受重构没有完成的一天","接受重构没有“完成”的一天",[12,610,611],{},"长期产品不会在某一天宣布“技术债已经清零”。业务会继续变化，今天的新结构也可能成为未来的旧系统。",[12,613,614],{},"比彻底重写更重要的，是让团队形成持续改善的节奏：新代码遵循新的边界，高频旧模块随需求迁移，低价值区域保持稳定，对危险依赖保留清晰记录。",[12,616,617],{},"重构的目的不是获得一份完美代码，而是恢复团队安全改变系统的能力。",[12,619,620],{},"就像一辆仍在行驶的车，我们不需要停车换掉所有零件。我们需要知道先换哪一个、如何确认它工作，以及出现问题时怎样回到上一站。",{"title":369,"searchDepth":370,"depth":370,"links":622},[623,624,625,626,627,628,629],{"id":416,"depth":370,"text":416},{"id":445,"depth":370,"text":445},{"id":489,"depth":370,"text":489},{"id":515,"depth":370,"text":515},{"id":544,"depth":370,"text":544},{"id":578,"depth":370,"text":578},{"id":607,"depth":370,"text":608},"架构思考","2026-08-09","真正困难的重构，不是在新项目里选择更好的技术，而是在业务继续运行时，让旧系统一步步拥有新的边界。",{},8,"\u002Fblog\u002Frefactor-without-stopping",{"title":396,"description":632},"blog\u002Frefactor-without-stopping","WcRRfKNxzL_n31hy7qNmVGw61GrC1UKqj5VeL4uHk5o",{"id":640,"title":641,"author":7,"body":642,"category":858,"date":859,"description":860,"extension":382,"headline":861,"image":7,"meta":865,"minRead":866,"navigation":389,"path":867,"seo":868,"stem":869,"__hash__":870},"blog\u002Fblog\u002Ftechnical-lead-still-codes.md","负责团队之后，我为什么仍然坚持写核心代码",{"type":9,"value":643,"toc":850},[644,647,650,656,659,662,665,668,671,688,691,695,698,701,733,736,739,742,745,759,762,765,769,772,775,792,795,798,801,804,807,824,827,830,833,836,844,847],[12,645,646],{},"从工程师成为技术负责人之后，一个常见问题是：还要不要继续写代码？",[12,648,649],{},"一种观点认为，负责人应该把时间全部用于架构、排期和人员协作；另一种观点则把“保持编码”理解成继续领取大量需求，甚至成为团队里最忙的开发。",[12,651,652,653],{},"我的经验介于两者之间：",[16,654,655],{},"技术负责人不必写下最多的代码，但应该持续参与最能暴露系统真实约束的代码。",[12,657,658],{},"我曾从 0 到 1 组建并负责 6–7 人研发团队，也带过更小的交付团队。在这些经历里，持续参与核心开发并不是因为不愿意授权，而是因为它能让很多管理和技术判断建立在事实之上。",[29,660,661],{"id":661},"编码是理解系统的一种方式",[12,663,664],{},"架构图表达的是我们希望系统如何工作，代码和生产日志呈现的则是它实际上如何工作。",[12,666,667],{},"当负责人完全离开实现一段时间，判断容易建立在过时印象上：以为某个模块边界已经清晰，以为一个接口只是增加字段，以为部署流程足够稳定。真正开始修改时，团队才发现隐藏依赖远比预期多。",[12,669,670],{},"参与核心代码可以持续校准这些认知。但“核心”不等于“最难”或“最炫技”，而是那些能够揭示系统关键约束的地方，例如：",[40,672,673,676,679,682,685],{},[43,674,675],{},"新业务的第一个完整纵切；",[43,677,678],{},"涉及多个系统的接口契约；",[43,680,681],{},"支付、订单和权限等高风险逻辑；",[43,683,684],{},"一次架构迁移的示范模块；",[43,686,687],{},"难以复现的生产故障。",[12,689,690],{},"写过第一条完整链路之后，负责人更容易把后续任务拆成团队可以并行完成的部分。",[29,692,694],{"id":693},"负责人写代码不应该成为瓶颈","负责人写代码，不应该成为瓶颈",[12,696,697],{},"技术负责人参与实现最大的风险，是所有关键任务都必须等他完成。短期看很高效，长期会让团队失去独立交付能力。",[12,699,700],{},"我会用几个原则避免这个问题：",[69,702,703,709,715,721,727],{},[43,704,705,708],{},[16,706,707],{},"优先写样板，不长期占有模块。"," 把新模式跑通、记录决策，再让其他成员继续扩展；",[43,710,711,714],{},[16,712,713],{},"选择高信息量任务。"," 参与能帮助理解系统的问题，而不是把大量重复页面留给自己；",[43,716,717,720],{},[16,718,719],{},"代码从一开始就进入正常评审。"," 负责人写的代码也要被团队审阅；",[43,722,723,726],{},[16,724,725],{},"确保至少一位成员理解实现。"," 关键模块不能只有一个人能够维护；",[43,728,729,732],{},[16,730,731],{},"主动退出稳定区域。"," 一旦边界清晰，就把所有权交给团队。",[12,734,735],{},"负责人写代码的目标不是证明自己仍是最强开发，而是降低未知、建立边界、帮助团队更快形成共同理解。",[29,737,738],{"id":738},"任务拆解必须靠近实现",[12,740,741],{},"“开发一个预约功能”不是可执行任务。真正的任务可能包括数据模型、可用时段计算、价格规则、订单接口、支付回调、页面状态和运营后台。",[12,743,744],{},"如果任务拆解离实现太远，常见结果是：",[40,746,747,750,753,756],{},[43,748,749],{},"工作量按页面数量估算，却忽略后端状态变化；",[43,751,752],{},"前后端各自假设接口，联调时才发现不一致；",[43,754,755],{},"正常路径很清楚，异常和恢复路径没人负责；",[43,757,758],{},"任务看似完成，却缺少日志、迁移和发布方案。",[12,760,761],{},"保持编码让我能够更早看到这些缝隙。拆解时，我会要求每个任务尽量包含明确输入、输出和验收方式，同时把跨模块风险单独列出。",[12,763,764],{},"好的任务应该可以被验证，而不只是被“做完”。",[29,766,768],{"id":767},"代码评审是建立共同判断不是找错","代码评审是建立共同判断，不是找错",[12,770,771],{},"如果代码评审只由负责人指出问题，团队会越来越依赖一个人的偏好。更有价值的做法，是把评审变成对设计判断的解释。",[12,773,774],{},"例如，与其只说“这里应该抽象”，不如说明：",[40,776,777,780,783,786,789],{},[43,778,779],{},"当前重复是否真的会一起变化；",[43,781,782],{},"抽象之后，调用方需要理解多少概念；",[43,784,785],{},"错误应该在哪一层被转换；",[43,787,788],{},"这个边界是否方便单独测试；",[43,790,791],{},"下一项需求到来时，哪部分最可能变化。",[12,793,794],{},"同样，负责人自己的代码也应该接受这样的讨论。团队看到技术判断可以被质疑和修正，才会更愿意表达不同意见。",[29,796,797],{"id":797},"生产问题需要负责人保持手感",[12,799,800],{},"线上故障往往同时涉及业务、代码、数据和部署。技术负责人如果熟悉真实运行链路，可以更快做出优先级判断：先恢复服务，还是先保护数据；应该回滚版本，还是补偿任务；哪些操作可逆，哪些需要等待外部平台。",[12,802,803],{},"但这不意味着负责人应该独自处理每次故障。",[12,805,806],{},"更好的方式是共同响应，并在事后沉淀：",[40,808,809,812,815,818,821],{},[43,810,811],{},"一条可复用的排查路径；",[43,813,814],{},"关键链路的监控和关联 ID；",[43,816,817],{},"必要的后台修复工具；",[43,819,820],{},"明确的回滚与补偿方案；",[43,822,823],{},"对系统边界的新理解。",[12,825,826],{},"故障处理的成果不只是修复当下问题，还应该让下一次响应不再依赖同一个人。",[29,828,829],{"id":829},"管理和编码不是两份工作",[12,831,832],{},"当我参与系统架构、任务协作和生产交付时，编码并不是管理工作之外额外增加的一份个人任务。它是获取信息、验证设计和建立团队标准的一种手段。",[12,834,835],{},"真正需要避免的是两种极端：",[40,837,838,841],{},[43,839,840],{},"完全离开实现，只通过会议和文档理解系统；",[43,842,843],{},"承担所有难题，让团队只能等待和执行。",[12,845,846],{},"技术负责人的价值，在于让正确的信息流向正确的人，让复杂问题拥有清晰边界，并让团队逐渐具备不依赖负责人也能稳定交付的能力。",[12,848,849],{},"我仍然写核心代码，但我希望留下的不是“只有我能维护”的模块，而是一套团队可以继续工作的路径。",{"title":369,"searchDepth":370,"depth":370,"links":851},[852,853,854,855,856,857],{"id":661,"depth":370,"text":661},{"id":693,"depth":370,"text":694},{"id":738,"depth":370,"text":738},{"id":767,"depth":370,"text":768},{"id":797,"depth":370,"text":797},{"id":829,"depth":370,"text":829},"团队与交付","2026-08-02","技术负责人不必写下最多的代码，但需要持续接触真实约束，才能让架构判断、任务拆解和生产决策保持准确。",[862,863,864],"负责团队之后，","我为什么仍然坚持","写核心代码",{},7,"\u002Fblog\u002Ftechnical-lead-still-codes",{"title":641,"description":860},"blog\u002Ftechnical-lead-still-codes","6XsPJnZBQgy-35bxydpjOrJmBi94RY3FIxUghmbj5q8",[872,900],{"id":873,"title":874,"articleLabel":875,"date":876,"description":877,"extension":878,"eyebrow":879,"image":880,"imageAlt":881,"meta":882,"name":883,"period":884,"responsibilities":885,"results":886,"role":887,"slug":888,"stem":889,"subtitle":890,"summary":891,"tags":892,"url":390,"__hash__":899},"projects\u002Fprojects\u002Fyuyue-cloud.yml","语月云 · 共享自助预约 SaaS","阅读工程复盘","2026-08-01","商户、门店、场地、会员资产与设备管理，连接一次预约到一次开门的完整体验。","yml","SaaS · IoT","\u002Fprojects\u002Fyuyue-homepage.png","语月云官网，展示无人门店自助预约系统与应用场景",{},"语月云","2025.11 — 2026.08","牵头研发任务执行与核心开发，参与同库多租户、预约交易、支付退款与 IoT 门禁联动；持续交付管理后台、多个小程序与 Nuxt 官网。","约 190 家累计服务商户 · 20 万+ 累计订单","全栈开发工程师 · 项目负责人","yuyue-cloud","projects\u002Fyuyue-cloud","共享自助预约 SaaS","从多租户与预约交易，到支付退款与 IoT 开门，打通无人门店的自助服务闭环。",[893,894,895,896,897,898],"ThinkPHP","MySQL","Redis","Vue","Uni-app","IoT","tsZGiPQE8RAcwIv2kSlFKrpz92jZ80YuonjAigo5nm4",{"id":901,"title":902,"articleLabel":903,"date":904,"description":905,"extension":878,"eyebrow":906,"image":7,"imageAlt":7,"meta":907,"name":908,"period":909,"responsibilities":910,"results":911,"role":912,"slug":913,"stem":914,"subtitle":915,"summary":916,"tags":917,"url":635,"__hash__":923},"projects\u002Fprojects\u002Fhkiphc.yml","HKIPHC 医疗预约与诊所运营系统","阅读架构思考","2025-06-01","统一 Laravel API 连接诊所后台、客户预约与代理商系统，覆盖预约、支付、核销、收银、样本流转与报告查询。跨公司持续承接产品线，在真实业务运行中推动系统渐进演进。","Healthcare · Platform",{},"HKIPHC","2016 — 2025","整体架构 · 团队建设 · 核心开发 · 发布运维","从 jQuery 逐步迁移到 Vue 2，再演进至 Nuxt 2，在持续交付中改善系统边界。","医疗预约 · 诊所运营","hkiphc","projects\u002Fhkiphc","医疗预约与诊所运营","统一 API 连接诊所后台、客户预约和代理商系统，覆盖预约、支付、核销与报告。",[918,894,919,920,921,922],"Laravel","Queue","Nuxt","React Native","阿里云","kJMZ-3zIZYvHwX1C3rz0QLP8prMq6j0SDk53qNzRGBg",1789624775797]