[Cuis-dev] Gatekeeper example from "Discovering Smalltalk"

Mark Volkmann r.mark.volkmann at gmail.com
Sun Jan 26 14:29:13 PST 2025


Wonderful! Thanks so much for showing me how to improve that code!

On Sun, Jan 26, 2025 at 3:34 PM Juan Vuletich <juan at cuis.st> wrote:

> 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 Vuletichcuis.stgithub.com/jvuletichresearchgate.net/profile/Juan-Vuletichindependent.academia.edu/JuanVuletichpatents.justia.com/inventor/juan-manuel-vuletichlinkedin.com/in/juan-vuletich-75611b3twitter.com/JuanVuletich
>
>

-- 
R. Mark Volkmann
Object Computing, Inc.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.cuis.st/mailman/archives/cuis-dev/attachments/20250126/b586d159/attachment-0001.htm>


More information about the Cuis-dev mailing list