13.07.2015 Views

Smalltalk Best Practice Patterns Volume 1: Coding - Free

Smalltalk Best Practice Patterns Volume 1: Coding - Free

Smalltalk Best Practice Patterns Volume 1: Coding - Free

SHOW MORE
SHOW LESS
  • No tags were found...

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

Lookup CacheHow do you optimize complex Detect or Select/Reject loops?The simplest solution is just to keep your code in its original form. Sometimes what you are doingis looking up an element by a simple attribute:childNamed: aString^self children detect: [:each | each name = aString]Sometimes you are computing subsets of the elements in a collection:childrenWithHairColor: aString^self children select: [:each | each hairColor = aString]These are simple to write and simple to read. This first time you need code like this, you shoulddefinitely write it in terms of Enumeration.For large collections or frequently computed expressions, this kind of computation can be aperformance bottleneck. If you measure a problem with one of these expressions, you may be ableto cache the result of computation and reuse it rather than recomputing it.As with all caches, you will only be able to do this if you can keep the contents of the cachesynchronized with changes to the collection and its elements.Prepend “lookup” to the name of the expensive search or filter method. Add an instancevariable holding a Dictionary to cache results. Name it by appending “Cache” to the name ofthe search. Make the parameters of the search the keys of the Dictionary and the results thevalues.The first example above turns into a variable called “nameCache”. First, we change the originalmethod to:lookupChildNamed: aString^self children detect: [:each | each name = aString]Assuming the variable holding the lookup cache is initialized (see Explicit Initialization and LazyInitialization), we rewrite “childNamed:” as:childNamed: aString^nameCacheat: aStringifAbsentPut: [self lookupChildNamed: aString]VisualWorks doesn’t implement at:ifAbsentPut:, and VisualAge takes an object as the secondparameter, not a Block, so you have to write:childNamed: aStringnameCacheat: aStringifAbsent:[nameCacheat: aStringput: (self lookupChildNamed: aString)]The second example above has collections as the values in the Dictionary instead of single objects,but other than that, the pattern plays out similarly:<strong>Coding</strong> <strong>Patterns</strong> page 118 of 147 9/30/2006

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!