12.12: Example — Deprecation
- Page ID
- 45972
Deprecation offers a case study of a mechanism built using resumable exceptions. Deprecation is a software re-engineering pattern that allows us to mark a method as being “deprecated”, meaning that it may disappear in a future release and should not be used by new code. In Pharo, a method can be marked as deprecated as follows:
Utilities class»convertCRtoLF: fileName "Convert the given file to LF line endings. Put the result in a file with the extention '.lf'" self deprecated: 'Use ''FileStream convertCRtoLF: fileName'' instead.' on: '10 July 2009' in: #Pharo1.0 . FileStream convertCRtoLF: fileName
When the message convertCRtoLF:
is sent, if the setting raiseWarning
is true
, then a pop-up window is displayed with a notification and the programmer may resume the application execution; this is shown in Figure \(\PageIndex{1}\) (Settings are explained in details in Chapter 5). Of course, since this method is deprecated you will not find it in current Pharo distributions. Look for another sender of deprecated:on:in:
.
Deprecation is implemented in Pharo in just a few steps. First, we define Deprecation
as a subclass of Warning
. It should have some instance variables to contain information about the deprecation: in Pharo these are methodReference
, explanationString
, deprecationDate
and versionString
; we therefore need to define an instance-side initialization method for these variables, and a class-side instance creation method that sends the corresponding message.
When we define a new exception class, we should consider overriding isResumable, description, and defaultAction. In this case the inherited implementations of the first two methods are fine:
isResumable
is inherited fromException
, and answerstrue
;description
is inherited fromException
, and answers an adequate textual description.
However, it is necessary to override the implementation of defaultAction
, because we want that to depend on some particular settings. Here is Pharo’s implementation:
Deprecation»defaultAction Log ifNotNil: [:log| log add: self]. self showWarning ifTrue: [Transcript nextPutAll: self messageText; cr; flush]. self raiseWarning ifTrue: [super defaultAction]
The first preference simply causes a warning message to be written on the Transcript
. The second preference asks for an exception to be signaled, which is accomplished by super
-sending defaultAction
.
We also need to implement some convenience methods in Object
, like this one:
Object»deprecated: anExplanationString on: date in: version (Deprecation method: thisContext sender method explanation: anExplanationString on: date in: version) signal