Guillermo,异常处理可以无缝地替换这里的一些坏主意:
- 使用 thisContext (这几乎没有必要,通常是个坏主意)
- 传递字符串,例如 '1|'、UserInterface invalidCartIdErrorMessage
- 使用 return: 与这些字符串一起传递错误
此外,retrieveCart:onErrorReturnFrom: 做得太多了。使用所有错误处理程序,实际的逻辑会丢失。
所以,我要做的第一件事是创建 Error 子类来表示您的域概念,例如 AddBookError、CartExpiredError、InvalidCartError
然后你只需设置错误消息,可能像:
CartExpiredError>>initialize
super initialize.
self messageText: '1|', UserInterface cartHasExpiredErrorMessage.
接下来的事情(实际上是两个步骤)是用私有访问器替换原始字典方法,它可以使用您的新错误类,如下所示:
timestampFor: aCartId
^ cartCreationDateAndTime at: aCartId ifAbsent: [ InvalidCartError signal ].
和
cartNumber: aCartId
^ carts at: aCartId ifAbsent: [ InvalidCartError signal ].
Cart>>add: aQuantity booksWithISBN: aBookISBN
fail ifTrue: [ AddBookError signal ].
现在,retrieveCart:onErrorReturnFrom: 可以变成:
retrieveCart: aCartId
| aCartCreationDateAndTime |
aCartCreationDateAndTime := self timestampFor: aCartId.
Time now > (aCartCreationDateAndTime + 30 minutes) ifTrue: [ CartExpiredError signal ].
^ self cartNumber: aCartId.
最后,大大简化的 A 变为:
add: aQuantity booksWithISBN: aBookISBN toCart: aCartId
| aCart |
[aCart := self retrieveCart: aCartId.
aCart add: aQuantity booksWithISBN: aBookISBN]
on: Error
do: [ :e | ^ e messageText ].
^ '0|OK'.
这仍然可以被清除(例如,为所有在 messageText 前面加上 '1|' 的错误类创建一个超类),显然你必须将这个简化版本应用到你的实际项目中,但是你可以开始看看异常是如何发生的吗?让你的生活更轻松?
这是代码的工作模型,在 github 上通过了测试
nb 我注意到的另一件事是aCartCreationDateAndTime。将其作为购物车的属性似乎更自然,但在实际应用中这可能没有意义......