I recently dealt with some code that I felt was not properly encapsulated, but in a sense that I’ve not seen articulated in this way before. Please enlighten me if I missed it.
Here’s a snippet:
OutputThing manipulate( InputThing input ) { ProcessingThing proc( input ); moreProcessing( proc.intermediateResult, input ); return OutputThing( proc ); }
This function takes in some input and returns some output, using a ProcessingThing to do some work.
I needed to make a change to ProcessingThing to support some functionality, and I fell foul of something I didn’t expect.
I wanted to transform my input a bit, and wrote that code inside ProcessingThing. What I didn’t expect was that the untransformed input would later be used (in the moreProcessing call). The moreProcessing code failed because the transformation I had done made the ProcessingThing inconsistent with the InputThing.
Obviously, I should have checked more carefully.
But, it struck me that there is a pattern here. We are processing something by passing it from step to step in a “production line” of code. By re-using something from an older step, we violate this metaphor of passing on responsibility, because suddenly there are two copies of our input – it wasn’t passed on at all.
This feels a bit like we’ve violated the encapsulation of input by ProcessingThing, but maybe I’m stretching the word encapsulation too far?
I feel like if ProcessingThing properly encapsulated the details of InputThing, we wouldn’t need to re-use input later.
In fact, the fix in my case was to put the moreProcessing logic into ProcessingThing, meaning there was no need to refer back to the original input. I think this supports the argument that we are talking about encapsulation.