没有向上抽象的思维,讨论设计就是讨论吃屎
咱们这行天天开会讨论技术,听起来挺高端,实际上跟讨论吃屎分几个步骤没啥区别——第一步开嘴,第二步把屎塞进去,第三步闭嘴。三步走完,周报上写"已完成需求开发",屎味四溢,产能翻倍,老板点赞。
这篇献给所有把产品原型当 ER 图、把 ext_info 当万能抽屉、把 AI 当挡箭牌的同仁。也献给三年前的我自己。
一、那个下午,我对着表结构陷入了沉思
"用户管理模块的数据表设计,大家看一下。" 技术总监老 K 把投影切到 Navicat。
屏幕上是一张 <font style="color:rgb(34, 34, 34);background-color:rgb(248, 248, 248);">t_user</font> 表,字段列表像裹脚布一样往下滚:
user_name, password, nickname, avatar_url, phone, email, gender,
birthday, province, city, district, address_detail, id_card,
real_name, wechat_openid, qq_openid, alipay_user_id,
last_login_time, last_login_ip, login_fail_count, account_locked,
locked_until, register_time, register_ip, register_channel,
invite_code, inviter_id, user_level, user_points, user_balance ......
"停停停。" 我实在忍不住了,"这表是谁设计的?"
"产品原型上有这些字段啊。" 后端主力小张理直气壮,"产品经理画的个人资料页里要展示这些信息,我们就照着建表呗。"
我深吸一口气:"那好,我问你——<font style="color:rgb(34, 34, 34);background-color:rgb(248, 248, 248);">wechat_openid</font>、<font style="color:rgb(34, 34, 34);background-color:rgb(248, 248, 248);">qq_openid</font>、<font style="color:rgb(34, 34, 34);background-color:rgb(248, 248, 248);">alipay_user_id</font> 这三个字段,有没有发现它们本质上是同一类东西?"
"呃……都是第三方登录的标识?"
"那你为什么建了三个字段,而不是一张 <font style="color:rgb(34, 34, 34);background-color:rgb(248, 248, 248);">t_user_third_party_auth</font> 关联表?"
小张愣了愣:"产品原型上就是这么画的啊,微信登录一个框,QQ 登录一个框,支付宝登录一个框……"
"所以你就建了三个字段。将来要接入抖音登录,再加一个 <font style="color:rgb(34, 34, 34);background-color:rgb(248, 248, 248);">douyin_openid</font>。要接入 Apple 登录,再加一个 <font style="color:rgb(34, 34, 34);background-color:rgb(248, 248, 248);">apple_user_id</font>。这张表最终会有五十个第三方登录字段,像不像一条被塞满各种杂物的裤衩?"
会议室沉默了。
这就是第一种吃屎姿势:产品原型画成什么样,数据库表就设计成什么样。产品经理在 Axure 里拖一个输入框,后端就加一个字段;产品经理画一个 tab 页,后端就建一张表。美其名曰"快速响应需求",实际上是把数据库当成了产品原型的像素级复刻。
有没有人向上问一句:这些字段在业务上究竟是什么关系?它们是同一个实体的属性,还是应该被抽象成独立的实体?
没有人问。因为问这个问题需要抽象思维,而抽象思维需要动脑子。动脑子累,照着原型建表多轻松啊——屎来伸手,屎去张口。
二、吃屎的三种专业姿势
姿势一:产品原型驱动数据库设计——把需求文档当 ER 图
"产品让我加一个收货地址,我就给订单表加 <font style="color:rgb(34, 34, 34);background-color:rgb(248, 248, 248);">receiver_name</font>、<font style="color:rgb(34, 34, 34);background-color:rgb(248, 248, 248);">receiver_phone</font>、<font style="color:rgb(34, 34, 34);background-color:rgb(248, 248, 248);">receiver_province</font>、<font style="color:rgb(34, 34, 34);background-color:rgb(248, 248, 248);">receiver_city</font>、<font style="color:rgb(34, 34, 34);background-color:rgb(248, 248, 248);">receiver_district</font>、<font style="color:rgb(34, 34, 34);background-color:rgb(248, 248, 248);">receiver_address</font> 六个字段。简单粗暴!"
确实简单。一个月后,产品说一个订单要支持多个收货地址(分批发货)。你怎么办?再加六乘 N 个字段?还是把订单表拆成 <font style="color:rgb(34, 34, 34);background-color:rgb(248, 248, 248);">t_order</font> 和 <font style="color:rgb(34, 34, 34);background-color:rgb(248, 248, 248);">t_order_shipment</font>?
后者需要抽象——你需要理解"订单"和"发货单"是两个不同的领域实体,它们之间是一对多的关系。但你没有这个意识,因为产品原型上"订单详情页"就是把收货地址嵌在里面的,你就原样搬到了数据库里。
这是一种病,学名叫"原型依存型数据库设计综合征"。患者临床表现包括但不限于:
- 产品经理画了几个筛选条件,他就建几个索引,从不问这些查询场景是否真的存在
- 产品经理说"这个字段以后可能用到",他就加一个
<font style="color:rgb(34, 34, 34);background-color:rgb(248, 248, 248);">varchar(255)</font>的<font style="color:rgb(34, 34, 34);background-color:rgb(248, 248, 248);">ext1</font>、<font style="color:rgb(34, 34, 34);background-color:rgb(248, 248, 248);">ext2</font>、<font style="color:rgb(34, 34, 34);background-color:rgb(248, 248, 248);">ext3</font> - 产品经理画了一个"用户标签"的多选框,他就给用户表加一个逗号分隔的
<font style="color:rgb(34, 34, 34);background-color:rgb(248, 248, 248);">tags</font>字段,然后在查询时写<font style="color:rgb(34, 34, 34);background-color:rgb(248, 248, 248);">FIND_IN_SET</font>自我感动
你看,数据库设计本质上是抽象建模的过程。你需要从纷繁的业务需求中提炼出核心实体、属性和关系。但很多人做的是反向建模——把 UI 上的每一个像素都映射成数据库里的一个字段,仿佛产品原型就是上帝赐予的 ER 图。
屎的形状取决于产品经理那天画原型时喝了多少咖啡。
姿势二:万物皆可 JSON——用 ext_info 字段埋葬一切建模
这是高阶姿势。初级选手才会复制粘贴 Controller,中级选手早就学会了"灵活设计"——给每张表加一个**** **<font style="color:rgb(34, 34, 34);background-color:rgb(248, 248, 248);">ext_info</font>** / **<font style="color:rgb(34, 34, 34);background-color:rgb(248, 248, 248);">config_json</font>** / **<font style="color:rgb(34, 34, 34);background-color:rgb(248, 248, 248);">attrs</font>** ****字段,JSON 存储,啥都往里扔。
需求来了:"订单要支持发票信息。" "简单,在 <font style="color:rgb(34, 34, 34);background-color:rgb(248, 248, 248);">t_order</font> 的 <font style="color:rgb(34, 34, 34);background-color:rgb(248, 248, 248);">ext_info</font> 里加个 JSON 字段。"
又来:"订单要支持优惠券核销记录。" "简单,<font style="color:rgb(34, 34, 34);background-color:rgb(248, 248, 248);">ext_info</font> 里再塞一个数组。"
再来:"订单要记录分销商的返佣规则。" "简单,<font style="color:rgb(34, 34, 34);background-color:rgb(248, 248, 248);">ext_info</font> 里加个嵌套对象。"
半年后,你打开线上一条订单的 <font style="color:rgb(34, 34, 34);background-color:rgb(248, 248, 248);">ext_info</font>,里面是一坨 4KB 的 JSON,<font style="color:rgb(34, 34, 34);background-color:rgb(248, 248, 248);">ext_info</font> 里嵌套 <font style="color:rgb(34, 34, 34);background-color:rgb(248, 248, 248);">rule_json</font>,<font style="color:rgb(34, 34, 34);background-color:rgb(248, 248, 248);">rule_json</font> 里再嵌套 <font style="color:rgb(34, 34, 34);background-color:rgb(248, 248, 248);">config_json</font>——一层套一层,像俄罗斯套娃,只不过每一层都是屎。
有没有人向上问一句:发票是不是一个独立的领域实体?优惠券核销是不是一条独立的业务事实?返佣规则是不是一套独立的配置模型?
没有人问。因为建一张新表要跟 DBA 对接、要走 DDL 审批、要改十几个 DAO,而往 <font style="color:rgb(34, 34, 34);background-color:rgb(248, 248, 248);">ext_info</font> 里塞一个字段只需要改一行代码。懒是第一生产力,JSON 是懒的官方赞助商。
真正可怕的是这一招的"政治正确性"。当你提出"这应该拆成 <font style="color:rgb(34, 34, 34);background-color:rgb(248, 248, 248);">t_order_invoice</font> 独立建模"时,一定会有人跳出来说:"不不不,用 JSON 更灵活、更敏捷、schema-less 是现代架构趋势。"
——放屁。schema-less 不是让你放弃 schema,而是让你把 schema 放到应用层强约束地管起来。但你根本没管,你只是把数据库该做的建模工作,外包给了一个永远没人维护的 JSON 黑洞。
三年后,当你需要统计"本月开了多少张专票"时,你发现要全表扫描解析 JSON。当你需要给发票表加唯一索引时,你发现根本没有发票表。当审计要求对返佣规则做版本追溯时,你发现 JSON 里只有当前值,没有历史。
你试图迁移数据——发现线上有十几种不同版本的 JSON 结构,因为每个同事塞进去的格式都不一样,而且没人知道哪些字段还在用、哪些是历史遗留。
**<font style="color:rgb(34, 34, 34);background-color:rgb(248, 248, 248);">ext_info</font>** ****不是一个字段,是一座垃圾填埋场。你以为你在做"灵活设计",其实你在做向未来的自己拉屎。
姿势三:状态靠布尔标志——用十个 is_xxx 干状态机的活
这是最隐蔽、最致命的一种。因为它看起来完全符合"代码清晰"的直觉。
订单有个状态,怎么设计?初级程序员会加一个字段:<font style="color:rgb(34, 34, 34);background-color:rgb(248, 248, 248);">is_paid BOOLEAN</font>。
然后需求变了,要区分"是否发货"。再加一个:<font style="color:rgb(34, 34, 34);background-color:rgb(248, 248, 248);">is_shipped BOOLEAN</font>。
然后要区分"是否取消":<font style="color:rgb(34, 34, 34);background-color:rgb(248, 248, 248);">is_cancelled BOOLEAN</font>。 然后是退款:<font style="color:rgb(34, 34, 34);background-color:rgb(248, 248, 248);">is_refunded BOOLEAN</font>。 然后是审核:<font style="color:rgb(34, 34, 34);background-color:rgb(248, 248, 248);">is_reviewed BOOLEAN</font>。 然后是锁定:<font style="color:rgb(34, 34, 34);background-color:rgb(248, 248, 248);">is_locked BOOLEAN</font>。 然后是删除:<font style="color:rgb(34, 34, 34);background-color:rgb(248, 248, 248);">is_deleted BOOLEAN</font>(逻辑删除,你懂的)。 然后是异常:<font style="color:rgb(34, 34, 34);background-color:rgb(248, 248, 248);">has_exception BOOLEAN</font>。
半年后,你的订单表有 8 个 boolean 字段。你觉得每一个都清晰明了,代码里到处写:
if(order.getIsPaid()&&!order.getIsShipped()&&!order.getIsCancelled()){
// 这是"已付款未发货"状态
}
if(order.getIsPaid()&&order.getIsShipped()&&!order.getIsRefunded()){
// 这是"已发货未退款"状态
}
停一下。
8 个 boolean 有 2 的 8 次方 = 256 种组合。其中合法的业务状态只有 12 种。剩下 244 种组合,全都是非法状态——比如 <font style="color:rgb(34, 34, 34);background-color:rgb(248, 248, 248);">is_paid=true, is_cancelled=true, is_refunded=false</font> 这种四不像。
但你的代码里有任何地方约束"这 244 种组合不能出现"吗?
没有。
于是线上 bug 永不绝迹。用户发邮件骂:"为什么我的订单显示'已付款已取消已发货未退款'?" 你一查数据库——是的,这个订单四个标志位同时为真。
为什么会这样?因为你没有状态机,只有 8 个互相独立的开关。任何一段代码都可以在任何时刻把任何一个开关拨到任何位置,没有任何约束。你以为你在用布尔值"表达状态",其实你在用布尔值放弃状态。
有没有人向上问一句:订单本质上只有一个状态属性,它的取值是一组互斥的枚举;状态之间的流转是一张有向图。我们要设计的不是 8 个 boolean,是一个状态机。
没有人问。因为 <font style="color:rgb(34, 34, 34);background-color:rgb(248, 248, 248);">is_paid</font> 这种字段名叫"语义清晰",是写在面试题里的最佳实践。没人告诉你语义清晰的字段堆在一起,会变成语义爆炸。
更精彩的是当产品说:"新增一种'部分发货'状态。" 你慌了:现在要 <font style="color:rgb(34, 34, 34);background-color:rgb(248, 248, 248);">is_partially_shipped</font> 还是 <font style="color:rgb(34, 34, 34);background-color:rgb(248, 248, 248);">shipped_ratio</font>?和 <font style="color:rgb(34, 34, 34);background-color:rgb(248, 248, 248);">is_shipped</font> 什么关系?历史数据怎么回刷?代码里所有 <font style="color:rgb(34, 34, 34);background-color:rgb(248, 248, 248);">if (is_shipped)</font> 的地方都要加上"或者 is_partially_shipped"——你打开 IDE 全局搜索,1200 个结果。
你不是在加一个状态,你是在给一座 8 阶屎山再加一层。
这就是没有状态机抽象的代价。你今天省下的那 30 分钟建模时间,将来会以每月两次 P2 故障的频率还回来。
三、屎的七十二变:那些你天天在写的"设计"
上面三个姿势只是基本功。真到工位上,屎有七十二变:
屎变 #1:多张结构完全相同的表
你见过这样的数据库吗?
<font style="color:rgb(34, 34, 34);background-color:rgb(248, 248, 248);">t_order_202401</font><font style="color:rgb(34, 34, 34);background-color:rgb(248, 248, 248);">t_order_202402</font><font style="color:rgb(34, 34, 34);background-color:rgb(248, 248, 248);">t_order_202403</font>- ...
按月分表,听起来挺专业的对吧?但当你发现每一张表的字段完全一样,只是表名后缀不同,而查询时需要动态拼接表名——你就知道这是一泡分装在不同罐子里的屎。为什么不设计一张分区表?为什么不用中间件?因为"按月分表"是你在某篇博客上看到的,你觉得很酷,就照做了。
屎变 #2:魔术数字漫山遍野,枚举值散落各处
if(order.getStatus()==1){...}// OrderServiceImpl
if(status.equals("1")){...}// OrderController
WHERE status IN(1,2,3)ANDtype=5// mapper.xml
const STATUS_PAID =1;// 前端 constants.js
同一个"已支付"在代码里有四种写法,在数据库里有一份,在需求文档里还有一句"支付成功的订单"。当产品说"把'已支付'拆成'已支付-待风控'和'已支付-已放行'"时,你需要改多少地方?没人知道,因为没人敢 grep**** **<font style="color:rgb(34, 34, 34);background-color:rgb(248, 248, 248);">== 1</font>**——会出来一万个结果。
抽象的正解是什么?一个枚举类、一张字典表、一套类型安全的转换器。但这需要你把"1"当成一个概念而不是一个整数——这一步动作,大部分人懒得做。
屎变 #3:参数校验逻辑散落在 30 个地方
同一个手机号格式校验,你可以在:
<font style="color:rgb(34, 34, 34);background-color:rgb(248, 248, 248);">UserController.add()</font>里找到一份<font style="color:rgb(34, 34, 34);background-color:rgb(248, 248, 248);">UserController.update()</font>里找到一份<font style="color:rgb(34, 34, 34);background-color:rgb(248, 248, 248);">OrderController.create()</font>里找到一份<font style="color:rgb(34, 34, 34);background-color:rgb(248, 248, 248);">RegisterService.validate()</font>里找到一份- 前端的
<font style="color:rgb(34, 34, 34);background-color:rgb(248, 248, 248);">utils.js</font>里还有一份
当工信部要求手机号支持 17 位物联网卡时,你需要改多少地方?没人知道,因为没人记得全。这就是没有抽象的后果——同一个规则被复制了无数次,每一次复制都是在制造未来的技术债。
四、AI Coding 时代:屎山制造进入工业 4.0
好了,前面说的都是"人手造屎"的时代。现在,咱们进入了 AI Coding 时代。
情况变好了吗?
变得更糟了。
GitClear 的研究数据显示,AI 生成代码的重复率是人工代码的 8 倍,技术债增加 32.45 issues/KLOC。Sonar 的报告更触目惊心:AI 生成的代码中,90% 存在代码异味。
这不是 AI 的错。AI 只是一个放大器。
你给它一个"在订单表加个发票信息"的 prompt,它很贴心地给你生成 <font style="color:rgb(34, 34, 34);background-color:rgb(248, 248, 248);">ALTER TABLE t_order ADD COLUMN invoice_info JSON</font>。你很满意,点下 Accept。
你又给它一个"再加个订单是否需要人工审核的标志"的 prompt,它又很贴心地给你 <font style="color:rgb(34, 34, 34);background-color:rgb(248, 248, 248);">ADD COLUMN need_manual_review BOOLEAN</font>。你又 Accept。
你连脑子都没过过——因为你自己就没有抽象意识,你根本不知道发票应该独立建模,状态应该抽成状态机。AI 忠实地执行了你的低水平指令,帮你把屎的生产效率提升了 125%。
你从一个人造屎,变成了一个人指挥 AI 造屎。生产效率飞跃,屎的质量没变,只是产量翻倍了。
这还不是最可怕的。最可怕的是 Vibe Coding——这个概念由 OpenAI 联合创始人 Andrej Karpathy 在 2025 年提出,核心理念是"完全跟着感觉走,拥抱指数增长,忘掉代码本身的存在"。
翻译成人话就是:不知道怎么写的代码,就让 AI 帮你写。看不懂也没关系,能跑就行。
GitClear 的研究显示,在 AI 编码助手普及后,提交历史中的重构活动在减少。微软的研究则指出,AI 驱动的信心往往以牺牲批判性思维为代价——开发者对 AI 生成代码的盲目信任,正在侵蚀他们原本就脆弱的抽象能力。
这是一个完美的恶性循环:
- 你没有抽象思维,不知道什么是好的设计
- 你用 AI 帮你生成代码,AI 也抽象不出好的设计(因为它只会从训练数据中找最相似的模式拼凑)
- AI 生成的屎比你手写的屎更隐蔽——它看起来工整、有注释、甚至还有单元测试
- 你欣然接受,觉得自己生产力爆棚
- 屎山以 8 倍的速度 增长
- 当你终于意识到问题时,屎山已经高到你不敢重构——因为 AI 生成的代码你根本没仔细看过,你不知道动哪里会塌方
AI 没有帮你解决问题,AI 只是帮你更快地到达问题。
ThoughtWorks 的技术雷达已经将"自满于 AI 生成的代码"列为暂缓采用的技术实践。而那些真正有抽象能力的工程师,正在用 AI 辅助重构,让 AI 帮他们把屎山改造成可维护的系统——前提是,他们自己知道"好"长什么样。
而对于没有抽象思维的你,AI 就是一台屎山 3D 打印机。以前你一天造一坨屎,现在你一天能打印十坨。
五、向上抽象,就是问一句"这他妈到底是啥?"
所谓向上抽象,就是逼着自己从 Ctrl+V 的手指运动中停下来,问几个该死的问题:
| 沉迷吃屎的日常 | 向上抽象的提问 |
|---|---|
| 产品原型有这个字段,加! | 这个字段是什么实体?和现有实体是什么关系? |
| 塞进 ext_info JSON 里就行了! | 这是一条业务事实,还是一个独立实体?它需不需要被查询、被索引、被审计? |
| 再加一个 is_xxx 标志位! | 这是一个独立属性,还是状态机的一个节点?整体状态空间有多少种合法组合? |
| 按月建表,简单! | 分区和分表的区别是什么?我真的需要分表吗? |
代码里到处 <font style="color:rgb(34, 34, 34);background-color:rgb(248, 248, 248);">status == 1</font>! |
"1"代表什么概念?这个概念的完整取值集合是什么? |
| AI 帮我写好了,Accept! | 这段代码在整体架构中的位置是什么?它和已有代码是否重复? |
问完这几个问题,你可能会发现——你准备造的屎,其实根本就不用造。
有一次,团队要做一个"优惠券发放"功能。产品经理画了满屏的原型:新人券、满减券、折扣券、兑换券、限时券、分享券……
后端老李熟练地打开 Navicat,准备建六张表。
我问了一句:"这六种券的本质是什么?"
"优惠券啊。"
"那它们的核心字段是不是都一样?名称、面值、使用门槛、有效期、适用商品范围。不同的只是类型和某些特定的规则。"
"所以?"
"所以我们建一张 <font style="color:rgb(34, 34, 34);background-color:rgb(248, 248, 248);">t_coupon</font> 表,用一个 <font style="color:rgb(34, 34, 34);background-color:rgb(248, 248, 248);">type</font> 字段区分类型,特定规则用策略模式处理发放/核销逻辑,类型本身是受控枚举,不是字符串。"
老李愣了愣,默默关掉了新建表的窗口。
后来这个系统支持了 20 多种券类型,核心表只有 3 张。
原来这些屎,根本不用分开拉。
六、结语:AI 时代,抽象能力是最后的护城河
我写这篇文章,不是为了教你设计模式——那是另一本书的事。我只想留下几个问题,供你在下一次想按 Ctrl+V 的时候思考:
- 这段代码和已有的某段代码,相似度超过 80% 吗? 如果是,你应该抽象,而不是复制。
- 这个字段和其他几个字段,本质上是同一类东西吗? 如果是,它们应该被建模成关联实体,而不是在一张表里无限追加,也不是塞进一个 JSON 黑洞。
- AI 生成的这段代码,你真的理解它在整体设计中的位置吗? 如果不理解,你就不是在编程,你是在给屎山添砖加瓦。
在 AI 能把任何 prompt 变成代码的今天,写出能跑的代码已经是最不值钱的能力。AI 写得比你快、比你多、比你规范。但它无法替你做一件事——判断什么是一个好的设计。
因为"好"不是一个能从训练数据中统计出来的概率,它是一种需要抽象思维才能把握的判断。
而没有抽象思维的人,在 AI 时代会变成什么?
会变成屎山车间的车间主任——管理着一群不知疲倦的 AI 机器人,24 小时不间断地生产形状各异的屎,产量惊人,品控为零。
所以,在你下一次打开 Cursor 之前,在你下一次按 Tab 补全之前,在你下一次说"能跑就行"之前——
抬头看一眼:你是在造系统,还是在吃屎。
开嘴之前多想半秒,这半秒就是你跟那群 24 小时不停嘴的同行之间,唯一的区别。
而这半秒钟,正在成为 AI 时代程序员最后的护城河。
附录:如果你觉得这篇文章是屎
是的,这篇文章是 AI 辅助写的。
我知道你在想什么。你可能从第一段就开始警惕了——"嗯,这种排比句、这种金句密度、这种情绪浓度……AI 味儿。" 你可能已经在心里给它贴好了标签:逻辑混乱、以偏概全、满嘴喷粪。
很好。请你继续这么想。因为你正在用一种非常纯粹的方式,亲身验证本文唯一的论点。
请跟上我的逻辑:
你读完这篇文章,做的第一件事不是逐句核对每一个论据的严密性,不是去翻 GitClear 的原始报告,不是去查 <font style="color:rgb(34, 34, 34);background-color:rgb(248, 248, 248);">ext_info</font> 反模式是否真的导致了你项目里那次 P0。
你做的第一件事是——向上抽象。你把两万字压缩成三个字:"这是屎"。你甚至没意识到,你刚刚完成的,是本文通篇苦口婆心在教你做的那件事:从混乱的细节里提炼本质。
区别只在于:你在批判一篇文章的时候,本能地会向上抽象;你在写代码的时候,本能地不会。
你读文章时会问"作者的核心论点是什么",写代码时却不问"这个字段的核心实体是什么"。 你读文章时会质疑"这段论据和结论的关系",写代码时却不质疑"这个 boolean 和上一个 boolean 的关系"。 你读文章时能一眼看穿"这是 AI 拼凑的",打开 IDE 却看不穿"这是 AI 拼凑的屎山"。
为什么?
因为骂一篇文章不用负责,维护一座屎山要你加班。你的大脑只在对你无利害的场合启用抽象能力,在对你有利害的场合——比如你需要交付、需要写周报、需要下班——它自动熄火。你不是没有抽象能力,你是把抽象能力精准地调度到了最没用的地方。
现在让我把退路一条一条堵上:
- 你说这篇文章是屎? → 你已经启动了抽象思维 → 但你只在批判别人时启动 → 你写的代码依然是屎。
- 你说这篇文章是金句之作? → 你认同观点 → 但你明天照样
<font style="color:rgb(34, 34, 34);background-color:rgb(248, 248, 248);">ext_info</font>塞一切 → 你写的代码依然是屎。 - 你说这篇文章一般般? → 你连抽象都懒得做 → 你写的代码 100% 是屎。
- 你说"这是 AI 写的,不算数"? → 你把对象从论点偷换成了作者 → 你用这种偷换逻辑工作了多少年 → 你写的代码依然是屎。
- 你说"我跟这文章里写的不一样"? → 请打开你的订单表看一眼 → 数一数
<font style="color:rgb(34, 34, 34);background-color:rgb(248, 248, 248);">ext_info</font>多少字段<font style="color:rgb(34, 34, 34);background-color:rgb(248, 248, 248);">is_xxx</font>多少标志位 → 谢谢配合。
无论你怎么选,结论只有一个。
这不是诡辩。这是你自己的行为在不同维度上的投影。你可以骂我逻辑强奸——但逻辑从来强奸不了人,是你自己的代码先把自己钉在了屎山上,我只是指了指钉子。
至于这篇文章是不是 AI 写的——无所谓。
如果你是因为"AI 写的"所以觉得是屎,那你反对的是作者身份,不是论点本身,你就是本文骂的那种"放弃抽象、放弃批判性阅读"的人。你恰好证明了:当一个人把"信息来源"当成"信息价值"的全部判断标准时,他已经失去了向上抽象的能力。
如果你是因为"内容不对"所以觉得是屎,那请具体指出哪一个论点错了——不是"感觉"错了,是哪一条结论在你真实的工程实践里不成立。如果你说得出来,这篇文章就该被改;如果你说不出来,那你刚才的"屎"就是一种情绪,而情绪无法反驳论证。
你当然可以关掉这篇文章,骂一句"狗屁不通",然后继续你的日常。AI 能帮你把下一段文字写得更流畅,也能帮你把下一坨屎写得更整齐。它唯一帮不了你的是——
在你按下 Tab 补全之前,替你问一句"这他妈到底是啥?"
那一句,只能你自己问。问出来,你就是系统设计者;问不出来——
打开你的 IDE 看一眼。
那坨东西,是你写的,还是 AI 替你拉的?
区别重要吗?
不重要。因为反正都是你的名字挂在 Git blame 上。
所以,现在,认真回答最后一个问题:
你写的下一行代码,是屎,还是系统?
别回答我。
你答不答都已经被这篇文章判过刑了——因为我不回答问题,我本身就是一个答案。

浙公网安备 33010602011771号