在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:
:是您的最佳选择。 halt
,assert:
和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中的错误是一流的对象,可能包含有价值的信息。