欢迎大家来到IT世界,在知识的湖畔探索吧!
欢迎大家来到IT世界,在知识的湖畔探索吧!
你去问任何一个资深程序员:“软件开发里有哪些定律?”
他们不是沉默,就是苦笑,或者开始讲一段凌晨三点修系统的血泪史。
这些“定律”不是写在教科书里的高深概念,而是开发路上一巴掌接一巴掌的现实。
比如你说“这个功能最多俩小时”,三天后还没完工。是不是很熟悉?
为什么我们总重复犯错?因为软件开发不仅是写代码,还是和复杂性、截止时间、人的情绪,以及那些标着“低优先级”却能炸生产环境的 bug 作战。
这些定律之所以存在,是因为我们不是给机器写代码,而是和一群人协作,为人类服务,同时还要抗衡混乱与熵。
这篇文章里,我们聊聊 15 条“痛并成长”的软件工程定律。放心,不讲道理,只说人话。
第 1 条:摩尔定律的副产品——期望指数增长定律
技术越快,用户越烦
你还记得当年网页加载 10 秒我们还会惊叹“互联网真神奇”?那样的时代已经一去不复返了。
摩尔定律说计算能力每两年翻一番,但没人提醒用户他们的耐心不会同步增长。
现在只要你的应用加载超过 1.5 秒,用户已经开始关标签、写推文:“这什么破站点。”
现实开发场景:
- 花了 6 个月优化后端处理流程,用户只说:“还是慢。”
- 给加载页加了个可爱的动画,用户说:“为什么还要加载?”
- 上线了一个超强的机器学习模型,响应时间 2 秒,用户吐槽:“这不是实时的吗?”
冷知识:
Google 的研究发现,53% 的移动用户会在页面加载超过 3 秒时直接退出。
开发者生存指南:
- 快速加载只是基本盘,为“急躁”而设计才是王道。
- 骨架屏(Skeleton Screen)胜过转圈圈(Spinner)。
- 预加载,预判,别让用户等。
- 用老旧手机和酒店 Wi-Fi 测试一下,别只盯着你的 MacBook Pro。
因为再快的后端,也挡不住有人用 Safari 连着 2G 信号。
第 2 条:Zawinski 定律:一切程序,最终都在发邮件
“Every program attempts to expand until it can read mail.”
——Jamie Zawinski
这本来是句玩笑,现在成了预言。
你最初的愿景是:我要做一个极简、专注的应用。
结果两次迭代之后:
“我们要加通知系统、评论功能、私信系统……”
最终你做了一个待办事项应用,变成了 Slack+Gmail 的混合体,邮箱一塌糊涂,没人用还总出 bug。
真实案例:
- 开发者 A:“我们做个 to-do 应用。”
- B:“可以分配任务吗?”
- C:“加个 @提及 和私信吧。”
结果你写着正则去解析表情符,恭喜,你已经造出了 Google Wave。
真相:
Zawinski 定律不是说大家热爱邮件功能,而是说“功能膨胀”是不可避免的。
每个产品经理、每个用户,甚至你自己都会不断冒出“这个也不错”的想法。
开发者建议:
- “说不”是种美德。
- 分清“灵感点子”和“关键功能”。
- 对功能膨胀保持警惕,就像对旧代码进生产一样小心。
因为一旦你的应用能发邮件,有人马上就会问:
“能不能顺便视频会议?”
第 3 条:霍夫斯塔特定律:即使你考虑了它,它还是会拖延
“It always takes longer than you expect, even when you take into account Hofstadter’s Law.”
这是软件开发的宇宙真理:永远完不成预估时间内的开发。
不是你不努力,也不是工具坏了(当然也有可能是),而是构建软件就像:在高速公路上修车,车还在跑,客户在车上,还要求你加个蓝牙。
痛点实例:
- 你预估一个功能 3 天完成。
- 实际花了 8 天,还算顺利。
- “就做个小重构” → 两周后还在处理循环依赖,顺便怀疑人生。
为何总是翻车?
- 软件开发不是线性的,一点小问题就能让整个时间线崩掉。
- 所谓“不可预见的问题”其实就是常态。
“我们忘了鉴权。”
“那个 API 已经废弃了!”
数据支持:
根据 Standish Group 的 CHAOS 报告:只有 29% 的项目按时按预算交付。剩下的?只能靠祈祷。
生存指南:
- 预留缓冲时间,然后再多留一点。
- 拆解功能点,逐步交付。
- 遵循神圣法则:估时 ×2,再×2,尤其是在老板盯着你的时候。
即使你知道项目会延误,它还是能用全新的方式让你崩溃。
第 4 条:Gall 定律:复杂系统不是设计出来的,是演化出来的
“一个运作良好的复杂系统,一定是从一个运作良好的简单系统演化而来。”
——John Gall
Gall 的定律不仅针对系统,也针对那些想搞事情的 ego。
你肯定见过:新手为了表现、架构师想留名,于是你原本的周末小项目突然出现了:
- CQRS
- GraphQL 联邦网关
- 事件驱动微服务
- 自定义日志框架
而真正使用的用户:3 个。
定律核心:
别一上来就造飞船。
先搞个滑板,再升级到自行车,最后才能考虑悬浮。
如果你的 MVP 上线前已经有服务注册中心、gRPC、k8s 编排……你不是在写软件,你是在制造痛苦。
真实例子:
- 原系统:单体 + REST API,稳定上线。
- “重构版本”:18 个微服务,CI/CD 每天挂一次,Kubernetes 配置只有一个人懂。
建议:
- 只做能运行的最简单版本。
- 加复杂性容易,去除它却像拆炸弹。
- 别为“未来的规模”设计一个今天用不上的系统。
如果你打算在 v1.0 发布之前,就实现 v5.0 的架构,你不是在遵守 Gall 定律,而是在挑战物理法则。
第 5 条:Conway 康威定律:你的组织结构就是你的系统架构
“一个组织设计的系统,其结构无可避免地会复制这个组织的通信结构。”
——Melvin Conway
Conway 康威定律,是你为什么会有四个后端服务和前端互相吵架的根本原因。系统之所以乱,不是因为技术选型问题,而是团队沟通结构有毒。
日常惨案:
- A 组用 Java,B 组用 Go,C 组全靠 Slack 表情沟通。
- 结果系统被称为“模块化架构”,其实是“团队架构导出的血缘图谱”。
Conway 定律体现在:
- 微服务分工明确,但团队互不讲话?服务就不互通。
- 老板只相信大前后端拆分?准备迎接 API 和 UI 对不上。
- 一位老员工维护的单体应用?一切顺利,直到他辞职。
建议:
- 团队结构要围绕用户体验来设计,不只是按技术栈分组。
- 沟通也是架构的一部分。
- 墙多了,代码里的“胶带”也多了。
软件不生于真空,而是诞生于会议、Slack 和充满疑问的 Jira 工单里。
第 6 条:Brooks 定律:人越多,进度越慢
“给一个已经延迟的软件项目增加人手,只会让它更晚交付。”
——Fred Brooks
当项目进入崩溃倒计时,还有两周上线,领导的第一个反应是?
“赶紧加几个人上来支援!”
结果你不是在写代码,而是在:
- 带新人熟悉项目;
- 解答“initLegacyWorkerFlag(true) 到底干嘛”的灵魂拷问;
- 修无止境的合并冲突。
为什么反而变慢:
- 新人短期内是负生产力。
- 沟通成本增长速度 > 编码速度。
- 代码知识传递 ≠ 新人立即能产出。
灾难现场:
- 原本 2 人开发的功能,6 人接手后变成 Frankenstein。
- 每个会议都在问:“现在谁负责哪个部分?”
- Git 历史像个墓地,埋着各种未完待续的 hotfix。
数据点:
哈佛商评 2020 年对 Brooks 定律的复盘发现:快速扩张团队的项目更容易出错、延期,士气也更低。
开发者生存技巧:
- 与其加人,不如缩减需求。
- 与其提早上线,不如保住理智。
- 小团队搞定垂直功能,别整个披萨都塞给他们。
因为多几双手并不会让代码写得更快,只会让系统更容易崩。
第 7 条:避免过早优化
“过早优化是万恶之源。”
——Donald Knuth
这是程序员最容易掉进的陷阱之一。你写个函数,刚跑起来就开始纠结:
“这个 for 循环能不能再快一点?”
“要不要上缓存?”
“这个能不能并发一下?”
结果半天过去,需求还没跑通,业务逻辑还在 if-else。
典型症状:
- 对微秒级优化如临大敌
- 对整体架构问题视而不见
- 花 3 天写一个比标准库还慢的排序算法
更好的做法:
- 先把功能写对,写清楚。
- 用 Profile 工具找出真热点。
- 再考虑优化,不做“脑补型优化”。
优化的前提是你知道哪里慢,而不是你猜哪里慢。
第 8 条:YAGNI:你不会需要它
You Ain’t Gonna Need It(你不会用到它)
工程师的天性是为未来设计。于是你写了一个登录接口,顺便写了:
- 多租户支持(将来可能用)
- 第三方账号绑定(以后要接)
- 日志链路追踪(先写起来)
现实是这些代码半年没人碰,你自己都忘了写了啥。
多余的代码不是储备,而是负债。
更好的做法:
- 用户没提的功能不要写
- 产品没确认的需求不要提前开发
- 代码只为当前需求服务,不为幻想兜底
写一个好用的“现在”,比构建一个“完美的将来”更重要。
第 9 条:单一职责原则(SRP)
一个类(或模块)应该只有一个引起它变化的原因。
说人话就是:一个东西只干一件事。
你写个函数,开始是计算订单金额的,结果后来它还:
- 打了个日志
- 发了个短信
- 更新了库存
- 写了个操作记录
现在你一改库存逻辑,整个函数都要重写。
为什么单一职责重要?
- 逻辑清晰
- 易于维护
- 可单独测试
- 代码复用性强
小技巧:命名法则:看函数/类名能不能用一句话准确描述。
- ✅calculate_total_price
- ❌handle_order_and_notify_and_log_and_update_db
一个函数像一只瑞士军刀,就很难优雅地进化。
第 10 条:DRY 原则:不要重复自己
Don’t Repeat Yourself.
当你复制粘贴的时候,可能在制造未来的维护地狱。
重复的逻辑 = 重复的修改点 = 更高的出错概率
举个例子:你在 3 个地方都手动计算了税费。需求一变,你得记得改 3 处。漏掉一处,Bug 就来了。
更好的做法:
- 提炼函数
- 统一逻辑
- 设计好接口
当然,也别走火入魔。
重复 1 次叫“复制”,重复 3 次才值得重构。
第 11 条:开闭原则(OCP)
对扩展开放,对修改关闭。
什么意思?简单说:
加功能可以,别动老代码。
举个例子:你有个订单系统,突然要支持拼团。理想做法是:
- 写个拼团模块
- 扩展现有逻辑
- 原有下单流程保持不动
现实中你可能会:
- 改下单接口
- 改业务逻辑
- 改数据库字段
- 改着改着原功能也崩了
开闭原则的关键是:
- 抽象接口
- 模块边界清晰
- 新功能通过“加代码”来实现,而不是“改旧代码”
老代码是地雷,新功能绕着走。
第 12 条:KISS 原则:保持简单
Keep It Simple, Stupid
如果你能用 3 行写清楚,别用 30 行绕晕自己。
程序不是用来炫技的,是给人维护的。
复杂不等于高级,冗长不等于健壮。能写简单,是本事。
写复杂的借口:
- “以后会更灵活”(但现在没人用)
- “这样可以兼容更多情况”(但目前就一种)
- “我觉得这样更优雅”(只有你觉得)
写简单的标准:
- 看得懂
- 改得动
- 出错少
代码看不懂,不是因为它深奥,而是因为它烂。
第 13 条:避免“神对象”
有些类,像黑洞一样吸一切功能于一身。
比如你有个 UserService,它开始只是处理用户注册,慢慢它开始:
- 管用户信息
- 发通知
- 调支付
- 管权限
- 操作数据库
最后这个类有上千行,谁改都害怕。
神对象的危害:
- 改一行影响全局
- 难以测试
- 无法复用
- 新人望而生畏
解法:
- 拆分为多个子模块
- 按功能聚合
- 一层一层抽象,不搞大一统
类不是越大越强,越小越清晰。
第 14 条:测试先行:TDD 思维
“没有测试的代码只是看起来能跑。”
写测试不是为了证明你没写错,而是为了未来的你能放心改。
没有测试的代码,是“上帝视角下的勇敢尝试”。
TDD(测试驱动开发)强调:
- 先写测试
- 再写代码
- 保证变更不会带来灾难
哪怕你不 TDD,至少也要写点单测,哪怕只覆盖关键路径。
测试就像安全带,可能你一整年都用不到,但出事时能救命。
第 15 条:代码是给人读的
“代码首先是写给人看的,其次才是给机器执行的。”
如果你写的代码只有你自己能看懂,那它就不是好代码。
所以要:
- 好命名
- 合理注释
- 删掉死代码
- 减少魔法操作(比如隐藏副作用)
别指望自己能记住三个月前的写法,也别让同事骂你“谁写的这鬼东西”。能读懂才是代码的第一生产力。
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://itzsg.com/127409.html