Posts Tagged 'Refactoring'

Why I still use bulleted functions

When implementing a function, I clearly know what the function will do and how. I know which services will be used within or without class scope; I limit the function’s responsibility and anticipate a concise implementation.

Over time, requirements will grow; more true for generic ‘milestones’ (setup, update functions, etc…). Sprouting functions avoid growing large functions, however this requires defining new semantics; naming functions is time-consuming and does not contribute to solving the problem at hand. When would we ignore the sprouting rule and let functions grow? Is there a workable compromise?

I usually break down function bodies into paragraphs, typically annotated as follows:

// do this...

...

// do that

...

…and so forth; breaking down a function into commented paragraphs is the first remedy I apply when spotting hard to read, bulleted functions; this takes less time than sprouting functions and may be a good preliminary to the latter; however, I do not yet plan on sprouting functions later on:

  • Commented paragraphs may be clearer than uncommented sequences of function invocations.
  • Commented paragraphs immediately reveal behaviour implementation.
  • Considering flow, this is less intrusive than defining a new function – no need to investigate concise, clear word concatenations; no need to layout an auxiliary function ‘somewhere else’ in a class file and scroll back and forth (in my experience, sprouting functions within a plain text editor will corrupt any logical ordering you attempt imposing on your members)

A good developer won’t advise you doing this, however:

  • Sprouting a function instead would scope your code – you will easily know what variables are involved in carrying a substep (if you’re evil, you will define class level privates to avoid passing arguments, and lose this benefit)
  • You are violating the single responsibility principle.
  • You are limiting opportunities to reuse the code.
  • Granted correct naming, sequences of slave function invocations are even more readable than commented paragraphs: sub-level statements hinder not our understanding of the main function.
  • Comments are unreliable – comments don’t compile and get out of date once commented code has been updated.

You may still feel uncomfortable with sprouting functions – so do I, and here’s why:

  • Sprouting functions obscure internal class design. If we afford inner classes and time enough to keep implementations tidy, I have no qualms.  But do we?
  • A private function used only once within a class formally advertises itself as reusable. If you are collaborating, somebody might start using a private member not actually meant for reuse. Another developer will modify the slave function for the benefit of either caller, potentially breaking your code.
  • Designing readable, concise function names is hard enough. A comment in the context of a sequence of instructions isn’t. In order to correctly name a sprouting a function, you may need to express the function’s intended invocation context as well as its intended behaviour.
  • Over time, sprouted function names are no more reliable than commented code paragraphs. Beyond self-consistency, function names are no less arbitrary to compilers than comments; meanwhile they are harder to change.

As a rule, I don’t sprout a function unless I need to share the code, perceive clear responsibility and safely anticipate accidental reuse.

=> In ECMAScript you surely can define slave functions by nesting them into other functions, right?
…I won’t be the first to try this.



Follow

Get every new post delivered to your Inbox.