Greetings
A functional kata to rule them all
The concept of pure function is of great interest to Test Driven Development as it forces us to think about a behavior that must evolve while the only things we can know about it -from the point of view of the test- are its current inputs and outputs. This is common to every classic TDD development, since it relies on black box tests. That is, we don’t take into account how the implementation of our unit under development works, we just interact with it through its public interface.
This is why I propose it as the final exercise of this series, because it helps train everything that we’ve learned in the previous ones, adding an extra restriction to force us not to use the resources that we’d have if we were using and object-oriented approach, such as keeping a state or extracting behavior to dependencies.
Moreover, given that the requirements change in each iteration, it forces us to refactor constantly to be able to introduce the necessary behavioral changes.
History
This kata isn’t very well known. I’ve found it in TestDouble, where Nick Gauthier is mentioned as the author.
Problem statement
The formulation of this kata is very simple. We have to create a pure function greet() that returns a string with a greeting. As a parameter, it must accept the name of the person that we want to greet.
Next, we’ll add requirements that will force us to extend the algorithm to support them, just through the function’s input and output. Each requisite will have be accompanied by an example. They are the following:
| Requirements | input | output |
|---|---|---|
| 1. Interpolate name in a simple greeting | “Bob” | Hello, Bob. |
| 2. If no name is passed, return some generic formula | null | Hello, my friend. |
| 3. If we’re yelled at, yell back | “JERRY” | HELLO, JERRY! |
| 4. Handle two names | “Jill”, “Jane” | Hello, Jill and Jane. |
| 5. Handle any number of names, using Oxford commas | “Amy”, “Brian”, “Charlotte” | Hello, Amy, Brian, and Charlotte. |
| 6. Allow mixing regular and yelled names, but separate the answers | “Amy”, “BRIAN”, “Charlotte” | Hello, Amy and Charlotte. AND HELLO BRIAN! |
| 7. If a name contains a comma, split it | “Bob”, “Charlie, Dianne” | Hello, Bob, Charlie, and Dianne. |
| 8. Allow escaping the commas of #7 | “Bob”, “\“Charlie, Dianne\”” | Hello, Bob and Charlie, Dianne. |
Hints to solve it
Part of the interest of this kata lies in working on one requirement at a time, so it’s important to not get ahead of ourselves and go one by one.
The difficulty: solving it without creating any extra units, only through the greet() interface. Each of the requirements lets us build a test that forces us to extend the behavior, although we can create as many tests as we see fit.
On the other hand, that “step back” that we talked about in the Bowling kata becomes very important. When we solve a requirement, making the corresponding test pass, we’ll find out that we need to pave the way for the implementation of the next one, while keeping all current tests green.
Summarizing:
- Focus on a requirement each time, in the proposed order.
- Once achieved, refactor to make the next requisite easier: make it so that the change is easy (this might be hard), and then make the easy change, as Kent Beck would say.