Exception 红旗方法不好吗?

Exception 红旗方法不好吗?,exception,smalltalk,flags,squeak,Exception,Smalltalk,Flags,Squeak,在Squeak System Browser(吱吱声系统浏览器)中,一些消息的左侧有一个红色标志 我从气球消息中看到,这是因为代码中有一个中断,即自停止:“foobar”或自错误:“foobar” 这么糟糕吗?怎样才能避免呢?我把error消息放在了一些特别糟糕的事情发生的地方,再进一步也没有什么意义。比如身份验证失败、从网络获取数据失败等等 我想在这些特殊的场合做一些类似于引发异常的事情,但是,如果可能的话,我不想在我的方法中看到一半的危险信号 是否有一个标准的做法来做这件事 如您所知,红旗表

在Squeak System Browser(吱吱声系统浏览器)中,一些
消息的左侧有一个红色标志

我从气球消息中看到,这是因为代码中有一个中断,即
自停止:“foobar”
自错误:“foobar”

这么糟糕吗?怎样才能避免呢?我把
error
消息放在了一些特别糟糕的事情发生的地方,再进一步也没有什么意义。比如身份验证失败、从网络获取数据失败等等

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


是否有一个标准的做法来做这件事

如您所知,红旗表示消息中存在某种类型的
halt
。如果您有一个需要停止执行以检查状态的开发代码,那么这是很好的

也就是说,这样的代码不属于生产代码。这应替换为异常

在squeak中,出现以下异常(ANSI兼容异常):

计算异常块 处理块上下文中引发的异常的方法

  • 消息:确保:A终止块
  • 描述:评估 评估接收器后的A终止块,无论 接收者的评估完成。

  • 消息:IfCurtiled:AterMinerationBlock
  • 描述:评估 接受者如果异常终止,请计算终止块。

  • 消息:on:异常do:handlerActionBlock
  • 说明: 在异常处理程序的范围内评估接收器, 抗手摇块
例子

["target code, which may abort"]
    ensure:
        ["code that will always be executed 
            after the target code, 
            whatever whatever may happen"]

["target code, which may abort"]
    ifCurtailed:
        ["code that will be executed
            whenever the target code terminates 
            without a normal return"]

["target code, which may abort"]
    on: Exception
    do: [:exception |
            "code that will be executed whenever
            the identified Exception is signaled."]
信息的来源是。

停止
#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
错误 最后,如果您非常确定某事应该/不应该发生,
#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
计算对角线:k
|产品akk差异|
产品:=自点产品限制为:k,带行:k。
akk:=矩阵atRow:k列:k。
差异:=akk-产品。
diff<0.0 ifTrue:[自身错误:“Cholesky分解失败”]。“噢……”
下atRow:k列:k put:diff sqrt

当然,要充分利用<代码>异常< /C>框架,您可能需要考虑添加自己的代码< >代码>:< /Case>消息,这样它将发出一个特定的子类:<代码>异常< /代码>,而不是一般的子类。系统中有大量示例可供您获取灵感。这并不总是必要的(或好的),只是需要考虑的事情

还要注意,
错误
可能是可恢复的,因此不要将其与中止策略相关联。事实上,
#halt
#assert:
do表示可恢复的异常

结论 调试器是您最好的朋友,#
halt
消息将把它带到代码中的任何地方。但是,在已发布的代码中留下
#halt
,将被解释为未完成工作的指示

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


错误是一种优雅的声明意外行为的方式,可以让开发人员(您)对可能发生的事情有一个线索。不要将错误视为文本消息,Smalltalk中的错误是第一类对象,可能包含有价值的信息。

感谢您对Leandro的详细解释。
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