侧边栏壁纸
  • 累计撰写 259 篇文章
  • 累计创建 73 个标签
  • 累计收到 6 条评论

目 录CONTENT

文章目录

创造一个屎山,需要分几步

橙序员
2026-02-10 / 0 评论 / 0 点赞 / 357 阅读 / 6,628 字 / 正在检测百度是否收录... 正在检测必应是否收录...
文章摘要(AI生成)

这篇文章探讨了“屎山”项目的概念,指出几乎每个程序员在职业生涯中都可能会接触到这样的项目。屎山项目通常是由于一系列妥协和缺乏设计造成的,即使能正常运行,却存在维护困难、逻辑混乱和高耦合等问题。文章描述了屎山的形成过程,包括需求不明确、架构设计缺失以及代码质量不重视等因素。 屎山的根本在于项目初期的心态,团队往往优先考虑快速上线而忽略了后续维护和结构设计。作者强调,屎山并非一蹴而就,而是通过不断的“先上线再说”逐步累积形成的。为了避免创建屎山,程序员需要意识到这些潜在的风险,并在项目中设立清晰的标准。 文章提供了一些“实操指南”,如在项目初期避免过度设计,保持代码命名模糊,使用复制粘贴提高效率等,旨在帮助程序员理解屎山的成因,从而在未来的工作中规避类似错误。最终,作者希望读者能从中吸取教训,避免成为屎山项目的建设者。

为什么每个程序员都逃不过屎山

几乎每个程序员,在职业生涯的某个阶段,都会遇到一个项目。

你一打开代码仓库,手已经离开键盘,眉头开始自动皱起。文件名看不懂,方法名像密码,业务逻辑靠“感觉”在流动。

这时候你通常会说一句话:“WC,这是什么屎山啊?”

如果你想要在公司无可替代,又能在领导前彰显你的价值,创作和维护一个屎山是你的必经之路,那么要想创造一个只有你能维护的屎山,首先我们得知道:


什么是屎山(项目)?

屎山项目并不等同于“代码烂”。真正的屎山,通常具备以下特征:

  • 能跑,但没人敢动(我没动,从我来的时候就是这样!)
  • 改一个地方,要全项目跟着回归(这影响很难评估,需要整体回归!)
  • 逻辑不是写出来的,是“堆”出来的(只要产品一句话,我就加加加)
  • 没有明显错误,但处处是风险(能run,但是时不时的来个内存溢出和线上P0啥的)

它不是一坨明显的 Bug,而是一整套高度脆弱、强耦合、低可读性的系统。

最讽刺的是:👉 屎山项目,往往还是公司的“核心系统”(所以想要不可替代,就要拉一个AI都挖不动的山!)


屎山不是一天建成的

没有哪个程序员第一天上班就说:“今天我要写一坨屎。”

屎山的形成过程,通常是这样的:

  • 第一次妥协:“倒排的需求时间紧任务重,这个地方先硬写吧”
  • 第二次妥协:“本来打算年前优化的,结果KPI还没达成。管他呢,反正已经乱了,再加一点也无所谓”
  • 第 N 次妥协:“上年都这么过来了,今年就别动了,领导OKR没他了,能用就行”

最终你回头一看,发现已经没有“正确的重构时机”了。屎山的本质,是无数次「先这样吧」的叠加。


先免责声明:本文宗旨不是教你变坏,不是教你如何去造一座屎山坑害同事、消耗自己,而是帮你看清——屎山从来都不是突然出现的,它的每一步,都藏着我们曾经的妥协和侥幸。看懂了屎山的形成逻辑,你才能在未来的工作中,避开那些埋雷的瞬间,要么拒绝造山,要么在屎山里找到破局之路。

so,下面我们来看看如何创建一个无法搬动的屎山吧


第一步:饼够大,梦够远

回头看很多屎山项目,你会发现一个共同点:问题不在代码,而在立项那一刻的心态。

我参与过不少项目,几乎每一个屎山,开头都很相似。

需求讨论会上,大家其实都很忙。产品想的是尽快落地,业务想的是先跑起来,先体现出项目价值(老许,大饼你要不要),技术想的是别把事情搞复杂。于是有些问题,被非常自然地跳过了。

比如:这个系统的边界到底在哪?项目上线第一版要解决的核心问题是什么?项目有哪些东西,是明确不做的?没人明确说“不重要”,但大家都默认——先别纠结这些。


技术选型通常也是在这种氛围里完成的。不是不专业,而是太现实

“这个框架挺火的”“以后扩展性会好一点”“万一后面要接更多业务呢”

这些理由单独看都成立,但组合在一起,往往意味着一件事:**我们在一个还没跑稳的项目上,提前背上了复杂度。**很多新技术在你遥远的梦中变成现实匆匆落地了,很好,你的屎山有了一个很好的铺垫。

当时不会觉得这是问题。直到某一天你发现,新人连项目都跑不起来,你才意识到:技术选型,已经变成了进入项目的第一道门槛。


更关键的是,立项阶段通常没人会认真讨论“维护成本”。项目默认是:

  • 做完一版就会有人接手
  • 需求会慢慢稳定
  • 后面有时间再重构

但现实是:

  • 需求只会越来越多
  • 时间只会越来越少
  • 原作者迟早会离开

所以,屎山第一步就是在项目一开始,进入一种隐含状态:**只要能按期上线,就算成功。**而代码质量,请放到“以后再说”。


这时候你要有足够的顿感力,等让团队意识到屎山的时候,你的项目往往已经跑了半年。那么此时业务是活的,数据是真实的,线上已经有人在用。这时候再去谈“重新设计”“边界清晰”,已经不现实了。

所以你的屎山就成了。记住:屎山不是被设计出来的,而是在一次次“先上线再说”中,被默认接受的。所以要保持一个空洞的脑袋,和想啥做啥的状态


第二步:没架构,不设计

想要成功打造一个屎山项目,有一条黄金原则你必须牢记:架构这件事,绝对不能太认真。

认真了,就容易清晰;清晰了,就不利于后期发酵。


一开始,项目刚启动的时候,其实是最危险的阶段。因为这时候:

  • 需求少
  • 代码干净
  • 脑子也清醒

**如果这个阶段你真的坐下来画架构图,那屎山基本就胎死腹中了。**所以正确做法是——用“先写再说”压制一切设计冲动。


当有人提出:“要不要先定下整体结构?”你可以很自然地回应一句:“现在需求还不稳定,设计了也会推翻。另外我们二季度的OKR方向还未定,所以不要过度设计”

这句话非常关键,它能完美达成三点效果:听起来很理性,显得你有经验,并且成功跳过架构设计

于是你的代码就获得了自由生长的权利,新人也有了可以大展身手的空间。


接下来,在写代码的过程中,你要遵循一个核心策略:让结构跟着功能走,而不是让功能服从结构。

来一个需求,加一段逻辑。逻辑该放哪?哪里顺手放哪里。

  • Controller 里能写,就别新建类
  • Service 能解决的,就别拆模块
  • 实在不好放的,就丢到一个“通用”类里
  • 实在想要体现能力,就写一个 util 类

时间一久,你会得到一种非常理想的架构状态:任何地方,都能改任何东西。


为了进一步巩固屎山结构,你还需要刻意模糊模块边界。比如:

  • A 模块需要点 B 的数据?直接调
  • B 模块反过来用 A 的逻辑?也没问题
  • 循环依赖?那说明它们关系紧密

边界一旦清晰,维护成本就下降了,这是我们不希望看到的。


当项目发展到一定规模时,有人可能会开始不安。

他们会说:“这里是不是该拆一下?”这时候你要立刻启动屎山防御机制:“这个地方太核心了,别动,风险太大。”

这句话的妙处在于:没人敢反驳,也没人愿意背锅,而且架构问题被永久冻结

从此,这段代码正式升级为屎山核心区


记住,在架构阶段,你的目标不是“混乱”,而是打造一种更高级的状态:看起来像是有架构,但实际上没有人说得清楚。

只要做到这一点,你就成功为后续编码阶段,打下了一座坚实、松软、可持续扩建的屎山地基。


好,进入屎山的核心产线了 😎
这一章开始,是真正的“实操指南”。


第三步:当下懂,之后蒙

如果说前面的立项和架构只是埋雷,那编码阶段,就是屎山的主要生产车间

在这里,你的目标只有一个:让代码在“能跑”的前提下,尽量不可读、不可推理、不可重构。


写代码时,第一件事要注意的不是逻辑,而是命名。命名一定不能太明确。名字一旦准确,别人就容易理解你在干什么。

推荐策略是:能用 data 就别用 orderList,能用 temp、a、b、c 就别用 result,同一个概念,在不同文件里起不同名字(你的英语也不好,经常repository、repostory不分)

最理想的效果是:变量名本身,不提供任何语义信息。


接下来是提升产量的关键技巧:复制粘贴

为什么要封装?为什么要抽公共方法?复制一份代码再改一行,才是效率最高的做法。

这样做有几个好处:改需求时,永远改不全;修 Bug 时,总会漏一个;运行行为不一致,但看起来一模一样

时间久了,你会得到一片非常自然的代码森林。


然后是逻辑组织。屎山代码的理想形态,是所有业务规则都直接写在流程里

  • if 能解决的,就别建对象
  • 嵌套能写三层,绝不写两层
  • 三元表达式能套,就一定要套

尤其推荐在一个方法里:校验参数、查询数据库、计算业务规则、组装返回值(如果可以,请在一个只有你维护的依赖库里再封装一个没有注释的切面)

方法越长,定位问题时越有成就感。


至于注释,这是一个很容易被误用的工具。正确的屎山注释应该满足两个条件:数量极少且内容高度误导

经典模板包括:

// 临时处理(产品说XXXX)
// 这里比较特殊(XXX给结论要特殊处理)
// 后面可能会改(leader后续规划)

最完美的情况是:注释存在,但已经失效多年。即使你在也可以按图索骥去甩锅(甩锅的顺序是先甩给不再的人,再甩给产品,甩给实习生,实在不行才留给自己当时排期太紧没有做实现或设计)


最后,一定要让代码和业务强绑定。不要抽象业务概念,直接把规则写死在逻辑里。

  • 状态值直接用数字
  • 枚举能不用就不用
  • 数据库字段语义靠口口相传

这样一来,任何业务变动,都会自然扩散成全项目改动。


当你做到以上几点,你的代码将具备一个优秀屎山应有的特质:每一行当下都“合理”,但整体无法理解。

第四步:时间紧,任务重

真正成熟的屎山,从来不是慢慢写出来的,而是被时间压力强行催熟的

如果没有 DDL(Deadline),屎山只能算是潜力股。


当项目进入冲刺期,你要牢牢记住一句话:时间不够,是一切技术问题的终极理由。

它可以解释:为什么不重构,为什么不拆模块,为什么直接在旧逻辑上硬加

而且,没人会反对。


在 DDL 面前,任何“更好的方案”都是多余的。当有人说:“这样写以后不好维护。”

你只需要回答:“排期不够,现在先上线,后面再说。”,而且记住,这句话的真正含义是:后面永远不会再说。


时间紧的时候,千万不要停下来“整理代码”。整理意味着风险,风险意味着延期,延期意味着你要解释。

相比之下,往现有逻辑里再塞一段 if,是最安全的选择。

于是屎山开始进入一个非常稳定的增长曲线:

  • 新需求 → 新分支
  • 新场景 → 新判断
  • 新规则 → 新特例

没有一个需求是重写的理由,每一个需求都是加法。


此时你还需要刻意培养一种氛围:**“这段代码太关键了,别动。”**如果必要,在工作量大的时候让其他组同学来协助你,让外人来改你的屎山是体现你价值的重要一步,这一点千万要记住(如果出问题你一定要记住它在你手里是好的)

一旦某段代码被贴上“核心”“关键路径”的标签,它就拥有了免重构权。哪怕它本身就是问题源头。


在时间压力下,技术债会被统一收纳进一个地方:脑海里的“以后”:以后再拆,以后再优化,以后再补测试

而现实是,DDL 只会越来越近,从不越来越远。


当项目多次在这种节奏下交付,你会发现一件很美妙的事:**屎山开始具备自我保护能力和自我繁殖能力。**它不需要你刻意维护,时间和需求会自动帮你加高、加厚、加复杂。


第五步:整体OK,先上线

当代码写完、DDL 逼近时,你已经成功培育出一座半成熟屎山。接下来要做的,是确保它顺利上线,而不是被测试拖死。


测试这件事,一定要保持“象征性”。理想状态是:本地能跑,接口能通,页面不白

至于边界条件、异常路径、并发场景——**那是未来的问题。**毕竟需求都没想清楚,测试又怎么可能写完整。


测试环境也要尽量贴近真实世界,但又不要太真实。

  • 数据不全,正好验证代码“健壮性”
  • 配置不一致,方便上线后再修
  • 偶尔出问题,用“环境差异”解释

只要你自己都搞不清楚环境问题,那就说明测试已经达到了应有的混乱程度。


发布之前,总会有人提一句:“要不要再回归一下?”

这时候你要迅速判断形势。如果没人明确负责回归,那答案就是:没必要。

因为真正的屎山哲学是:没有测试,比有不完整的测试更安全。

有测试,反而会暴露你的代码有问题。


上线流程一定要干脆:合并代码要快,回滚方案要模糊,发布窗口越短越好

最好能在上线后立刻进入下一个需求,不给任何人“冷静分析刚刚发生了什么”的时间。


一旦上线成功,不管过程多惊险,都要迅速形成结论:“问题不大,整体是稳定的。”

这句话非常重要,它会直接把当前状态固化为“可接受状态”。要记住,只要你那记事本里的一堆运维接口也能搞定那就不算大问题。从这一刻起,所有线上行为,都会被当作既定事实来维护。


如果上线后出了问题,也不要慌。补丁是屎山的天然养料。

哪里出问题,哪里加判断;能兜底,就别深挖;线上修完,立刻忘掉

只要系统还能跑,这次发布就可以被定义为“成功”。至此,一座能运行、能交付、能不断打补丁的屎山,已经正式投入使用。


稳了,这一章是屎山真正进入“生态系统”阶段 😌
从这里开始,你甚至不需要再主动造,它会自己长。


第七章:难读懂,难维护

当一个项目进入维护期,很多人会以为节奏会慢下来。但对屎山来说,这才是黄金时代。


维护阶段的第一个特征,是没人再愿意大改代码。代码已经跑了一段时间,数据是真实的,业务是依赖的。

这时候你只需要反复强调一句话:“先别动大的,风险太高。”这句话一旦成为共识,项目就会进入只加不减的状态。


接下来的所有需求,都会以一种非常优雅的方式进入系统:在原逻辑上加判断。

你不用设计新结构,也不用拆旧模块。只需要在合适的位置问一句://如果是新场景,那就走另一条分支

这样做的好处是:

  • 不会影响旧逻辑
  • 不需要额外测试
  • 看起来非常稳妥

坏处?那是以后才需要考虑的。


维护期还有一个重要变化:**“理解成本”开始超过“修改成本”。**新接手的人发现:看懂代码要半天,改一行只要五分钟于是他们会非常理性地选择:**少看,多改。**而这,正是屎山最理想的繁殖方式。


随着补丁越来越多,你会发现一个现象:某些文件,开始被“供起来”了。改动频率极高,出问题概率极高,但没人敢动结构。它们会被称为:核心模块/历史代码/老逻辑

这些名字,本质上只有一个含义:这里已经失控,且被默认为不可触碰。


此时,屎山已经具备了完整的自我保护机制:

  • 改动会引发未知问题
  • 风险无法评估
  • 最安全的方式是继续堆

从此以后,每一次维护,都会自然地增加复杂度。你甚至不需要刻意为之。

来了,这一章是屎山的成人礼
一旦走到这里,项目基本就稳态运行了。


第八章:调部门,换工作

一座真正成熟的屎山,必须脱离原作者的控制。只要原作者还在,代码就还有被解释、被修正的可能。所以,人员流动是屎山进化过程中不可或缺的一环。


最理想的情况,是原作者逐步淡出。

  • 忙于新项目
  • 不再碰老代码
  • 只在关键时刻“帮忙看一眼”

这会让代码进入一种非常微妙的状态:有人知道它,但不再负责它。


交接阶段也要把握好尺度。交接文档当然可以有,但一定要停留在表面。要写一下系统整体介绍、模块大概功能、接口大概用途

至于:为什么当初这么设计、哪些地方不能动、哪些逻辑是补丁

这些信息,不必明确传达。理解成本越高,屎山越安全。


新接手的人,往往是最好的“屎山继承者”。他们面对的是:

  • 已在线上运行的系统
  • 没有完整背景的代码
  • 随时可能出问题的业务

在这种环境下,最理性的选择只有一个:不重构,只适配。

他们会非常谨慎地:

  • 在现有结构上加逻辑
  • 避开“看不懂”的部分
  • 用经验而不是理解解决问题

屎山,开始真正脱离个人,变成一种组织资产


随着人员继续流动,项目会逐渐形成一种文化:

  • 老代码不碰
  • 新需求就加
  • 出问题就补

没有人能说清楚全貌,但每个人都能改一小块。这是屎山最稳定、也最持久的形态。


完结章来了 😎
这一章负责盖棺定论 + 情绪收口 + 掘金味收尾


恭喜你,已经成功造出一座屎山

如果你一路看到这里并有一种他乡遇故知的感觉,那说明一件事:**这套流程你并不陌生。**甚至可能看到某些段落里代入了,你还下意识点了点头。


一座合格的屎山,其实并不需要满足所有条件。只要具备以下几项,就已经非常成功了:

  • 系统稳定运行,但没人敢动
  • 新需求永远只能“往里加”
  • 出问题靠经验兜底,而不是理解
  • 原因没人说得清,历史无人能还原

如果你的项目已经这样,那基本可以确认——屎山已经进入完全体形态。


这时候再讨论“当初为什么不设计好”,已经没有太大意义了。因为屎山的真正可怕之处在于:它并不是某一次错误决策造成的,而是一连串看似合理选择的自然结果。每一步都能解释,但合在一起,就没有退路。


更微妙的是,屎山并不会立刻带来灾难。它能交付、能上线、能支撑业务。甚至在某些阶段,它还是“功臣系统”。正因为如此,它才得以长期存在,并不断被加高、加厚、加复杂。


如果你能把这篇文章当成一份**“反向操作指南”**,那它的价值才真正成立。当你在下一个项目里:

  • 想直接往旧逻辑里塞代码时
  • 想用“以后再说”跳过设计时
  • 想用“太核心了别动”来冻结问题时

你可能会突然意识到:**哦,这一步,是在造屎山。**只要这一刻你停下来,哪怕只犹豫十秒,屎山就可能少长一层。


如果你看完文章发现已经身陷屎山,那我送一套屎山指数自测表给你:

  • 项目里没有完整的架构图和需求文档,核心逻辑全靠口口相传?(10分)
  • 变量命名全是 data、temp、flag,看半天不知道是什么意思?(10分)
  • 改一行代码,牵出3个以上bug?(15分)
  • TODO 列表比代码还长,且大部分 TODO 已经存在超过6个月?(15分)
  • 线上出问题,日志里找不到有效信息,只能靠猜?(10分)
  • 有一段代码,没人敢改,也没人能说清它的作用?(15分)
  • 新需求只能往旧逻辑里塞,不敢新增模块也不敢重构?(15分)

评分标准:

  • 0-30分:正常项目,继续保持,警惕埋雷(你不重要阶段);
  • 31-60分:轻度屎山,及时优化,还能挽救(没你也行阶段);
  • 61-85分:中度屎山,需要系统性重构,难度较大(没你不行阶段);
  • 86-100分:重度屎山,建议做好交接,准备跑路(你行不行阶段)。

最后送你一句屎山工程师的至理名言:不是每个项目都值得被拯救,但每个屎山,都是被一步步造出来的。

0

评论区

欢迎访问shiker.tech

请允许在我们的网站上展示广告

您似乎使用了广告拦截器,请关闭广告拦截器。我们的网站依靠广告获取资金。

订阅shiker.tech

文章发布订阅~

通过邮箱订阅文章更新,您将在文章发布时收到及时的邮件提醒~