同样的功能,两套代码没区别?
外包和大厂的代码 · 差在凌晨三点
激励机制决定代码质量的下限;AI 把快乐路径写到几乎免费,差距全挤进了看不见的地方
一套 KPI 种出一套代码:五层防御,逐层拆开看
掘金上有篇文章,观点很硬:外包前端和大厂前端的代码差距,根源不是能力,是激励机制。外包按项目结算、按人天计费,验收通过、尾款到账,项目就结束了;大厂长期运营、持续迭代,一个隐藏的 Bug 可能在半年后被某个边缘场景触发,变成波及几百万用户的线上事故。我顺着这条线,把 V2EX 上十几年的甲方乙方吐槽翻了一遍。结论比他还狠一层:这套机制不仅解释了代码差距,还顺带解释了为什么到了 2026 年,外包这个模式正在被 AI 从下面拆台。
同一个功能,两套代码 假设决定上限
同一个需求交付到两边,看得见的部分趋同,看不见的部分分岔——这张图就是整篇文章的论点。
评估一个前端功能的代码质量,别数用了多少设计模式,数它覆盖了几种世界。外包代码只覆盖一种:理想世界。接口返回 200,数据结构完全正确,用户操作完全符合预期——在这个世界里,代码跑得很好,验收演示那天尤其好。大厂代码默认现实世界是个充满恶意的程序:接口可能返回 500,可能返回结构完全错误的 JSON,用户可能在网络断开的一瞬间点了提交,后端可能某次发版后悄悄改了字段名。
最后一行值得单独说。localStorage 对 XSS 攻击是完全不设防的——页面一旦被注入恶意脚本,攻击者能瞬间偷走所有用户的身份凭证。大厂用 HttpOnly Cookie、输入转义、CSP 内容安全策略把这些防线藏起来,正常使用时完全感知不到,遇袭时它们是最后一道墙。这些防线在验收清单上一样都没有,所以它们不出现在外包代码里,不是人的问题。
激励机制:一套 KPI 种出一套代码 定价问题
一条是跑到验收终点就结束的短跑,一条是没有终点线的长跑——代码长什么样,取决于你跑的是哪条道。
外包的商业模式决定了它的核心 KPI:用最短的时间、最少的人力,让功能在验收演示那一天跑通。可维护性、极端边界防御、长期性能劣化——这些东西不在验收清单里,自然也不会出现在代码里。这不是外包工程师偷懒,是商业模型决定的理性选择。
代码质量不是道德问题,是定价问题。 V2EX 上一条 2021 年的老帖里,有人把这件事说得比任何文章都透:「如果钱给的多,而且后续还可能要维护,就会考虑代码的质量,至少不能坑自己。如果钱又少,后续又不需要自己维护,那不是怎么快怎么来吗?」
同一个帖子里的甲方们则贡献了另一面的真实:有人花 4 万外包一个投稿系统,验收时没细看,钱付完了正式用起来到处是问题,十几页需求文档、答疑文档、思维导图全写了照样翻车;有人总结得刺眼——甲方如果真的花那么多精力去当外包的测试工程师,这份成本甚至大于自己开发。注意,这两拨人说的其实是同一件事:你为一个“交付即静止”的系统付的钱,买不到一个“会持续变化”的系统的代码。想要后者,要么加钱,要么加工期,要么自己写。
而大厂那一边,激励机制反过来了。系统上线后要被几十个人维护三五年,人员会流动,你今天写的每一行代码,半年后可能被一个完全不认识你的同事接手。所以大厂用严苛的 ESLint、强制的 TypeScript 严格模式、残酷的 Code Review,确保合入主分支的每一行代码,任何中级工程师五分钟能看懂。变量叫 data1、组件叫 NewPage2、一个文件塞 2000 行——写的人知道不用为后续负责,这些名字才敢出现。
五层差距,逐层拆开 拿着去审源码
一次请求要穿过五层关卡才能安全到达屏幕——少任何一层,平时看不出来,出事时全是窟窿。
把“看不见的代码”拆成五层,你就能拿着这张清单去审任何一份源码,包括你自己三年前写的。
第一层 · 全链路防御
外部输入 → 状态检查 → 运行时数据校验 → 安全渲染 → 错误兜底 → UI 降级 → 错误上报,一环都不能少。特别注意:TypeScript 只保证编译期类型,它不能证明 HTTP 返回值在运行时可信——接口数据和前端之间,永远隔着一层 Schema 校验。
第二层 · 系统维度
外包的典型页面是一个 500 行的文件:请求、loading、表格、分页、筛选全堆在一个组件里。系统维度的写法会把同一个页面自然拆开:数据 hook 管状态、service 层管接口封装和错误归一化、展示组件只渲染 props、边界状态完整覆盖 loading / empty / error。区别不在技术,在为一个“会持续变化”的系统做设计,还是为一张“交付即静止”的页面做实现。
第三层 · 异常路径
快乐路径谁都会写,差距几乎全在异常路径:接口挂了怎么办?返回为空怎么办?用户疯狂连点提交怎么办?组件卸载后异步请求才回来怎么办?最后这个有个经典形态——React 组件卸载后异步回调里还在 setState,控制台里的内存泄漏警告常年没人管。一个 cancelled 标记就能修的事,写不写,取决于你有没有被这类问题咬过。
第四层 · 可观测性
外包交付的系统几乎没有前端监控:页面崩了没人知道,接口报错只看到一个白页面然后默默关掉。大厂的系统背后是 Sentry 全局异常捕获、关键业务流程逐步打点、接口响应时间和错误率的实时大盘。代码不仅要能跑,还要能被观测——每个 catch 块里都带着完整的错误上下文,让值班同学第一时间定位。
第五层 · 安全意识
就是第一节表格最后那一行。Token 存储、输入转义、CSP,正常使用时感知不到,遇袭时是墙。
打开你手上的项目,先回答一个问题:这五层里,你的代码占了几层?
2026 年的新变量 差距被拉大
机器负责把代码写得越来越快,人负责在洪流里找出那个藏在快乐路径外的窟窿。
以上都是老结论。但 2026 年有件事改变了天平:AI 让快乐路径的代码几乎免费了,于是看得见的部分趋同,看不见的部分差距反而更大。V2EX 今年有个帖子很典型:某公司内部评审认为 6 万行代码足以实现所有功能,外包交付时交了 18 万行——大面积 AI 生成的产物。帖子里的高赞评论一针见血:「如果是大模型生成的代码,又何必找外包第三方呢?甲方自己调用大模型不就好了,而且甲方自己更懂自己的需求。」
另一条评论更值得抄在墙上:「改不动的代码便宜,改的动的代码贵。」把这两条放一起,外包这个模式的处境就清楚了:它最核心的卖点是“用更低的成本把功能堆出来”,而这个卖点正在被 AI 直接商品化。当甲方自己调模型就能生成能跑的系统,“外包比自建便宜”这个前提就开始松动。外包剩下的生存空间,只剩两样:一是 AI 也搞不定的复杂业务上下文,二是出事之后有人负责——而后者,恰恰是这套激励机制历来最不愿意为之付费的东西。
AI 时代值钱的不再是“把功能写出来”,而是“定义什么算对”。 写功能的部分在飞速贬值,能写验收标准、能设计异常路径、能搭监控告警的人,反而更贵了。因为机器产出的是代码,验收产出的是信任。所以别问“AI 会不会取代前端”。要问:你的工作里,有多少比例是在生产快乐路径,多少比例是在守护异常路径?后者才是你的护城河。
不管你在哪,五层是你自己的 六问
原作者最后有句话我很认同:外包的代码不是烂,它只是在一套不同的规则下做出了最理性的选择。如果你给大厂高级前端两周交付一个完整管理系统的预算,他写出来的代码大概率和外包没有本质区别——极度压缩的时间里,任何人都会砍掉现在看不到价值的东西。但有个动作是任何人都能立刻做的:在每个项目里多加一层错误兜底,多写一行类型校验。这些看不见的代码不涨薪、不进周报、验收时没人看,但它们是唯一能跟着你走的东西——换公司、换城市、换技术栈,都带得走。
把这张清单存下来,下次 review 代码时对着数:
- 每个网络请求,HTTP 状态码校验了吗?
- 接口数据过运行时校验了吗,还是直接信了 TypeScript 的类型?
- loading / empty / error 三种边界状态 都有对应 UI 吗?
- 异步请求有取消机制吗,组件卸载后还会 setState 吗?
- catch 块里是 console.error,还是带着上下文上报?
- Token 在 localStorage 里吗?
六问里答不上来的,就是你这周可以补的第一课。
最后
外包和大厂的代码差距,拆到底是一道算术题:为看不见的东西付费的意愿,决定了代码的质量下限。大厂付得起,因为它运营得久;外包付不起,因为它交付完就走。而 2026 年的 AI 把这道题改了个条件——生成看得见的代码不再需要付任何人的费,于是所有剩余的价值,都压在了那些看不见的层里。
凌晨三点被 P0 电话叫醒过的人,和没被叫醒过的人,写的代码注定不是一个物种。但叫醒你的不一定是大厂的系统——也可以是你自己项目里那条没人看过的 catch。
看得见的代码越来越便宜,看不见的层越来越贵。
本文由 AI图鉴自动抓取并翻译,版权归原作者所有;如需查看原文请点下方链接。
Same function. Two sets of codes?
The code for outsourcing and the big factory is at 3:00 in the morning.
Incentives determine code quality floors; AI writes happy paths to almost free, and the gaps are pushed into invisible places.
One set of KPIs to grow a code: five layers of defense, one layer by one. Look.
There are articles on gold mining with a strong view: code gaps at the front end of outsourcing and at the front end of a large plant are rooted not in capacity but in incentives. Outsourcing is done on a project-by-project basis, with acceptance check passed and the final payment paid, and the project is closed; a large plant is running on a permanent and continuous basis, and a hidden Bug may be triggered by a marginal scenario in six months' time, turning it into an online accident affecting millions of users. I went through this line and turned the A-B-Talk for over a decade. The conclusion is even worse: the mechanism explains not only the code gap, but also why in 2026 the outsourcing model was being dismantled by AI from below.
The same function, two sets of codes.
The same demand is delivered to both sides, where the visible parts converge and the invisible parts are confused — this figure is the argument of the entire article.
To assess the quality of the code for a front-end function, how many design models have been used and how many worlds it covers. Outsourcing codes cover only one: the ideal world. The interface returns 200, the data structure is perfectly correct, and the user is operating in full compliance with expectations — in this world, the code runs well, especially on the day of the acceptance check demonstration. Large plant code defaults that the real world is a malicious process: the interface may return 500, the JSON may return to a completely faulty structure, the user may have submitted at an instant point when the network is disconnected, and the back end may have changed the name field quietly after a release.
The last line deserves to be said alone. The localStorage attack on the XSS is completely undefended - once the page is injected into a malicious script, the assailant can immediately steal all the user IDs. With HtpOnly Cookie, input conversion, CSP content security strategy, the main plant hides these lines, which are completely undetected during normal use and are the last wall in the attack. These lines are not on the acceptance check list, so they do not appear in outsourcing codes and are not human problems.
Incentive mechanisms: a set of KPIs to plant a set of codes pricing problems
One is a short run to the end of acceptance check, and one is a long run without a finish line — depending on which path you run.
The business model of outsourcing determines its core KPI: to run the function at acceptance check with the shortest time and minimum manpower. Maintainability, extreme border defence, poor long-term performance - It's not on the acceptance check list, and naturally it's not in the code. This is not a laziness on the part of outsourced engineers. It is a rational choice determined by business models.
Code quality is not a matter of ethics, but of pricing. In a previous post from 2021 V2EX, it was said more than anything: "If more money is given and it may be maintained, the quality of the code will be taken into account, at least not on its own." If the money is small and then you don't have to keep it for yourself, how quickly can you come?"
In the same post, the A side contributed to the other side of the story: someone spent 40,000 dollars out of a filing system, acceptance check did not look at it carefully, paid out of official use was a problem, and more than a dozen pages of demand files, answer papers, thought maps were all over the car; and someone summed up that the A side was even more expensive to develop if it really spent so much effort to become an outsourced test engineer. Note that the two dials are actually talking about the same thing: you can't buy a system code that's going to change when you pay for a delivery or static system. If you want the latter, you can either raise the money, process it, or write it yourself.
And on the other side of the big factory, the incentive is the reverse. When the system goes online, dozens of people are left on the line for three or five years, people move around, and every line you write today can be taken over by a colleague who doesn't know you at all. So the big factory uses a tough ESLint, a mandatory TypeScript strict model, a cruel Code Review, to make sure that every line code in the main branch can be read by any mid-level engineer for five minutes. The variable is called Data1, the component is NewPage2, and a file plug 2,000 -- people who write know that they don't have to be responsible for the follow-up, and they don't appear.
Five layers of gap, one layer at a time. Take it to the source. Code
A request is made through a five-storey level to reach the screen safely — without any layer, which is not normally visible, and when it happens it is full of holes.
Break the invisible code down to five layers, and you can take this list and examine any source code you wrote three years ago.
First level - full chain defense
External input status check → data validation while running → security rendering → error-deep UI down → error-reporting, none less. In particular: TypeScript ensures only the type of compilation period, which does not prove that the HTTP return value is trusted at the time of operation - between interface data and the front end, always in a single layer of Schema verification.
Second level. System dimensions
The typical page outsourced is a 500-line file: request, loating, table, page break, filtering all over one component. The system dimension is written in such a way that the same page is automatically removed: data hook pipe state, service pipe interface encapsulation and error integration, displaying only props for components, complete boundary status overloading. The difference is not between technology, design for a “continuous change” system or a “delivery is static” page.
Third level. Anomalous path.
Anyone can write a happy path, and the gap is almost entirely on an abnormal path: what if the interface dies? What if it's empty? What if the user goes crazy? What if you ask to walk back after the components are unloaded? Finally, there's a classic pattern -- react components are unmounted and retrospect is still setstate, and the memory leak warning on the console is left unattended. It depends on whether you've been bitten by a problem like this.
Level 4 - Observability
There are virtually no front-end controls for outsourced deliveries: no one knows that the page collapses, and the interface is misreported only by seeing a white page and then turning it off. Behind the large plant system is a big, real-time disk of the set of global abnormal catch, step-by-step points for key business processes, interface response times and error rates. The code is not only capable of running, it's also capable of being observed -- each catch contains a complete error of context, which allows the duty class to locate at first sight.
• Security awareness
The last line of the first section of the table. Token storage, input conversion, CSP, undetected during normal use, wall in case of attack.
Open the project in your hand and answer one question: How many layers of the five are your code?
In 2026, the new variable was widened.
The machine is responsible for writing the code faster and faster, and the man is responsible for finding that hole in the flood.
These are old conclusions. But in 2026, something changed the scales: AI made the code of happy paths almost free, so the visible parts converged, and the invisible parts became even bigger. V2EX has a typical post this year: an internal review of a company found that the 60,000-line code was sufficient to perform all the functions, and 180,000-line products were delivered when outsourced - large-scale AI products. "If it's a code created by LLM, why should we find a third party to outsource?" It is not enough for A to call LLM itself, and it is better for A to know its own needs”.
Another comment is more worth copying on the wall: "The unaltered code is cheap and the altered code is expensive." When we put the two together, the situation of outsourcing is clear: Its central selling point is "to stack the function at a lower cost," which is being commercialized directly by AI. The premise of “outsourcing is cheaper than self-building” began to loosen when the A side model itself could generate a running system. There are only two ways to outsource the remaining living space: the complex business context, which AI can't handle, and the responsibility that comes after the incident — and the latter, which is exactly what the incentive mechanism has been most reluctant to do for paid.
AI is no longer “writing functions”, but “defining what is right”. The part of the function is devalued at a fast pace, and it is more expensive to write acceptance criteria, to design an abnormal path, to carry a surveillance alarm. Because the machine produces code, acceptance check produces trust. So don't ask "AI will replace the frontend." Question: What percentage of your work is on a happy path to production, and what percentage is on the path to safeguarding anomalies? The latter is your moat.
Wherever you are, the fifth floor is your own.
The original author concluded by agreeing that the outsourcing code was not bad, but that it made the most rational choice under a different set of rules. If you deliver a full management system budget to the senior front end of a large plant for two weeks, there is no difference between the probability of the code he wrote and the quality of the outsourcing — in a time of extreme compression, anyone will cut off what is not now valuable. But there's one thing anyone can do right away: Add an additional error loop to each project and write an additional line of type verification. These invisible codes don't get paid, they don't get read in the weekly papers, they're the only ones that can follow you — change companies, change cities, change technology bars.
Save this list. Next time you review the number:
- Every network request, HTTP status code checked?
- Did you check the interface data while running, or did you directly write the type of TypeScript?
- Does all three border states match UI?
- Is there a cancellation mechanism for walk-in requests, and is there a setstate when components are unloaded?
-Catch, Console.error, or report with context?
- Token in the localStorage?
It's your first lesson this week.
Finally.
The code gap between outsourcing and large plants is an arithmetical question: the minimum quality of the code is determined by the will of the invisible paid. Large plants can afford it because it has been in operation for a long time; outsourcing cannot afford it because it leaves after delivery. And in 2026 AI changed the subject to a condition -- to create visible codes that no longer cost anyone, and all the remaining values were placed in invisible layers.
Those who were awakened by the P0 phone at 3 a.m. and those who were not, the code is not a species. But waking you up isn't necessarily the big factory system -- it's the catch that nobody saw in your own project.
The visible code is getting cheaper and the invisible layers are getting more expensive.
Auto-fetched and translated by AI Atlas. All rights belong to the original author.