How can you learn and practice test-driven development (TDD), or refactoring, or working with legacy code? I can explain the principles. But the question that comes back is, “But what do I actually do?”
That’s what code katas are for. They’re not tutorials. They’re exercises, designed to help you grow in your technical agility. I’ll introduce you to some that are specifically for Swift programmers. Then try doing one today!
What’s a Code Kata?
How do professional athletes stay on top of their game? They practice. How about professional musicians? Practice, practice, practice.
“Kata” is a Japanese martial arts term for choreographed patterns of movement. They’re also called “forms.” Both beginners and masters practice these detailed patterns over and over. The movements eventually come without thought, because your body knows what to do.
A “code kata” applies this idea to coding. It’s a self-contained exercise you can repeat. Every time you repeat it, you’ll learn something new. At first, you’ll work to learn one approach to solving a problem. As you repeat the same approach, your learning will shift toward muscle memory.
Swift code katas: At first, you’ll work to learn one approach to solving a problem. As you repeat the same approach, your learning will shift toward muscle memory.
Then you can tackle the same problem but with different approaches. A common style during the annual Global Day of Coderetreat is to repeat a problem while adding different coding constraints. For example, how much coding can you do using only keyboard shortcuts? Or can you write code without using conditionals? …A physical analogy would be running with extra weights, or fighting with one hand.
Doing self-contained exercises like this is the best way to practice coding. They’re outside of your production code, so there’s no worry of breaking anything. You’ll throw away what you try because you’re going to repeat the coding kata later. The goal is to gain mastery over coding tools and techniques.
So let’s look at some exercises for Swift programmers. But first, here are a few pro tips.
Code Kata Pro Tips
Use a Scratchpad
Before you start: Make sure you have a piece of paper and something to write with. An index card or sticky note is all the space you need.
Why? Because TDD is a discipline of doing one thing at a time. When you notice something to clear up, don’t dive straight into it. Write it down for later, and stay focused on whatever you’re working on now.
When you complete a task, revisit your list. Clear up the code, and cross the entries off your list.
In the Bowling Game example, this scratchpad is actually shown in the slides. In the upper-left corners, you’ll see boxes like this:
When you see this, write it down on your scratchpad. I mean it: write it down. This will help reinforce good TDD habits.
When you’re working on a new code kata, I’d recommend going through the entire exercise, once through.
Then we can follow Marlena Compton’s advice in Learning TDD with Exercises, by doing 15 minutes a day. Set a timer. Stop when you get to 15 minutes. The next day, continue from where you stopped. Try making it a small part of your daily routine.
In the spirit of using different constraints, work through a TDD kata or legacy code kata without them. Then do it again, using my templates. See if they change the experience.
Refactoring Swift Katas
Before diving into test-driven development, experience what it’s like to work in code that has tests. Learn how to do some refactoring.
These exercises focus on sections of code that have unit tests. The goal is to move in small steps.
Refactor in Small Steps: Move Field
Experience the Move Field refactoring by following the steps described in the accompanying post When You Refactor, Are You Using Small Steps? The first step is to move strings from the view controller into the view model—so that the view model can use them.
Refactor in Small Steps, Continued: Move Logic
This is the a continuation of the example above. Having done the Move Field refactoring to put the strings into the view model, the next step is to move the conditional logic. Follow the steps in the accompanying post Refactoring: How Do You Clear Up a Mess, Safely?
Many of One
This is a Swift version of an exercise by Llewellyn Falco. He identifies an important step to use when you want to go from one thing to many. The in-between step most people miss is to use “many of one.” Start using an aggregate type such as an array—but have the array contain only that one item, at first.
Refactor a View Controller (Book Example)
Most of part 3 of my book iOS Unit Testing by Example is about refactoring a single view controller. The view controller is messy, but there are accompanying tests. Once the code is ready, follow the steps described in the book:
- Do some initial clean-up, turning messy MVC (model view controller) code into bright MVC code.
- Refactor to MVVM (model view view-model).
- Refactor to MVP (model view presenter).
Refactor a View Controller (Video Example)
Take this fully-tested iOS view controller written in MVC. Play around with refactoring it in different ways, such as:
- Refactor to MVVM.
- Refactor to Null Object pattern.
- Refactor to MVP.
TDD Swift Katas
Here are Swift code katas about TDD. The focus is on test-driven evolutionary design.
The idea is to score a game of bowling. Follow along with slides, coding each step:
In my version of the Bowling Game slides, green lines show code that we just added. Red lines show code that we’re about to remove. For example, here we added the last line, and are about two remove the two lines above it:
Let me call out some specific slides…
Slide 12: Set up Xcode to show test code and production code side-by-side, mimicking the slide. Do this as follows:
- Swift: Click the test file so it shows on the left. Option-click the implementation file so it shows on the right.
- Objective-C: Click the test file so it shows on the left. Option-click the .h file so it shows on the right. Shift-option-click the .m file and double-click the “+” in the bottom right. On the right side, you should have .h above and .m below.
You may prefer to use tabs instead, and that’s fine. The goal is to see the code side-by-side, or switch between them so fast that it doesn’t matter.
Slide 23: Select the two circled lines, then use the context menu to Refactor → Extract. (If Xcode refuses, do it by hand. Or, try AppCode which has better automated refactoring.)
Slide 40: You have various options to rename loop variable “i” using Xcode:
- Do it by hand.
- Use “Refactor → Rename” observing how long it takes to index and animate.
- Select its first appearance and do Edit All in Scope. This is available through the menus, or in a pop-up menu that appears when you hover over a selection, as shown here:
Try each option to see how they affect your “flow.” And one more option is to try AppCode.
The challenge is to input a name in standard English order, returning the name normalized for use in a bibliography.
This is a “TDD paint by numbers” exercise: the tests are written for you. Initially, they’re all disabled. Enable them one-by-one, and follow the remaining two steps of the TDD Waltz:
- Write enough production code to pass the test.
- Refactor the code so it expresses the domain. (In this exercise, leave the test code alone.)
You can see one possible final solution in the “all-solutions” branch (though not the steps to get there). I also offer 75-minute mob programming sessions of this exercise on PubMob.
I walk through this kata in the last chapter of my book, iOS Unit Testing by Example.
Make code to greet someone by name, according to the time of day:
- 5:00 am – 11:59 am: Good morning.
- 12:00 pm – 4:59 pm: Good afternoon.
- 5:00 pm – 4:59 am: Good evening.
So if we provide the name “Lauren” and the time is 4:15 p.m., it should return, “Good afternoon, Lauren.” Allow for the possibility that there is no name.
Collection of TDD Katas
Brandt Daniels has assembled a collection of katas for practicing TDD in Swift. Besides the Bowling Game, these include:
- Game of Life
- Password Verifier (within the Refactoring folder)
- String Calculator
- Interactions (follow up to String Calculator)
You can see possible solutions in the “developers/brandtdaniels” branch.
Legacy Code Swift Katas
In the real world, we often face legacy code: that is, code written without tests. Since testability wasn’t a concern, adding tests afterwards is challenging. We usually need to make careful changes to make it testable.
In the following code katas, you will face a glob of untested code. Your challenge:
- Bring the code fully under test without changing its behavior.
- Refactor the tests to better express the behavior.
- Then lean on those tests to improve the design of the code.
Baby Steps Timer
This app helps you take “baby steps” while doing TDD. The idea is that you should be in Red (that is, have failing tests) for no longer than 2 minutes.
This is a real, functioning app. There's a view controller with buttons. There's a timer that plays sounds and changes the color. Since this is full of iOS specifics, it’s more challenging than the other legacy code katas. So I’d try one of the others first.
Real life is messy and hard to model. There are items for sale at the Gilded Rose inn, and the requirements are varied.
Once you have the code tested and cleared up, add a new feature: “Conjured” items should degrade in Quality twice as fast as normal items.
Imagine a social networking website for travelers:
- You need to be logged in to see content
- You need to be a friend to see someone else’s trips
Some of the code makes calls to things we shouldn’t actually invoke during unit testing. These are stubbed out to throw exceptions. Can you use only automated refactoring tools to make it possible to replace these parts during testing? Hint: subclass and override.
Are there other Swift code katas that you like? Please let me know so I can add them to the list.