吉列爾莫,異常處理可以無縫地在這裏代替一些不好的想法:
- 使用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'.
這可以仍然被清潔(例如爲所有預先設置'1 |'的錯誤類創建一個超類到messageText),顯然你將不得不將這個簡化版本加入到你的實際項目中,但是你能否開始看到異常情況如何讓你的生活更輕鬆?
Here是代碼的工作樣機,以在github
N.B.通過測試我注意到的另一件事是aCartCreationDateAndTime。將它作爲購物車的一個屬性似乎更自然,但也許在實際應用中沒有意義。
這不是破解封裝爲什麼B應該知道關於A的一切? – Mark
B和A是_same object_上的方法。 –
@Guillermo我仍然試圖圍繞你正在嘗試的東西......除了指定返回值之外,你還在做B中的錯誤處理程序嗎?這是你的目標,即你是否堅持A/B部門,還是靈活?真的,如果你能以較少的以實現爲中心的方式陳述具體的問題,那將會是什麼。我們可以很容易地回答你的問題,但是這在Smalltalk中似乎非常罕見,直覺表示有更好的方法來處理它... –