摆脱烦恼

2022-02-14 23:18:31

我真的很喜欢围棋编程语言。第一次使用它时,它看起来有点滑稽,但过了一段时间,当你发现编写服务器软件是多么方便时,你会觉得“啊,我明白了”——这是理所当然的。但就像在任何语言中一样,有几件事真的很烦人。

Java做得很好的一件事是Javadoc。您可能喜欢,也可能不喜欢文档的语法或呈现方式,但它有一些重要的特性。比如能够显式地记录参数、返回值和可能会被抛出的异常。在记录方法时,您希望这样做,因为它与您应该如何测试和评估代码有关。

编写方法,记录参数、返回值和异常,以及前置和后置条件。然后,当您编写测试时,您测试的是文档中承诺的内容。你不考虑实现——你只使用Javadoc。如果这个方法符合tin上的说明,很好,那么你可以继续编写测试,在了解方法内部情况的基础上进行操作。但如果你不能信守承诺,你必须先回去解决这个问题。

这是一个很好的做法。在某些时候,这会揭示出你的承诺并不总是你所能实现的。返回时会发生什么,或者给方法输入异常的输入时会发生什么,这尤其容易搞砸。

对于应该如何彻底地记录和测试代码,有不同的思想流派。我的目标很简单:给定文档和测试,您应该能够重新创建测试中的代码。

将文档和测试视为代码的一部分。你应该能够删除和重新创建代码,只需要文档和测试。

有清晰标识参数、返回值等的标记意味着您可以自动检查是否确实记录了所有应该记录的内容。该工具可以指出您懒惰的地方。

我不喜欢围棋。当您习惯于让工具帮助您了解自己的马虎之处时,Go文档注释是一个很大的倒退。您没有任何用于指定参数和返回值的语法。而且对注释的要求几乎毫无用处:注释必须以函数名开头,并且名称后至少还有一个单词。是的,因为这确保了合理的评论,对吗?

您应该记录参数,但实际上没有任何好方法可以通过编程精确地在注释中查找参数文档。这意味着没有好的方法以HTML或其他格式呈现它。作为文档的使用者,您最终会扫描文本中的参数和返回值,同时必须向下浏览函数签名。

由于没有记录参数的好方法,开发人员往往会对此马虎。包括我自己。阅读文档会带来更大的认知开销,每个人都会为此付出代价,因为每个人都将查找某些内容,并且可以从精确性中受益。我经常发现自己不得不阅读代码,因为文档不够精确。Java实际上做到了这一点。我没去。

最初的Go-linter的维护者倾向于站在没有帮助的一边——坚持认为广泛使用的有效实践应该产生linter警告。例如,当linter抱怨公共函数返回未报告的结构时。在某些情况下,这样做是有正当理由的,应该可以关闭警告。但任何这样做的请求都被拒绝了。

我记得看到的一个更荒谬的建议是“好吧,那就忽略掉林特对此的抱怨吧”。

这不是好工具的工作方式。如果你不得不允许生成产生警告的版本,你很快就会被警告淹没,看不到你真正关心的那些。还记得Java中典型Maven构建的输出吗?太吵了,你根本看不到有新的警告出现。因此,警告变得毫无用处。

不听取开发者意见的结果是什么?现在我们有了好几根,而不是每个人都用一根。必须安装、理解和管理。虽然你可能会耸耸肩,说这是件好事,但如果99%的开发人员都能达成一致,并且这可以成为标准工具的一部分,那就更有用了。它不必要地分割了Go的使用方式。

虽然我们讨论的是碎片化,但Go在日志记录方面也可以从Java学习。不是因为Java做的每件事都是对的,而是因为Java做了很多错误的事情,我们可以从中学习。

当日志记录成为Java1.4标准库的一部分时,已经存在大量日志记录框架。其中一些相当可怕的东西又大又笨又慢。但大多数程序员关注的是这些工具中的一些,它们将日志消息呈现到磁盘、网络或控制台上。人们选择框架是基于美学,而不是技术合理性。

爪哇伐木业最终成为一场彻头彻尾的灾难。要想从混乱中摆脱出来,需要做很多工作。是的,java。util。伐木确实有弱点。堆栈跟踪生成过去很慢,但很快就不再是问题了。它应该有一个API,允许您将插值延迟到您知道日志消息是否会被输出时。但它非常简单,易于理解,非常易于使用,而且它是一个更好的起点,可以为大多数开发人员提供支持。

所以Go肯定从中学到了什么?不,Go似乎什么都没学到。内置的日志记录是最原始的。它甚至没有日志级别的概念。更不用说任何有用的结构了。为什么设计人员不能在开始使用日志包之前,花一两天时间与经验丰富的Java程序员交谈,并尝试了解一些关于日志的知识?知识是存在的。他们只是没有利用它。

结果如何?我们现在有很多不同的日志框架,抽象不是很好,没有一种方法可以登录Go,而且问题似乎每年都会变得更糟。

大多数语言都有strftime(3)的语法变体。大多数程序员都知道这种语法是如何工作的。靠记忆你不必查。那么,你到底为什么要发明一种新的时间格式语法,要求你记住一个“神奇”的时间戳,并试图记住它是否遵循了美国不合理的月/日顺序的做法。不过,它有一个补偿功能:更容易在小数秒内指定所需的位数。但这不是一个需要解决的问题。这个解决方案并没有降低认知开销。