标签 软件工程 下的文章

【规律之手】资深码农都懂?软件工程中的13条“潜规则”定律

本文永久链接 – https://tonybai.com/2025/04/26/13-laws-of-software-engineering

大家好,我是Tony Bai。

做软件开发时间越长,越觉得背后似乎有只“无形的手”在影响着项目进度、团队协作、系统架构甚至技术决策。有些现象反复出现,从早期的一头雾水,到后来的似曾相识,再到最后的会心一笑(或许是苦笑),让人不得不感慨其中蕴含的某些“规律”。

最近看到国外一位开发者ANTON ZAIDES总结了软件工程领域的13条“定律”。它们中有些广为人知,有些则相对小众,但都非常实用。它们虽然不像物理定律那样严格精确,但确实精准地捕捉到了我们日常工作中经常遇到的挑战和现象,堪称是工程师和管理者都应该了解的宝贵“经验法则”或“心智模型”。

今天,就让我们一起来了解和学习一下这13条定律,看看它们是如何在我们身边运作的。

注:下面文中各条定律的配图也借自ANTON ZAIDES的原文章。

1. 帕金森定律 (Parkinson’s law)

定律:工作会不断扩展,填满所有可用的时间 (Work expands to fill the available time.) (任务总能拖到最后期限前完成?)

这是最著名的定律之一。简单说,如果你给一个任务设定了1周的期限,它很可能就会花掉1周;如果设定了2周,它就可能花掉2周。这常常被用来解释为什么设定“伪造”的(有时甚至不合理的)截止日期似乎能提高效率——它迫使人们在有限的时间内集中精力。但这一定律也容易被滥用,导致不切实际的期望和压力。

合理设定Deadlines是必要的,但要警惕其副作用,并结合对工作量的实际评估。它提醒我们时间管理的重要性,以及在没有明确时间约束时,任务可能无限膨胀的风险。

2. 霍夫施塔特定律 (Hofstadter’s law)

定律:事情总是比你预期的要花费更长的时间,即使你已经考虑了霍夫施塔特定律。 (It always takes longer than you expect, even when you take into account Hofstadter’s Law.) (估时永远不准?)

这是对软件项目估时困难最精准的自嘲。几乎所有的软件项目都会延期,即使你已经预留了缓冲时间。这一定律完美地平衡了帕金森定律:如果你因为帕金森定律而设置过短的Deadline,结果很可能是团队burnout或者项目持续延期。

软件工时评估极其困难,充满了不确定性。简单的缓冲时间往往不够。有效的项目管理需要在时间、资源和可协商的范围 (negotiable scope) 之间找到平衡,并依赖持续的沟通和实践经验。

3. 布鲁克斯定律 (Brooks’ law)

定律:向一个以延期的软件项目中增加人力,将使其更加延期。(Adding manpower to a late software project makes it later.) (人月神话?)

这就是著名的“9个孕妇不能在1个月内生出一个婴儿”的道理。当项目延期,高层管理者常常会说:“这个项目很紧急,你可以从其他团队调配任何你需要的人!” 但项目经理的内心可能是:“请别再打扰我们,让我们专心工作就好”。

增加新人手需要时间成本:新人需要学习项目背景、熟悉代码库、建立沟通渠道。这些都会消耗现有团队成员的时间和精力,增加沟通开销,短期内甚至可能降低整体生产力。

在项目后期,尤其是面临延期时,要极其谨慎地考虑增加人手。更好的策略可能是缩减范围、优化流程或给予现有团队更多不受干扰的时间。

4. 康威定律 (Conway’s law)

**定律:组织输出的设计是这些组织的沟通结构的副本。(Organizations produce designs which are copies of the communication structures of these organizations.) (你的架构是不是反映了你的团队结构?)

简而言之,你的系统架构往往是你团队组织结构的镜像。如果你的公司有独立的“前端团队”和“后端团队”,他们之间的沟通壁垒和协作模式,会直接反映在前后端接口的设计、数据格式的匹配度以及可能出现的额外“胶水代码”上。

这一定律提醒我们组织结构对技术决策的深远影响。反过来,我们也可以利用 逆康威定律 (Inverse Conway Maneuver):为了达成期望的系统架构,主动调整团队的组织结构和沟通方式。例如,想要微服务化?那就组建更小、更自治、拥有端到端职责的团队。

5. 坎宁安定律 (Cunningham’s law)

定律:在互联网上获得正确答案的最佳方式不是提问,而是发布一个错误的答案。 (The best way to get the right answer on the internet is not to ask a question; it’s to post the wrong answer.) (想得到反馈?先大胆“错”一个?)

这条定律巧妙地利用了人性——人们往往更乐于纠正错误,而不是回答问题。

在工作中遇到阻碍时,可以巧妙运用这一定律。例如,与其提交一个请求单等待DevOps团队处理,不如自己尝试写一个(哪怕不完美的)解决方案,提交一个Pull Request。即使写得不对,通常也能更快地获得相关人员的注意和具体的修改建议,同时也促进了知识的传递和流程的改进。主动迈出第一步,哪怕是“错误”的一步,也比原地等待更有效。

6. 斯特金定律 (Sturgeon’s law)

定律:任何事物(特别是人类创造出来的)90% 都是垃圾。 (Ninety percent of everything is crap.) (你做的功能多少是真正有价值的?)

这条定律是对现实的残酷揭示,有点像加强版的“二八定律”。无论是代码、想法、功能特性,大部分都可能是平庸甚至无用的。你发布的大部分功能可能对用户价值寥寥,只有那一小部分核心功能支撑着你的产品。

这要求我们具备批判性思维,勇于质疑。作为开发者,不能仅仅被动接受产品经理给出的需求列表,而要思考功能的真正价值,避免将精力浪费在那“90%的垃圾”上。这也解释了为什么“10倍工程师”并非指写10倍代码的人,而是能创造10倍价值的人——他们更懂得识别和聚焦于那重要的10%。

7. 扎文斯基定律 (Zawinski’s law)

定律:每一个程序都试图扩展直到它能阅读邮件为止。那些不能如此扩展的程序会被可以如此扩展的程序替代掉。 (Every program attempts to expand until it can read mail. Those programs which cannot so expand are replaced by ones that can.) (警惕功能蔓延!)

这条定律形象地描述了“功能蔓延”(feature creep) 的现象。程序(或产品)总有一种内在的趋势去添加越来越多的功能,最终变得臃肿不堪。尤其在AI时代,给任何应用加上一个聊天机器人似乎都轻而易举。

我们要警惕无休止的功能添加!保持产品的核心价值和简洁性至关重要。过多的功能不仅会增加复杂度和维护成本,还可能让用户(尤其是新用户)感到困惑,找不到真正需要的功能。需要有意识地做减法,抵制“什么都想要”的诱惑。

8. 海勒姆定律 (Hyrum’s law / The Law of Implicit Interfaces)

定律:当你有足够多的API用户时,你在合同(文档)中承诺什么都无关紧要:你系统中所有可观察的行为都会被某些人所依赖。 (With a sufficient number of users of an API, it does not matter what you promise in the contract: all observable behaviors of your system will be depended on by somebody.) (接口行为不能轻易改动!)

这条定律对API设计和维护者至关重要,它揭示了接口(API)维护的残酷现实。即使某个行为没有写在你的官方文档里,只要它是可观察到的(比如某个特定的错误返回格式、某个未公开的内部端点、某个副作用),一旦有足够多的用户,就一定会有人依赖上这个行为。

因此,API的设计和变更需要极其谨慎。任何微小的改动,即使是修复Bug或改变未承诺的行为,都可能破坏依赖者的系统。这也解释了为什么移除那些依据斯特金定律属于“垃圾”的特性如此困难——总有用户在依赖它们。进行接口设计时,要尽可能减少可观察的副作用,明确接口契约,并为变更做好版本管理和兼容性策略。

9. 普莱斯定律 (Price’s law / Price’s Square Root Law)

定律:在一个组织中,一半的工作是由占总人数平方根的人完成的。 (50% of the work is done by the square root of the total number of people.) (团队里的核心贡献者?)

这一定律量化了贡献度的不平均分布。例如,在一个10人的团队里,大约3个人 (√10 ≈ 3.16) 完成了50%的工作;在一个 100 人的公司里,大约 10个人 (√100 = 10) 的产出相当于剩下90人的总和。这也可以在一定程度上解释为什么Twitter在大规模裁员后没有立即崩溃。

团队规模的扩大并不会带来线性的产出增长。如果你想让产出翻倍,可能需要4倍的人员规模。这警示管理者在扩张团队时要关注人效和组织结构,识别并赋能那些核心贡献者。

10. 瑞格曼效应 (The Ringelmann effect)

定律:当一个团体的规模增加时,个体成员的生产力趋于下降。 (The tendency for individual members of a group to become increasingly less productive as the size of their group increases.) (人多不一定力量大?)

这个效应早在1913年就被发现(通过拔河实验)。团队越大,个体平均贡献的力量越小。原因主要有两个:一是动机丧失(即“社会惰化”,觉得自己的贡献不重要或难以衡量);二是协调成本增加(沟通、同步、冲突解决等开销变大)。

这也是对布鲁克斯定律和普莱斯定律的有力补充。保持小而精干的团队往往效率更高,尤其是在需要高度协作和创新的领域。明确的职责划分、有效的沟通机制和对个体贡献的认可,有助于缓解瑞格曼效应。

11. 古德哈特定律 (Goodhart’s law)

定律:当一个度量本身成为目标时,它就不再是一个好的度量。 (When a measure becomes a target, it ceases to be a good measure.) (警惕 KPI 陷阱!)

这是关于KPI和度量最著名的警告。一旦某个指标(如代码行数、PR 数量、Bug 修复数、用户增长数、客户满意度)被设定为考核目标,人们就会想方设法“优化”这个指标本身,而不是优化它所代表的真实价值,最终导致该指标失去意义。例如,为了提高代码行数而写冗余代码,为了快速关闭工单而不是定位根因并从根本上解决问题。

对任何单一的量化指标都要保持警惕。度量是必要的,但不能迷信指标。需要结合多个指标、定性分析以及对最终业务价值的判断,来全面评估绩效和进展。

12. 吉尔布定律 (Gilb’s law)

定律:任何你需要量化的东西,都可以用某种方式来衡量,这种衡量方式优于完全不衡量。 (Anything you need to quantify can be measured in some way that is superior to not measuring it at all.) (与上一条辩证看,还是要量化!)

这一定律是古德哈特定律的必要平衡。它告诉我们,尽管度量可能不完美、可能被“攻击”,但完全放弃量化是不可取的。“没有度量,就没有改进”。找到一个(哪怕是粗糙的)量化方法,总比凭感觉行事要好。

因此,不要因为害怕古德哈特定律而彻底放弃量化。关键在于选择合适的度量维度(比如 DORA 指标、开发者体验 DevEx 等),持续迭代和优化度量方法,并结合业务背景进行解读。

13. 墨菲定律 (Murphy’s law)

定律:任何可能出错的事情,最终都会出错。 (Anything that can go wrong will go wrong.) (那个被你忽略的边缘 Case…?)

这条定律大家再熟悉不过了。它提醒我们,那些看起来概率极小、懒得处理的边缘情况、那个被你忽略的潜在Bug、那一次“应该没问题”的侥幸操作,往往会在最关键的时候给你带来麻烦。

在软件工程中,要有敬畏之心。进行充分的测试(尤其是边缘情况测试)、建立健壮的错误处理和容错机制、实施灰度发布和监控告警,都是应对墨菲定律的必要手段。不要低估任何可能出错的环节。

小结:定律是启发,而非束缚

这13条定律,更像是前辈们用经验和教训为我们绘制的“认知地图”。它们并非严格的科学定理,但在理解软件开发这个复杂系统时,能为我们提供宝贵的视角和警示。

将这些定律记在心中,不是为了给自己设限或者找借口,而是为了让我们在日常的编码、设计、沟通和决策中,多一份清醒,多一份审慎,少踩一些坑,从而更从容地驾驭软件工程这门充满挑战与乐趣的艺术。

你对这些定律有哪些特别的感触?或者在你多年的开发生涯中,还总结出了哪些有趣的“私房定律”?

欢迎在评论区留下你的思考和故事!


商务合作方式:撰稿、出书、培训、在线课程、合伙创业、咨询、广告合作。如有需求,请扫描下方公众号二维码,与我私信联系。

拯救你的Commit Log:Conventional Commits实践指南

本文永久链接 – https://tonybai.com/2025/04/24/conventional-commits-guide

告别混乱Commit Log!用规范指引你写出有意义的提交!

大家好,我是Tony Bai。

Git的Commit Log (提交日志) 是项目演进的脉络,也是开发者之间沟通变更、追溯历史、理解代码演变的关键载体。然而,在实际开发中,我们常常面对杂乱无章、意义不明的提交信息——”fix bug”、”update code”、”wip” 等屡见不鲜。这些模糊的记录不仅让代码审查、问题排查和版本追溯变得异常困难,也阻碍了自动化流程的实施。Conventional Commits (约定式提交) 规范提供了一套清晰、简洁的指引,旨在将每一次提交都转化为有意义、结构化的信息单元,从而显著提升 Commit Log 的价值和可利用性。

在这篇文章中,我们将探讨Conventional Commits如何作为一项关键指引,帮助开发者和团队构建更清晰、更一致、更具信息量的提交历史。

1. Commit Log的困境:为何需要指引?

缺乏明确指引的Commit Log往往会陷入以下困境:

  • 信息熵高,有效信息少: 大量模糊、随意的提交信息混杂在一起,难以快速定位关键变更或理解特定提交的目的。
  • 沟通效率低下: 团队成员需要花费额外时间去解读他人的提交意图,代码审查效率降低。
  • 历史追溯困难: 当需要回溯某个功能或 Bug 的引入/修复历史时,无结构的日志如同大海捞针。
  • 自动化阻碍: 不一致、不可预测的提交信息使得自动化生成 Changelog、语义化版本控制(SemVer)等流程难以实现。

面对这些普遍存在的困境,业界亟需一套行之有效的规范来引导开发者记录更有价值的提交信息。这正是 Conventional Commits 规范所要解决的核心问题,它通过引入一套简洁而强大的结构化指引来实现这一目标。Conventional Commits并非强制性的铁律,而是一套强大的指引 (Guidance),它通过引入轻量级的结构化约定,引导开发者在提交时思考并明确表达变更的性质、范围和影响

2. Conventional Commits 核心指引:结构化的力量

该规范的核心指引体现在其简洁的提交信息结构上(如下所示):

<type>[optional scope]: <description>

[optional body]

[optional footer(s)]

遵循这项指引,每次提交都应包含以下关键要素:

  • Type (类型): [必须遵循的指引] 表明提交的性质。规范定义了基础类型:

    • fix::修复 Bug (对应 SemVer PATCH)。
    • feat::引入新功能 (对应 SemVer MINOR)。
    • 鼓励扩展: 团队可以根据需要定义其他类型,如 build, chore(用于标记那些不涉及新特性或修复的常规维护工作,比如更新依赖项等), ci, docs, style, refactor, perf, test等,以适应具体工作流。这些扩展类型本身通常不直接影响版本号(除非包含破坏性变更)。
  • Scope (范围): [可选但推荐的指引] 明确提交影响的代码库区域或模块,用括号包裹,如 feat(api): 或 fix(parser):。这极大地增强了信息的可定位性。

  • Description (描述): [必须遵循的指引] 紧跟冒号和空格,用简洁的语言(推荐使用祈使句现在时)概括本次提交的核心变更内容。这是提交信息的“标题”。

  • Body (正文): [可选指引] 当简短描述不足以说明时,提供更详细的上下文、动机和实现细节。与 Description 之间需空一行。

  • Footer(s) (脚注): [可选指引] 提供元数据,如关联 Issue (Refs: #123)。特别重要的两个脚注指引:

    • BREAKING CHANGE: :明确标示不兼容的 API 变更 (对应 SemVer MAJOR)。
    • INITIAL STABLE RELEASE: :标记项目从 0.y.z 进入 1.0.0。

强调重要变更的简化指引: 规范还提供了 ! (紧跟 type 或 scope 之后) 和 !! 作为标记 BREAKING CHANGE 和 INITIAL STABLE RELEASE 的快捷方式,进一步简化遵循指引的实践。

为了更直观地理解这个结构,以下是一些典型的Conventional Commits示例:

  • 简单的 Bug 修复:
fix: correct minor typos in documentation
  • 带范围的新功能:
feat(lang): add Polish language support
  • 使用 ! 标记破坏性变更:
refactor!(auth): remove deprecated JWT authentication method

注意:这里的 ! 表明这是一个破坏性变更,即使type是refactor。

  • 包含详细正文和脚注的提交:
perf(api): improve user query performance significantly

Implemented a new indexing strategy for the users table and optimized
the SQL query execution plan. Initial tests show a 50% reduction
in average query latency under heavy load.

Reviewed-by: Alice <alice@example.com>
Refs: #456, #478
  • 使用 !! 标记首次稳定版发布:
chore(release)!!: prepare for 1.0.0 stable release

Finalized documentation, updated dependencies, and ran comprehensive
end-to-end tests to ensure stability for the first major release.

INITIAL STABLE RELEASE: The project is now considered stable for production use.

通过遵循这些简单的指引,原本混乱的Commit Log就被转化为结构清晰、信息丰富的记录。

理解了 Conventional Commits 的核心结构和要素后,我们自然会问:遵循这项指引究竟能为开发者和团队带来哪些实实在在的好处?答案是多方面的,它能让原本静态、难以利用的 Commit Log “活”起来,释放出巨大的潜在价值。

首先,结构化的 type 和 scope 提升了可读性与可理解性,使团队能够快速筛选和定位信息,清晰的 description 和 body 阐述了变更的“什么”和“为什么”。

其次,一致的格式增强了团队沟通与协作,减少了误解,提高了代码审查和协作效率,使每一次提交都成为清晰的沟通。

此外,结构化的日志简化了历史追溯与问题排查,便于查找特定功能引入、Bug 修复或破坏性变更的源头。

最后,一个充满有意义提交的日志自然而然地成为自动化工具的理想输入,能够驱动自动化生成 CHANGELOG、自动化 SemVer 版本判断,以及基于提交类型触发不同的 CI/CD 流程。

认识到 Conventional Commits 带来的显著价值后,如何在日常开发中有效地遵循并最大化其效益,就成了一个关键问题。仅仅了解规范的语法是不够的,掌握一些最佳实践和深入的洞察,能帮助我们更好地将这项指引融入工作流。

3. 遵循指引的最佳实践与洞察

为了更好地应用Conventional Commits指引,以下几点值得关注:

  • 原子化提交: 我们鼓励将复杂的变更分解为多个逻辑上独立的、遵循单一type的提交。这本身就是一种良好的 Git 实践,很多大厂的git commit规范以及代码review规范也是这么要求的。Conventional Commits 进一步强化了这一点。

  • 选择最合适的Type: 当一次提交包含多种类型的变更时(虽然应尽量避免),选择最能代表其核心意图的 type,并在 Body 中详述其他变更。

  • 祈使句现在时: 推荐使用如 “Add feature”、”Fix bug” 的风格撰写 Description,简洁、直接,如同给代码库下达指令。

  • 利用工具辅助: 社区提供了丰富的工具(如Commitizen, commitlint等)来帮助开发者遵循规范格式,并在提交前进行校验,降低遵循指引的负担。

  • 团队共识与逐步采纳: 引入规范需要团队达成共识。可以通过分享、讨论和使用工具逐步推广。

当然,良好实践的推广离不开工具的支持。幸运的是,围绕 Conventional Commits 已经形成了一个活跃的社区和丰富的工具生态系统,它们极大地降低了开发者遵循规范的门槛,让指引更容易落地。

4. 社区生态:工具让指引落地

Conventional Commits 的流行离不开活跃的社区和丰富的工具支持,它们帮助开发者轻松地将这项指引融入日常工作流:

  • Commitizen: 交互式命令行工具,引导用户创建符合规范的提交信息。
  • Commitlint: 用于校验提交信息是否符合规范,常与 Git Hooks (如 husky) 集成。
  • IDE 插件: 主流 IDE (VS Code, JetBrains IDEs 等) 均有插件提供模板、补全和校验支持。
  • 自动化版本与 Changelog 工具:semantic-release, goreleaser/chglog等,它们消费符合规范的提交历史。

这两年基于大模型的辅助生成commit log的工具以及一些代码智能体应用(如Cursor等)也在规范git commit log方面起到了非常积极的作用,对于像我这样英语非母语但又喜欢以英文log提交的选手来说,这些工具大幅降低了我在纠结如何写commit log时的心智负担,给予了我很大的帮助。

5. 小结

总而言之,Conventional Commits 远不止一套冷冰冰的格式规则,它更像是一位贴心的向导,一项旨在将每一次提交都转化为宝贵信息资产的核心指引。它赋予我们结构化的力量,能够将困扰许多团队的混乱、低效的Commit Log,转变为清晰、一致且富有洞察力的项目演进历史——这对于提升代码可维护性、团队协作效率乃至自动化流程都至关重要。

现在,就将这项指引融入你的日常开发吧! 让每一次git commit不再是随意的记录,而是对项目演进负责任的、有意义的贡献。

那么,你的团队是如何采纳和实践提交规范的?你在使用Conventional Commits或其他规范时,有什么独到的心得或踩过的“坑”吗?

非常期待在评论区看到你的分享与交流!

如果这篇文章让你觉得“提交信息确实应该更有意义”,请分享给你的同事或团队,一起提升代码库的 Commit Log 质量吧!

别忘了关注我,持续获取更多提升研发效能的实用技巧与深度解析。

6. 参考资料


img{512x368}
img{512x368}

著名云主机服务厂商DigitalOcean发布最新的主机计划,入门级Droplet配置升级为:1 core CPU、1G内存、25G高速SSD,价格6$/月。有使用DigitalOcean需求的朋友,可以打开这个链接地址:https://m.do.co/c/bff6eed92687 开启你的DO主机之路。

Gopher Daily(Gopher每日新闻) – https://gopherdaily.tonybai.com

我的联系方式:

  • 微博(暂不可用):https://weibo.com/bigwhite20xx
  • 微博2:https://weibo.com/u/6484441286
  • 博客:tonybai.com
  • github: https://github.com/bigwhite
  • Gopher Daily归档 – https://github.com/bigwhite/gopherdaily
  • Gopher Daily Feed订阅 – https://gopherdaily.tonybai.com/feed

商务合作方式:撰稿、出书、培训、在线课程、合伙创业、咨询、广告合作。

如发现本站页面被黑,比如:挂载广告、挖矿等恶意代码,请朋友们及时联系我。十分感谢! Go语言第一课 Go语言进阶课 AI原生开发工作流实战 从 0 开始构建 Agent Harness Go语言精进之路1 Go语言精进之路2 Go语言第一课 Go语言编程指南
商务合作请联系bigwhite.cn AT aliyun.com
这里是 Tony Bai的个人Blog,欢迎访问、订阅和留言! 订阅Feed请点击上面图片

如果您觉得这里的文章对您有帮助,请扫描上方二维码进行捐赠 ,加油后的Tony Bai将会为您呈现更多精彩的文章,谢谢!

如果您希望通过微信捐赠,请用微信客户端扫描下方赞赏码:

如果您希望通过比特币或以太币捐赠,可以扫描下方二维码:

比特币:

以太币:

如果您喜欢通过微信浏览本站内容,可以扫描下方二维码,订阅本站官方微信订阅号“iamtonybai”;点击二维码,可直达本人官方微博主页^_^:
本站Powered by Digital Ocean VPS。
选择Digital Ocean VPS主机,即可获得10美元现金充值,可 免费使用两个月哟! 著名主机提供商Linode 10$优惠码:linode10,在 这里注册即可免费获 得。阿里云推荐码: 1WFZ0V立享9折!


View Tony Bai's profile on LinkedIn
DigitalOcean Referral Badge

文章

评论

  • 正在加载...

分类

标签

归档



View My Stats