[Cuis-dev] Gatekeeper example from "Discovering Smalltalk"
Juan Vuletich
juan at cuis.st
Sun Jan 26 13:34:51 PST 2025
Hi Mark,
Interesting exercise!
Doing `self become: ` is dangerous and tricky. The very method doing
that will continue execution, but now the receiver is of a different
class! This would crash the system if that methods tries to access
instance variables that are not there. The control in #become: that
bothers you is trying to protect you from that risk.
I suggest slightly different code, to avoid doing `self become:`: move
the sends to #become. to the class side. So:
class side
on: anObject
| proxy |
proxy := self new on: anObject.
anObject become: proxy.
^proxy
instance side
on: anObject
history := OrderedCollection new.
object := anObject shallowCopy.
" anObject become: self"
and class side
restoreAndProvideHistory: aProxy
| result |
result := aProxy history.
aProxy become: aProxy object.
^result
Also add the two needed getters #history and #object. Now the workspace
example does:
history := HistoryProxy restoreAndProvideHistory: date.
This doesn't need any modification to #become:, is more robust and
future proof, and better style.
Cheers,
On 1/26/2025 4:56 PM, Mark Volkmann via Cuis-dev wrote:
> I recently read the book "Discovering Smalltalk". I know it's quite
> dated and it's based on Smalltalk/V instead of Smalltalk-80, but I
> still learned a lot from it.
>
> I implement the Gatekeeper example described on pages 428-430 in Cuis.
> It demonstrates using the becomes: method to track all messages sent
> to a given object. I got it working, but I had to make a small
> modification to the ProtoObject instance method becomes:. I'm
> wondering if my change would break other uses of this method.
>
> I replaced the line
>
> selfMethod = otherObjectMethod ifFalse: [
>
> with
>
> selfMethod ~= nil and:
> [otherObjectMethod ~= nil] and:
> [selfMethod ~= otherObjectMethod] :: ifTrue: [
>
> Here's my working Gatekeeper code where I renamed that class to
> HistoryProxy.
>
> Object subclass: #HistoryProxy
> instanceVariableNames: 'history object'
> classVariableNames: ''
> poolDictionaries: ''
> category: 'Demo'
>
> "class method"
> on: anObject
> ^ self new on: anObject
>
> "instance method"
> on: anObject
> history := OrderedCollection new.
> object := anObject shallowCopy.
> anObject become: self
>
> "instance method"
> doesNotUnderstand: aMessage
> "Record the message and reroute it to the object."
> history add: aMessage.
> ^ aMessage sendTo: object.
>
> "instance method"
> restoreAndProvideHistory
> | result |
> "Extract information before mutating because it won't be available
> afterwards."
> result := history.
> self become: object.
> ^ result.
>
> Here's an example of using this:
>
> date := Date today.
> HistoryProxy on: date.
> date monthName print.
> date dayOfWeekName print.
> date year print.
> history := date restoreAndProvideHistory.
> history print "an OrderedCollection(monthName dayOfWeekName year)"
>
> --
> R. Mark Volkmann
> Object Computing, Inc.
--
Juan Vuletich
cuis.st
github.com/jvuletich
researchgate.net/profile/Juan-Vuletich
independent.academia.edu/JuanVuletich
patents.justia.com/inventor/juan-manuel-vuletich
linkedin.com/in/juan-vuletich-75611b3
twitter.com/JuanVuletich
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.cuis.st/mailman/archives/cuis-dev/attachments/20250126/f93a2d4a/attachment.htm>
More information about the Cuis-dev
mailing list