I thought I'd follow up on my last technical post with a few extra details about the Marble pattern, despite the name of the article I mostly talked about the Wood pattern. I guess perhaps this is timely because the use of Promises to represent asynchronous operations is increasingly popular, but these notions are not really limited to context pattern, though promises do make for good examples.
So, what are the essential properties?
- objects tend to be smaller and more abundant (model the nodes not the tree)
- dependencies and dataflow tends to be represented on a per object basis
- dependencies frequently make long chains (such as a series of promises lashed to one I/O)
- each object is participating in its own dependency chain but it they are really all the same
- objects tend to be bigger (model the tree not the nodes)
- dependencies and dataflow tend to flow through these big objects, the dependencies are not dependent on the size of the problem but on the necessary transforms
- the dataflow that SQL uses for running a query is an example of this, complexity of plan is determined by joins/merges not by data size
- dependencies still can make long chains but
- the nature of the depenencies is expressed exactly once no matter how much data there is
Again, using promises as an example (and I am not down on promises at all, they work great, but you don't have switch to the wood pattern universally just because you have async i/o)
- create many async requests for data
- attach additional promises to these requests for processing
- end each promise chain with some operation to do whatever needs doing at the end (such as inserting stuff into a DOM)
- create many async results for data
- give the promises to a broker which will handle all of them (and maybe created them in the first place as needed)
- provide any number of handlers to the broker which will run those handlers on each datum as the promises resolve
In the marble pattern I can still write nice anonymous delegates if I choose, or I can provide a class or other handler, whatever is necessary. However I don't create one handler instance for every datum. I created one or more broker objects that handle the various stages of processing and coordinate some or all of the post steps.
From a memory perspective Marble is much more economical and of course it doesn't have the terrible property that I'm making lots of long lived objects. In the wood pattern everything ends up being long lived because everything lives at least as long as the I/O request is outstanding.