在Squeak System Browser中,某些messages的左侧有一个红色标记。

我从Balloon消息中看到这是因为我的代码中断了,即self halt: 'foobar'self error:'foobar'

这样不好吗?如何避免呢?我将error消息放在发生特别糟糕的事情的地方,而进一步走下去没有多大意义。就像身份验证失败,从网络获取数据失败一样。

我想做一些类似的事情,例如在这些特殊情况下引发异常,但是,如果可能的话,我不想在一半的方法上看到危险信号。

有标准做法吗?

最佳答案

停顿

#halt是用于调试目的的东西。在大多数情况下,当您想到达执行流中的某个点时,插入一个#halt,然后使用调试器从那里继续执行,逐步执行并检查所涉及的对象。您还可以添加一个#halt来查看是否调用了某些方法,以便更好地了解在评估某些表达式时实际发生的情况。在所有这些情况下,调试完成后都应立即删除#halt

作为一个典型的例子,想象一下您正在调试算法,并且需要更好地理解它为什么会失败。然后插入#halt

computeDiagonal: k
  | product akk diff |
  product := self dotProductLimitedTo: k withRow: k.
  akk := matrix atRow: k column: k.
  diff := akk - product.
  diff < 0.0 ifTrue: [
    state := #fail.
    ^self halt].                                                       "wait a minute!"
  lower atRow: k column: k put: diff sqrt


断言

但是,在某些情况下,您的调查尚无定论,或者所分析的问题无法重现。然后最好留下一些长期迹象,表明不应该发生某件事,或者如果确实发生,则为更好地了解其原因提供了机会。在这些情况下,halt可能有效,但表达能力不足(您不再沉迷于原始问题),因此您可能需要考虑使用#assert:#deny:。这些通常在单元测试中发送的消息也可以以任何方法出现,并传达出更清晰的意图。

请注意,使用#halt#assert:的决定不取决于方法,而是取决于模型的成熟状态。例如,如果您不确定算法不会再次失败,但是您无法重现失败,则应将#halt替换为assert:#deny:

computeDiagonal: k
  | product akk diff |
  product := self dotProductLimitedTo: k withRow: k.
  akk := matrix atRow: k column: k.
  diff := akk - product.
  self deny: diff < 0.0.                                              "got you!"
  lower atRow: k column: k put: diff sqrt


失误

最后,如果您确定应该/不应发生某些事情,#error::是您的最佳选择。 haltassert:error:之间的区别在于,后者用于最终用户,而其他则用于开发人员。

computeDiagonal: k
  | product akk diff |
  product := self dotProductLimitedTo: k withRow: k.
  akk := matrix atRow: k column: k.
  diff := akk - product.
  diff < 0.0 ifTrue: [self error: 'Cholesky decomposition failed'].   "Oh oh..."
  lower atRow: k column: k put: diff sqrt


当然,要充分利用Exception框架,您可能要考虑添加自己的#error:消息版本,以便它表示Exception的特定子类,而不是通用的子类。系统中有很多示例可供您获取灵感。这并非总是必要的(或好的),只是要考虑的事情。

另请注意,Error可能是可恢复的,因此请勿将它们与中止策略相关联。实际上,#halt#assert:确实表示可恢复异常。

结论

调试器是您最好的朋友,并且#halt消息会将其带到代码中的任何位置。但是,将#halt保留在已发布的代码中将被解释为未完成的指示。

断言可以帮助其他开发人员更好地了解如何使用您的对象。但是请抵制过于自信的诱惑。

错误是一种声明异常行为的优雅方法,它可以使开发人员(您)对可能发生的事情有所了解。不要将错误视为文本消息,Smalltalk中的错误是一流的对象,可能包含有价值的信息。

10-08 08:03