文章摘要
文章阐述了在银行、电信和支付等关键领域,可靠性至关重要。通过函数式编程和代数数据类型(ADTs),可以将业务规则嵌入类型系统,从源头防止非法状态的出现,减少错误。文中还介绍了如何利用模式匹配和穷举检查等技术,以及在实际领域中的建模模式和迁移方案。
文章总结
为什么可靠性需要函数式编程:ADT、安全性与关键基础设施
核心观点
在银行、电信和支付领域,可靠性是基本要求而非锦上添花。函数式编程(FP)和代数数据类型(ADT)能够通过类型系统在代码运行前消除整类错误,使非法状态无法被构造。
关键技术与案例
类型系统保障可靠性
- 常见生产事故多源于非法状态(如魔法字符串
"paypal"、空值null、冲突布尔值isActive=true且isSuspended=true)。 - FP通过ADT建模领域规则,使非法状态无法编译(例如用
Payment = Cash | Card | Pix杜绝非法支付方式)。
- 常见生产事故多源于非法状态(如魔法字符串
ADT实践:积类型与和类型
- 积类型(如用户记录
{id:int; name:string})组合字段,和类型(如支付方式Cash | Card) 表示互斥选择。 - 示例:OCaml和TypeScript中分别用
type payment和type Payment确保支付方式合法性。
- 积类型(如用户记录
模式匹配与完备性检查
- 编译器强制处理所有可能分支,新增类型变体会触发编译错误,确保重构安全。
- 代码示例:
describePayment函数必须处理所有Payment变体,否则无法通过编译。
典型领域问题解决方案
- 银行交易:用
txn_state = Pending | Settled | Failed替代布尔值,防止重复结算。 - 电信计费:
Call = Dialing | Connected | Completed确保仅完成通话才计费。 - 配置解析:
Result类型显式处理NaN等错误,避免隐式转换。
- 银行交易:用
工程实践建议
迁移路线:
- 用和类型替代冲突布尔值
- 用
Option替代null - 用
Result替代异常控制流 - 为数值添加单位标签(如
Cents类型) - 在CI中强制完备性检查
架构设计:
- 纯核心+副作用边缘:领域逻辑保持纯函数,IO操作外推至系统边界。
- 不可变性:通过创建新值而非修改旧值避免并发问题。
结论
ADT、模式匹配和不可变性等FP特性能够将领域规则编码至类型系统,从根本上杜绝非法状态。对于金融、电信等关键领域,采用这些模式可显著降低故障率,提升系统可靠性。
延伸阅读:代数数据类型、模式匹配、不可变对象等概念(原文附维基百科链接)。
评论总结
以下是评论内容的总结:
1. 关于强类型系统与函数式编程的讨论
支持强类型系统:认为强类型系统有助于提高代码可靠性,尤其在约束LLM生成代码时表现突出。
- "when there are bugs the 'blast radius' is much larger in a dynamic language like Python than in a static language like Haskell"(mightybyte)
- "Haskell's pure functions allow you to create much stronger guard rails constraining what kinds of code the LLM can write"(mightybyte)
质疑函数式编程:认为函数式编程在处理复杂错误时可能不切实际,且代码可读性差。
- "Functional programming as in: the final program consists in piping functions together... tends to get in the way of complex error handling"(d--b)
- "Functional programming often leads to write-only incomprehensible code"(pizlonator)
2. 关于可靠性与错误处理的讨论
强调容错性:认为在高风险行业(如银行、电信)中,容错性比追求完美更重要。
- "These types of businesses require fault tolerance... investing heavily into correctness may not be worth it compared to investing into fault tolerance"(charcircuit)
- "Reliability is a cost center and Product-oriented Builders treat it as such"(whateveracct)
质疑绝对可靠性:认为生产环境的事故更多源于系统固有的潜在问题,而非代码状态。
- "Most production incidents are due to the system entering into one of thousands of unsafe states which were possible and latent"(thundergolfer)
3. 关于测试与类型系统的补充观点
测试的重要性:认为纯函数和确定性行为对测试更有帮助,而非函数式编程本身。
- "The main value of pure functions is that now their behavior is representative in tests"(websiteapi)
类型系统的局限性:认为代数数据类型(ADTs)可能不如无标签联合类型实用。
- "The 'tagged' unions of ADT languages... are arguably pretty clearly inferior to the 'untagged' unions of TypeScript"(cubefox)
4. 其他观点
对绝对声明的质疑:反对关于编程的绝对化断言。
- "I'm wary of absolute statements about programming"(wewewedxfgdf)
- "Yet another silver bullet"(FpUser)
工业实践的反例:指出实际工业中关键系统(如AWS)并未依赖函数式编程。
- "AWS... what is it written in? Java"(jatins)
总结:评论中对强类型系统的价值有一定共识,但对函数式编程的实用性存在分歧。多数人认为可靠性需结合容错性和实际测试,而非单纯依赖编程范式或类型系统。