有效使用 ML:错误、抽象与复杂度管理

原标题Effective ML: Errors, Abstraction and Managing Complexity

一位 Jane Street 工程师讨论显式处理失败、样板代码、类型系统的克制,以及副作用的实际作用。

频道
Jane Street
发布
2016年3月31日
视频
23:58
阅读
5 分钟
原文
英语
在 YouTube 打开
往下滚动阅读时,视频会缩到右下角继续播放。字幕跟随阅读语言。
阅读语言共 2 种语言可读
由 AI 从英语原文翻译。打开“对照原文”可以逐段核对。
摘要

30 秒看懂

在 Effective ML 演讲的第二部分,讲者认为,可读且健壮的软件应明确表达失败,并抽象重复模式,同时避免引入不必要的复杂度。他还讨论了可变状态、代码审查、团队规模、交易中人的参与,以及历史上选择 OCaml 的原因。

  1. 1option 与异常根据调用者的需求,查找操作可以返回 option,也可以提供名称明确的异常版本。
  2. 2样板代码掩盖变化重复代码难以一致更新,审查起来也很枯燥。
  3. 3复杂度才是敌人如果精巧的类型级不变量让接口无法理解,它就没有帮助。
  4. 4作为通信的状态修改共享可变状态将程序的不同部分连接起来,可能使局部推理更困难。
  5. 5审查关键代码讲者介绍了交易系统关键路径上的多人审查和测试。

要点建议

  1. 当调用者需要处理预期中的失败时,应在类型中表达失败,并清楚命名会抛出异常的替代函数。
  2. 抽象重复模式,让共同的行为和有意义的变化都清晰可见。
  3. 如果额外的静态保证让接口复杂得难以理解,它并不一定更好。
  4. 避免不必要的状态修改,同时认识到有用的程序需要副作用。
  5. 代码审查、测试和规模较小且目标清晰的项目有助于构建可靠系统。
  6. 语言选择取决于应用的性能和运行需求。
全文

按章节阅读整理后的全文

只看原始文稿
01

明确表达错误

讲者对比返回 option 的接口与异常,并解释为什么错误处理选择取决于失败的后果。

有效使用 ML 编程的关键思想之一,是让被调用函数中的常见错误清晰而明确。人们常说只应在异常情况下使用异常,这背后有两个顾虑:异常产生非局部控制流,而隐式错误处理容易让人忽略失败。

我并不完全反对异常;它们很有用。但失败是否属于异常情况取决于调用者的上下文。一段代码可能确信列表查找总能找到元素,而另一个调用者可能确实不知道元素是否存在。

列表接口可以同时提供返回 option 的 find 和可能抛出异常的 find_exn。前者在类型中表明结果可能不存在,迫使调用者处理;后者通过名称表明可能发生异常。我们的约定是,对于可能因输入而经常失败的操作,使用 _exn 后缀。

通常返回 option 的版本更好,因为类型系统承载了失败的可能性,而不只是依靠命名约定。我们从实践中学到了这一点,并按这种风格修改了大量代码,以提高健壮性。

上下文对错误处理设计很重要。MLton 编译器的作者 Stephen Weeks 加入 Jane Street 后,发现自己的看法发生了变化:编译器因异常退出并打印堆栈跟踪固然不便,但交易系统在交易日中途崩溃是严重得多的问题。

有些接口完全避免了这个问题。fold 可以处理空列表,不像要求列表头部存在或查找成功的操作。错误行为简单的函数更容易放心使用;明确的失败条件也让其余情况更容易推理。

02

避免样板代码

重复模式可能掩盖错误,也难以更新。ML 的抽象可以清楚表达共同模式及其变化。

接下来,要避免样板代码:反复复制相似代码,并做一些细小但重要的修改。即使优秀的程序员也会这样做,因为语言可能没有提供容易表达该模式的抽象,或者他们不知道如何表达这种抽象。

重复造成两个问题。模式会演变,开发者修改时可能遗漏众多副本中的某一个。重复代码也很枯燥,难以审查;人们可能仔细检查第一处,却忽略后续副本中的重要差异。

对于这类模式,C 提供的抽象工具相对有限,常见选择是宏或复制代码。ML 提供函子和高阶函数。我建议对重复保持低容忍度:即使只有两份副本,也值得寻找抽象。

即使抽象让代码变长,也可能值得。局部函数将共同模式写一次,参数则显示哪些部分会变化。与几份几乎相同的代码相比,结果可能更明确、更容易理解。

03

控制复杂度

类型级保证和纯度很有价值,但过度精巧会让代码更难理解。目标是取得实际的平衡。

强大的类型系统带来相反的诱惑:因为有趣且可行,就不断编码更复杂的不变量。我见过一些接口,即使解释过,有经验的 ML 程序员仍无法理解。到了这一步,额外的静态保证可能增加了整体复杂度,而不是提供帮助。

软件工程的核心挑战是管理复杂度。学习巧妙的技术,在有帮助时使用它们,但也要有所克制。代码必须适合维护者理解,而不只是符合优雅的抽象模型。

副作用和状态修改也需要类似的平衡。应优先避免不必要的修改,因为共享引用是程序不同部分之间的通信通道。这些通道连接相距较远的代码,使孤立地理解一个组件更加困难。

不要把纯度变成宗教。有用的程序要与外部世界交互:读取 socket、写入文件或查看时钟都是副作用。Haskell 有纪律地分离纯代码和有副作用的代码,但并没有从有用程序中消除副作用。

将副作用推向程序外围可能有帮助,但前提是结果不能比直接的命令式方案更复杂。有时命令式算法更容易理解,或者不需要精巧机制就能获得良好性能。目标是构建满足任务所需的最简单系统。

04

关于工程与交易的问答

讨论涵盖代码审查、小团队和人在交易系统中的作用。讲者最后回顾了历史上选择 OCaml 的原因。

有人问到审查时,我解释说 Jane Street 将从交易决策到进入市场之间的代码视为关键路径。多个人——至少两人,通常三人——被指定在代码进入生产环境前审查变更,内部系统负责追踪审查。单元测试和回归测试也很重要,但审查是保持系统安全和一致的核心。

我们尽量将开发组织成目标清晰的小组项目,人数大致从一人到最多六人。较小、相对独立的部分可以装进个人的脑海,并组合成更大的系统。我认为让一个大团队直接共同处理同一块基础设施会很难管理。

有人问到自动化时,我说业务差异很大。有些工作涉及人们通过电话谈判,另一些系统则连续运行数小时,人们主要观察而不是不断修改。大多数系统都需要大量人的参与;公司并不是一台无人看管、自动赚钱的机器。

交易是一场博弈,每笔交易的另一端都有一个参与者。市场模型必须考虑对方。交易员和技术人员的注意力,是人和技术相结合的系统中的核心部分。

演讲时 Jane Street 已使用 OCaml 约九年,在此之前曾使用 Excel、Java 和 C# 等系统。选择这种语言部分是因为我熟悉它。OCaml 也提供了一种有用的平衡:代码具有声明式风格,同时编译策略相对直接且高效。

我们没有选择 Haskell 的一个原因是,以当时的需求来看,它的性能,尤其是空间使用,更难推理。它的实现已有改进,但为提高效率所需的工作会增加复杂度。语言选择取决于所构建系统的需求。

同频道的其他文章

1:48:29EN → 简体中文
JSJane Street· 2026年10月16日AI 如何改变编程:John Krazit 与 Ron Minsky 的对话Ron Minsky, John Krazit · Jane StreetJane Street 的 AI 工具负责人和 Signals and Threads 主持人探讨智能体基础设施、安全、代码审查,以及软件开发体验的变化。编程智能体Developer productivity评估+2
1:36:37EN → 简体中文
JSJane Street· 2026年9月23日Aaron Bauer:在 AI 时代教授软件工程Ron Minsky, Aaron Bauer · Jane Street当模型能够生成代码时,学习目标、主动练习和编辑器设计如何影响工程教育。AI in EducationSoftware engineeringEducation+2
9 张幻灯片1:05:45EN → 简体中文
JSJane Street· 2026年9月11日Cyrus Omar:实时编程与人与 AI 共享的计算公共空间Cyrus Omar通过 Hazel 演示,探讨即时反馈、结构化协作和精细权限如何帮助人类与 AI 智能体共同工作。Programming LanguagesHuman-AI Collaboration开发流程与测试+2
1:25:00EN → 简体中文
JSJane Street· 2026年9月2日Eric Mannes:如何将杂乱的外部数据用于交易研究Ron, Eric Mannes · Jane Street从商品期货和 Excel 风险系统,到时点数据集和 AI,Eric Mannes 解释 Jane Street 数据工程背后的领域知识。Data quality & curation开发流程与测试Investing+2
7 张幻灯片1:16:29EN → 简体中文
JSJane Street· 2026年8月26日Grant Sanderson 与 Alok Puranik:从群论看位置编码Grant Sanderson, Alok Puranik · 3Blue1Brown从注意力机制的假设出发,他们推导矩阵指数,并将旋转、衰减和 Jordan 块与 RoPE、ALiBi 联系起来。Transformers & attentionMathematics机器学习基础+1
27:39EN → 简体中文
JSJane Street· 2026年8月21日3Blue1Brown 与 Jane Street 谈交易、机器学习和文化Grant Sanderson, Nitya, In Young, Craig, Alok · 3Blue1BrownGrant Sanderson 与 Jane Street 的同事讨论做市、共享算力、研究,以及他们加入公司的不同经历。Machine LearningFintechCompany Culture+2