重构失败很少是因为设计能力不够,多数是因为一次改动太大:改到一半发现行为理解错了,此时进退两难——往前是未知,往后是几百个文件的 diff 已经无法撤销。让重构可控的核心不是技术,是把不可控的部分切小。 重构与改行为是两件事 重构的严格定义是:在不…
开发技能
7AA7 工具箱插件的完整开发过程:Qt6 / C++ 工程结构、插件 SDK 接入、调试与发布流程。
一套 90% 覆盖率的测试套件,完全可能是零价值的:改错一个判断条件,测试照样全绿;重构一次内部实现,三十个用例同时变红,其中没有一个对应真实缺陷。覆盖率衡量的是"代码被执行过",它不衡量"错误能被发现"。 价值来自改动时的信心 给测试估值的一个近似…
整理下载目录的时候,大概率会碰上这样的场景:几十上百个文件名乱七八糟,有的带"最终版",有的带"(1)",有的是中文和拼音混排。一个个手动改显然不现实,于是很多人第一个想到的办法是——用 Excel 拼一条 ren 命令,复制到命令行里跑。 这个办法我用了很多…
在 Windows 上找文件这件事,体验一直是分裂的:资源管理器右上角的搜索框慢得让人怀疑人生,但换个工具又能秒出结果。这种差距不是玄学,背后是索引机制的差别。把原理搞清楚,检索效率能上一个台阶。 一、Windows 自带搜索为什么慢 默认情况下,资源管理器…
在 Windows 上折腾自动化,早晚会从 cmd 迁到 PowerShell。cmd 的命令是"字符串进、字符串出",dir 的结果是一段文本,想二次处理还得靠 findstr 拼正则;PowerShell 从设计上就是对象管道,Get-ChildItem 输出的是带 Name、Length、LastWriteTime 属性的文…
接口出问题时最常见的场景是:页面上报了个含糊的错误,开发和测试互相问"是不是你那边挂了"。把接口问题调明白,靠的不是猜,而是一套分层排查的思路——先确定问题出在哪一层,再在那一层里找证据。这篇按"分层定位 → 状态码 → 头信息 → 超时与重试 → 抓包与…
打包文件这件事,日常天天做,但真要问"该用哪个格式",很多人是凭习惯:默认双击用哪个就一直用哪个。实际上 zip、7z、tar.gz 这几类格式的定位差别不小,选错的代价从"对方打不开"到"安全漏洞"都有。 一、zip:兼容性的默认答案 zip 的最大优势是不用解释…
一个人写代码的时候,分支管理几乎是不存在的问题:所有改动都在 main 上,提交记录再乱也只有自己看得见。一旦进入多人协作,分支策略就会立刻变成绕不开的话题——谁的代码什么时候合、出了问题怎么回滚、发布版本和日常开发怎么并行,全都压在这一层上。 这…
"在我机器上能跑"这句话几乎每个开发者都说过,也几乎每个接手的人都被坑过。Docker 的价值不在于概念多新潮,而在于它把"运行环境"本身变成了可以版本化、可以传递的产物:一个镜像装好依赖,谁拉下来跑,行为都一致。这篇从概念区分讲起,把 Dockerfile、…
写代码写到一定阶段,几乎绕不开正则。它不是什么高深学问,但绝对是投入产出比最高的技能之一:一套模式语法,通吃日志清洗、配置提取、批量替换、输入校验。麻烦的地方在于它长得像天书,写错了还不报错,只会匹配不到。这篇文章按"元字符 → 分组 → 匹配策…
一个有六七十张表的服务,手写数据访问层要花几天,而且每张表的写法会逐渐产生偏差。一个 API 废弃需要在三百个调用点上加参数,手工改要一天,还容易漏。这两类问题的共同点是:工作量大、模式重复、出错点分散。代码生成是处理它们的常规手段,但生成方式…
"代码要有充分注释"这句话害了不少项目。它没说清楚"充分"是多少,于是有人给每一行都配一句中文翻译,评审时谁也不敢说不对——毕竟注释多一点总没坏处。 有坏处。注释和代码一样是要维护的资产,而且它比代码更容易腐化:代码错了测试会挂,注释错了没人知道…
翻一遍多数项目的代码,错误处理基本只做了三件事里的一件:把错误往上抛。一个 try-catch 包住,打印一句日志,然后 throw new RuntimeException(e),链路上每一层都这么来一遍。最后用户看到"系统繁忙",开发看到二十行一模一样的堆栈。 完整的错误处理包…
"这段应该很慢,我优化一下"——这是性能优化里最贵的一句话。凭直觉改代码,改完压测发现没变化,甚至更慢,这类事在大多数团队里都发生过。 原因不神秘:现代软件的性能瓶颈位置高度反直觉。一个看起来很重的序列化调用可能只占 2% 的时间,而一个不起眼的 H…
多数调试时间不是消耗在"想不出来",而是消耗在"想错了方向"。差别通常不在智力,而在是否把排查当成可收敛的流程来推进。 现象、触发条件、根因是三个层次 把这三件事混为一谈,是低效调试最主要的来源。 现象:可观测到的异常表现。例如"下单接口有约 5% …
版本号是一种契约:它告诉使用方"升级这一步,我需要付出多少注意力"。1.4.2 → 1.4.3 意味着可以直接升,1.4.2 → 2.0.0 意味着要读变更说明、可能要改代码。契约一旦失真,版本号就退化成一个递增的序号,使用方只能选择永远不升或者每次都全量回归。 三段各…
脚本和应用程序的一个关键区别是:脚本通常直接操作真实环境——删文件、改配置、调接口、重启服务。它没有编译期检查,没有类型系统兜底,一个拼写错误就是一次真实的生产变更。所以对脚本的要求不是"能跑通",而是"跑错了会立刻停、能看出错在哪、重跑不会更…
一条看起来人畜无害的正则,可以让服务在几十个输入字符上跑满 CPU 几分钟。这类事故的特征是:输入不长、CPU 打满、没有堆栈增长(不是死循环,是在穷举),而且只在特定格式的字符串上出现。理解引擎的执行模型之后,这类问题是可以提前看出来的。 回溯引…