副标题 / 摘要

可变值带来性能与直觉操作,不可变值带来安全与可预测性。本文从工程角度给出取舍指南。

目标读者

  • 需要做语言/架构选型的开发者
  • 经常处理共享状态与并发的工程师
  • 想降低 bug 成本的团队负责人

背景 / 动机

“用可变还是不可变”常被当成风格问题,但本质是成本问题:
可变值降低了短期编码成本,却提高了长期维护成本;不可变值相反。

核心概念

  • 可变值:对象可被修改,引用指向同一状态
  • 不可变值:对象创建后不可变,修改通过创建新值
  • 别名问题:多个引用指向同一对象导致隐式副作用

实践指南 / 步骤

  1. 核心业务规则优先用不可变
  2. 性能敏感且局部范围内用可变
  3. 共享数据优先不可变
  4. 用类型或约定明确边界
  5. 在接口处转换:可变在边界层,不可变在核心层

可运行示例

下面展示共享可变带来的副作用:

nums = [1, 2, 3]
ref = nums
ref.append(4)
print(nums)  # [1, 2, 3, 4]

不可变方式:

nums = (1, 2, 3)
ref = nums
ref = ref + (4,)
print(nums)  # (1, 2, 3)
print(ref)   # (1, 2, 3, 4)

解释与原理

可变值让“状态变化”隐式发生,易产生别名问题;
不可变值把变化变成显式的新值,便于推理与测试。

常见问题与注意事项

  1. 不可变一定更慢吗?
    不一定。结构共享与持久化数据结构可以降低成本。

  2. 可变值是不是更直观?
    对局部数据更直观,但对共享状态更危险。

  3. 如何混用?
    常见做法是“核心域不可变,边界层可变”。

最佳实践与建议

  • 在并发场景优先不可变
  • 在性能关键、局部封闭场景用可变
  • 给团队建立明确的可变/不可变规范

小结 / 结论

可变值适合局部与性能场景,不可变值适合共享与核心逻辑。
真正的工程实践不是二选一,而是分层与约束。

参考与延伸阅读

  • Effective Java:不可变对象章节
  • Clojure Persistent Data Structures
  • Rust Ownership Model

元信息

  • 阅读时长:7~9 分钟
  • 标签:可变性、不可变性、并发
  • SEO 关键词:Mutable, Immutable, 并发安全
  • 元描述:对比可变与不可变的优缺点,并给出工程选型建议。

行动号召(CTA)

列出你项目中最容易被“误修改”的对象,从把它变成不可变开始。