Archive for the 'Clean Code' Category

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.

Programming Using State Transitions

Actions Pass, State Remains

Many widely used languages today are imperative. Essentially, most code written using those languages can be reduced to statements, such as:

System.out.println("Hello World");

I had the idea of programming using state transitions while trying to find reasonable ways to formally encourage writing simple, readable code. There are two drawbacks of classic imperative programming that pointedly led me to state transitions:

  • Complex control structures – imperative programming often results in lengthy method bodies – so called ‘bulleted functions’ that could not exist without a complex control structure (I’ll write about this sometimes)
  • Sequential ordering – this allows programmers to write APIs in such a way that using them requires invoking several functions in a predefined order.
  • No matter how convoluted imperative programming can get, actions within a program ultimately aim at modifying runtime or persistent state.

Could modeling and programming using state transitions help increase the clarity and readability of code? This is the question I tried to answer. I’m now looking at typical function types, and what a state oriented perspective tells us about them:

Constructors

Constructors are used to setup the original state of an object. Ideally, the original state of an object can be easily specified using a hierarchy of elements – however, using imperative languages, we often need replacing this by lists of statements like:

ChildType x=new ChildType();
parentObject.addSomething(x);

Actions

An action is a function that modifies the runtime or persistent state of a system. In object oriented programming, an action executes from a locale and modifies state that is reasonably easy to reach from such locale. Often, the crux of any action is to prepare and execute a statement that will add, remove, set or clear a property related to the locale.
Invoking an action allows us to export state to a remote locale.

Queries

A query is a function which, ideally, modifies no state and is merely used to collect information from a given locale. Invoking a query allows us to import state from a remote locale.

Can I use this to improve code readability and simplicity?

Alas, how oft have I started writing a function with clear, straightforward intentions and eventually produced monsters that only the sleep of reason could emulate?

  • Functions that dilute their original purpose in scores of preparation statements.
  • Functions that modify program state in too many ways, with no clear view of where (within the function body) the states are affected.
  • ‘Hidden’ actions modifying the state of my program while advertising query semantics.

As a rule of the thumb, if I can’t concurrently visualise the name of a function and the statement that realises its purpose, I feel something is wrong. Proposed remedies:

  • After writing a function, immediately reconsider its implementation and sprout methods for complex preparation code. It is usually handy to add preparation code wherever needed while writing code, however this eventually makes implementations impossible to read (I wouldn’t sprout methods until after writing the code, because preparation code often needs researching, which requires a different kind of concentration).
  • Avoid functions that concurrently return and modify state – with some exceptions: factory methods are usually fine; returning metadata (succes/failure flags) is sometimes okay (granted many of us think exception handling’s just better).

Even small functions can become fairly confusing because the preparation steps required to realise a state transition typically precede the statement realising the transition. The typical remedy is to bundle preparation code into separate methods. This allows shifting the emphasis back to the target statement while leaving granular details ‘for further reading’.

Pushing state orientation into language design

Recently, I’ve been trying to design a language to better support state orientation. Read on.



Follow

Get every new post delivered to your Inbox.