Skip to content

搞英语 → 看世界

翻译英文优质信息和名人推特

Menu
  • 首页
  • 作者列表
  • 独立博客
  • 专业媒体
  • 名人推特
  • 邮件列表
  • 关于本站
Menu

默认错误

Posted on 2022-05-14

一些编程语言使用“延迟”模式进行资源清理。这是一个结构,例如defer关键字,它安排清理代码在封闭块(或函数)的末尾运行。这在 Zig、Go 甚至 GCC C 中都可用。

 fn printFile ( path : str ) ! void { var f = try open ( path ) defer f . close () for line in f { print ( try line ) } // File is closed here. }

这提供了一些关键的好处。

  1. 清理就在分配旁边。很容易发现并保持同步。
  2. 即使对于早期返回和错误情况,也会自动进行清理。
  3. 清理以正确的顺序自动进行(关键字的相反顺序)。

这是对手动编写和运行清理代码的巨大改进。以上每一点都是常见的错误来源,现在很容易避免。

然而, defer有一个巨大的缺点。你需要记住它。

与 C++ 或 Rust 之类的东西相比:

 fn printFile ( path : & str ) -> std :: io :: Result < () > { let f = std :: fs :: File :: open ( path ) ? ; for line in std :: io :: BufReader :: new ( f ) .lines () { println! ( "{}" , line ? ); } Ok (()) // File is closed here. }

当然,添加一行代码并不难。但你可以忘记。你怎么知道需要close 、 unlock或以其他方式处理的类型?自动处置(称为RAII )让程序员摆脱了这种想法并避免了错误。所有需要清理的东西都在不再使用的时候清理干净。

Java也有同样的问题。许多程序员喜欢垃圾收集器,因为它们会在你之后清理。但是大多数垃圾收集器的问题是它们只清理内存!还有许多其他类型的资源,例如锁、文件、线程和套接字,您需要自己处理。其中一些可以由终结器处理,但由于它们运行之前的时间可能很长,它们不适合某些资源,例如锁。

一个好的资源管理解决方案(例如 RAII)可以处理您的程序使用的所有资源。在很长一段时间内,java 的最佳解决方案是finally块。

 FileInputStream inputStream = new FileInputStream ( "story.txt" ); try { // Read file here... } finally { inputStream . close (); }

虽然这显然比 defer 更多样板并导致令人不快的右移,但实际上是相同的。最重要的是,您仍然需要记住哪些类型需要关闭。

这在 Java 7 中通过try-with-resources 语句变得稍微好一些。

 try ( FileInputStream inputStream = new FileInputStream ( "foo.txt" )) { // Read file here... }

但即便如此,正确性仍需要手动操作。然而,这个特性最好的部分可能是java.lang.AutoCloseable接口。最后有一种方法可以知道需要清理哪些类型。这种机器可见的信息可以允许构建有效的 lint。如果你曾经得到一个AutoClosable类型,你最好在 try-with-resources 语句中使用它,或者快速将它传递给其他人(并将负担转移给他们)。但是复杂的情况很难可靠地检测到。例如,如果您将类型存储在数据结构中并在删除后对其进行清理。即使只是简单地将引用传递给多个地方,也会对谁负责清理它产生歧义。

这个故事的寓意是,避免错误的最好方法是让它们难以编写。理想情况下,使错误比正确的代码更难编写。 defer和 try-with-resources “默认情况下是错误的”,需要代表程序员进行明确的工作才能正确。 RAII 是正确的,无需程序员做任何额外的事情。

这篇文章的灵感来自defer关键字,但这是一个比这更普遍的问题。我记得 Google 上有一篇关于--dont-be-stupid标志的文档。这些通常会在发现错误时添加,但修复包含某些客户端所依赖的行为更改,或者需要仔细推出更改。几年后,大多数服务将有几十个这样的标志,所有这些标志都硬编码在服务配置中。当然,每隔一段时间就会设置一个新的服务实例,这个错误会再次出现。向后兼容性和逐步推出是好的,但在某些时候,您需要更新代码以使其默认正确。

原文: https://kevincox.ca/2022/05/13/wrong-by-default/

本站文章系自动翻译,站长会周期检查,如果有不当内容,请点此留言,非常感谢。
  • Abhinav
  • Abigail Pain
  • Adam Fortuna
  • Alberto Gallego
  • Alex Wlchan
  • Answer.AI
  • Arne Bahlo
  • Ben Carlson
  • Ben Kuhn
  • Bert Hubert
  • Bits about Money
  • Brian Krebs
  • ByteByteGo
  • Chip Huyen
  • Chips and Cheese
  • Cool Infographics
  • Dan Sinker
  • David Walsh
  • Dmitry Dolzhenko
  • Elad Gil
  • Ellie Huxtable
  • Ethan Marcotte
  • Exponential View
  • FAIL Blog
  • Founder Weekly
  • Geoffrey Huntley
  • Geoffrey Litt
  • Greg Mankiw
  • Henrique Dias
  • Hypercritical
  • IEEE Spectrum
  • Investment Talk
  • Jaz
  • Jeff Geerling
  • Jonas Hietala
  • Josh Comeau
  • Lenny Rachitsky
  • Lou Plummer
  • Matt Stoller
  • Mert Bulan
  • Mostly metrics
  • News Letter
  • NextDraft
  • Non_Interactive
  • Not Boring
  • One Useful Thing
  • Phil Eaton
  • Product Market Fit
  • Readwise
  • ReedyBear
  • Robert Heaton
  • Ruben Schade
  • Sage Economics
  • Sam Altman
  • selfh.st
  • Shtetl-Optimized
  • Simon schreibt
  • Slashdot
  • Small Good Things
  • Taylor Troesh
  • Telegram Blog
  • The Macro Compass
  • The Pomp Letter
  • Thinking Deep & Wide
  • Tim Kellogg
  • 英文媒体
  • 英文推特
  • 英文独立博客
©2025 搞英语 → 看世界 | Design: Newspaperly WordPress Theme