A common activity during software development is deciding when and how to functionally decompose your code. I take some liberty with the broad term functional decomposition here, and am specifically referring to *breaking down or refactoring larger functions or methods into smaller functions or methods*. At Atomic Object, we’ve sometimes referred to this practice as _rolling out the dough_.
Some reasons that drive me to start decomposing, and become my *when*, are:
* complicated unit tests
* the “single responsibility principle”:http://en.wikipedia.org/wiki/Single_responsibility_principle
* implementation readability
* refactoring for re-use of common code elsewhere
These are but a few of many reasons that provide us, as programmers, context for some much needed dough rolling. Lately I’ve been pondering *how* the next step should be taken given the options.
*An Aside*: At Atomic Object we write a good amount of our OO code in a functional style, where many of our classes are akin to a state-less module (instantiated as a non-enforced singleton) with one or a few methods defined on it. I find this approach useful when solving problems not directly related to data modeling, where thinking functionally feels more natural.
Once poised to break down a larger function, *how* do you approach it?
* Do you define a new private method or non-exported function?
* Would you make a new class or module with a public method or function to promote re-use within your project?
* Would you add a new public method or function to the same module, preferring categorized groups of functions over many small modules?
* How much does the context of decomposition matter to your decision?
h2. What I’ve done
Given a “functional” OO environment I’d usually default to making a new class with a public method. This feels like the cleanest approach to a scenario where I:
* can unit test the new function in the easiest way for the resulting implementation
* can produce a separation in the original implementation that’s easy to use interaction based testing on (mocks), if desired
* provide a publicly tested interface to the new function that can be used elsewhere
h2. What do you do?
Do you have a preferred approach for rolling out the dough in your language of choice?
My first tool is to extract as well, usually to a new method at first.
When I extract to a new method I usually don’t write unit tests since it can take many hours to write even simple tests where I work. It’s low risk since I use my IDE to extract for me. If there’s a lot of things passed to the new method, if it uses few instance variables, or if it has several methods or fields that are only used by it, then I extract a new class.
When I extract to a new class then I usually do write unit tests since it provides a good opportunity to clean up dependencies with constructor injection.
I always make everything public at first. Otherwise someone else may look for the same functionality, not find it, and reimplement it. If the class’s public api becomes too big then it’s probably time to extract it.
I’m not sure what a “context of decomposition” is but it looks like I follow the same process as you for the same reasons. That’s reassuring for me.
“At Atomic Object we write a good amount of our OO code in a functional style, where many of our classes are akin to a state-less module (instantiated as a non-enforced singleton) with one or a few methods defined on it. I find this approach useful when solving problems not directly related to data modeling, where thinking functionally feels more natural.”
I’d love to read a separate blog post just on this.
Matt: Here’s an intro – https://spin.atomicobject.com/2012/06/04/bringing-fp-to-oo/
Comments are closed.