Old call for volunteers still up to date

Pennell, David dpennell at quallaby.com
Tue Apr 18 14:25:39 UTC 2000


> EncodingFilters can be found in the current image and are used by  
> the Morphic Postscript-Canvas.  EncodingFilters formalize a specific  
> kind of double-dispatch pattern that has various objects or 
> an object  
> graph such as a morphic world interacting with a single "encoder"  
> object such as a morphic canvas.

Note:  Look at the class hierarchy starting with NullEncoder.  There
are no classes with names similar to EncodingFilters.
 
> The specific action to perform in such a pattern depends on both the  
> specific morph in question and the specific canvas it is being drawn  
> on.  A similar pattern holds for most encoding tasks, be it  
> printing, storing, marshalling, etc.  Currently, these operations  
> either (a) don't implement a double-dispatch (printOn:), which means  
> that related operations cannot share code, or (b) implement 
> their own  
> ad-hoc double-dispatch mechanism.
> 
> Morphic's drawOn: method was modified last year from an (a)-style  
> implementation, with a morph's drawOn: method sending drawOn: to its  
> submorphs, to a (b)-style implementation that indirects through the  
> canvas, giving it a chance to intervene.
> 
> So EncodingFilters aren't really some brand-spanking new concept,  
> but just a factoring of a common pattern (the double-dispatch style  
> from above) into a class, with subclasses for common variations and  
> as starting points for specific subclasses.  At least that's the  
> "Encoding" part of it.
> 
> The "Filter" part comes from having a simple + symmetric interface  
> that allows encoding-filters to be arranged in processing pipelines,  
> because each filter sends its results to a "target" filter.  To  
> encode an object via a filter, you send it the #write: message with  
> the object to be encoded as its argument.  The filter processes the  
> object in a filter-specific way and sends the result to its target  
> filter, again using the #write: message.
> 
> In techno-babble, one could call it a reactive data-flow  
> architecture, because unlike "traditional" data-flow systems, a  
> filter never actively pulls data, it just sits and reacts to data  
> sent to it.
> 
> The reason I think EncodingFilters would be useful in refactoring  
> printing is that they actually allow variants of printing operations  
> to be easily defined as new filters.  Variants of #printOn: cannot  
> easily reuse existing implementations because the #printOn: selector  
> is hard-coded into the methods (an a-style implementation), whereas  
> the double-dispatch of EncodingFilters allows the selector to  
> effectively reside in the stream and thus be variable where  
> appropriate.
>
> I hope this is at least a little clear.


Thanks for the explanation.  Between this and your previous post
and a lot of ALT-M and ALT-N's, I think I finally understand.

My own spin:

- Externalizing encoding is "a good thing" because you can never
  anticipate all of the environments that your objects will live
  in.  [e.g. FormCanvas/PostScriptCanvas, SQLDatabase/ObjectDB,
  CORBA/XMLRPRC, etc.]
- An external encoder is a convenient place to put all the support
  methods needed.  This is especially true when the client object
  only common ancestor is Object or another similarly broad class.
  This is hard to illustrate with #printOn: because it doesn't 
  typically need much support other than #nextPut:, #nextPutAll: and
  #print.  It easier to see in the Canvas examples.
- Extending this framework with DecodingFilters would be interesting.
- Double-dispatch and pluggable objects are certainly powerful 
  implementation techniques, but produces code that is difficult to
  read (at least to me).  Has anybody seen or thought about ways to 
  improve this? 

-David





More information about the Squeak-dev mailing list