Sunday, September 28, 2003

Re: Nifty Trick

Got the following reply via email about my Nifty Trick post. I've posted my reply along with the original email. Enjoy!


Hey,
First off, thanks for your comments! I thought about doing it the way you specified. But, I decided the proxy was too much. Here's why: There's only a handful of methods that need to be recorded in the public interface of the agent actually. And I thought the #triggerCommandEvent was easier to implement. Now, the agent simply "broadcasts" events and doesn't care if anyone is recording them or even listening to them. So, you could have mulitple recorders listening to the same agent. The tape registers itself as a listener on the agent object only when it is in "reocrd" mode. Otherwise, the tape is not registered and does not care what the agent is doing. Actually, the tape has several states it can be in and this is implemented via the State pattern. So, it's acutally, the "record" state that registers itself to the agent and unregisters when stop is pressed. I need to put up the source for the Agent program soon. But, I love these types of design discussions.

I posted the nifty trick simply because "walking the stack" is a pretty cool feature of Smalltalk and most dynamic languages actually. I must admit that I try NOT to use it, because like you said, "it makes the code less portable", but I knew when I wrote the agent that it would just run in Dolphin. Also, I thought it was cool to generically "record" the method by walking the stack and then calling that method with its parameters on any object that implemented that protocol. Now, my code for the Java Serialization is a different matter. I want to make that portable as I can. But, I thought I would at first implement it in Squeak and then worry about portability issues.

Thanks for reading my blog!
------------------------------------------------
Blaine Buxton
My Amps: Smalltalk, Lisp, and Ruby
http://www.blainebuxton.com

>From: Reinout Heeck
>To: blainebuxton@hotmail.com
>Subject: Re: Nifty Trick...
>Date: Sun, 28 Sep 2003 14:23:16 +0200
>
>Your blog's reply box only allows 400 characters :-/
>So I respond by email.
>
>
>
>----------
>
>
>It seems to me that when you use your code to replay the 'tape' the
>actions get added to the tape once more.
>
>Is this the intended behavior or do you switch to a different object
>(no recording) when playing back?
>
>
>
>Allow me to suggest a variation:
>
>remove the calls to #triggerCommandEvent and instead wrap the Agent
>with a generc proxy, implement #doesNotUnderstand: on the proxy to
>both record the message and resend it to the Agent.
>
>Advantages:
>
>1) no more stackwalking so more portable code
>2) possibility to wrap multiple recorders around one Agent
>3) more generic: you can now record messages to any object type
>4) decoupling: the Agent does not take on the responsibility of
>recording. (The developer does not need to remember to insert 'self
>triggerCommandEvent' in the right places)
>5) clearer code:
>
>Agent>>withRecorderOnTape: aWriteStream
>
> ^Recorder on: self tape: aWriteStream
>
>
>
>Recorder>>doesNotUnderstand: aMessage
>
> tape nextPut: aMessage.
> ^subject
> perform: aMessage selector
> withArguments: aMessage arguments
>
>
>
>Disadvantage:
>this breaks encapsulation, the calling code needs to know which
>message sends need recording and which don't and send them to the
>correct object (agent vs wrapped agent), see 4) above.
>
>
>
>Cheers!
>
>Reinout
>-------
>

No comments: