This post originated from an RSS feed registered with Python Buzz
by Ng Pheng Siong.
Original Post: Patterns
Feed Title: (render-blog Ng Pheng Siong)
Feed URL: http://sandbox.rulemaker.net/ngps/rdf10_xml
Feed Description: Just another this here thing blog.
I was writing a Smalltalk program and needed undo/redo
functionality, so went to look up the book Design Patterns, Smalltalk Campanion, by Alpert et al. (Bought this book several years ago from a bookstore warehouse sale: $5, brand new. Browsed it every now and then. Excellent value for money. ;-)
Ah, I want the Command pattern. <tap> <tap>
<tap> Typed the code in. (There isn't much.) The pattern
is implemented in the class AppCommand.
My program has a class called AppWorld that represents the state
of the application. Created a global variable called MyAppWorld
containing an instance of that. All my application-related classes
which need to deal with "the world" talk to MyAppWorld.
In many cases, aReceiver and anApplication are the same, namely,
the global variable MyAppWorld.
Testing of undo failed. Hmmm. Inserted 'self halt'
judiciously to get into the debugger. Popped open a number of inspectors from within the debugger and also a "global existence monitor" for good measure. (This shows the number of instances per class in existence at any time and their memory usage. It is properly called the "memory monitor".)
Stepped through the code in the debugger: Undoing did happen, but
from the memory monitor I could see that somewhere, another instance
of MyAppWorld came into being and the code was operating on the copy,
not the global. Inspecting the two instances showed that they were
identical in structure, just not identical in Smalltalk terms...
Hmmm, perhaps using a global as a singleton isn't good enough and
I need a real implementation of the Singleton pattern. Okay, the book has this. <tap> <tap> <tap> There, AppWorld became a
Singleton.
Tested again, still undo operated on a copy, not the
singleton. Argh!
So what else? <twiddled thumbs> <made coffee> <had
a snack> <checked mail> ... <light bulb went on> Of
course, deepCopy! Browsed its implementation in Object: Ah,
it tells how to exclude objects from being deepCopied:
AppCommand>>deepCopyUsing: aDictionary
"Entries in aDictionary won't be copied. Don't want my
instance variables 'receiver' and 'application' copied."
aDictionary
at: application put: application;
at: receiver put: receiver.
^(super deepCopyUsing: aDictionary)
Tried again. Yes! Undoing did. Memory monitor showed just one
instance of AppWorld.
Message to self: before deepCopying, reflect deeply.