String Calculator kata as a single unit of work with state

These are some notes on a String Calculator kata implemented in an “object-oriented” way as a single unit of work with state. Why the air-quotes are used? Because it is not a true object-oriented way of doing things, even though the class keyword and state are used. This kata implementation tends to be sort of procedural.

Before we dive into this solution, we need to look at some key characteristics. This solution does not have/use any collaborative objects. It uses state to retain the results of computations. The decomposition happens only in one file inside one single class.

Code map and responsibilities

More about responsibilities was written in the introductory article. Here is the summary:

  • extraction of numbers (we extract numbers from different string formats) – a high possibility of change
  • validation of numbers (we validate the extracted numbers) – an average possibility of change
  • filtering of numbers (we filter the numbers before the final operation) – an average possibility of change
  • addition of numbers (at we end we add up all the numbers) – a low possibility of change

Let's take the the solution's code and color the responsibilities on its code map. In the picture, we can definitely see that the entry point does not reflect all the behavior and the sum() method is a mishmash of responsibilities.

Implementation code map

Originally, the kata consisted of 9 steps. I added the 10th step, which consists of questions that may help reflect on the final code. Here, I want to share an overview of my answers.

Reflections

There is no specific idea behind this decomposition. It keeps all the behavior inside a class without any dependent collaborators. The add() method is the entry point that keeps all the high-level policies. The presence of state (for delimiters and numbers) affects the way how the code is structured (we put too many things in the sum() method because we should justify the existence of state, so we try to use as few parameters as possible).

I do not like this implementation. I don't see any pros, but only cons (comments in the code). Briefly, the implementation is easy to understand at first glance, but this simplicity is deceptive. In the entry point we can see only two responsibilities. The other two responsibility (the validation and filtering) are buried inside the code. What makes it even worse is that it is very hard to reason about the state at different points of execution.

It seems to follow some general programming principles. It separated concerns at the beginning, but eventually it mixes them up. It does not comply with SOLID principles, not only because there are no collaborators. Even the SRP is violated. Whether a new requirement comes into play or changes are required, the production code will be touched and rewritten in different places.

I wouldn't even try to improve it. But if I had to, I would think about making the state read only (sort of immutable, when the state can be set only once). This simple trick drastically increases code's predictability.

Solutions in the series:

Comment this page: