Featured resource
Forrester Wave Report 2025
Pluralsight named a Leader in the Forrester Wave™

Our tech skill development platform earned the highest scores possible across 11 criteria.

Learn more
  • Labs icon Lab
  • Core Tech
Labs

Guided: Designing Refactoring Strategies with TDD

Correctness is only the first measure of software quality. If you are to achieve software greatness, you must strive after other quality measures like testability, performance, and other enterprise-specific aspects which support the mission. In this lab, you’ll look at refactoring to improve those measures while using a TDD firewall for correctness. You’ll implement one of Martin Fowler’s classic Refactors, Conditional Dispatcher to Command, perhaps the most common refactoring that developers work with when improving their code.

Labs

Path Info

Level
Clock icon Beginner
Duration
Clock icon 39m
Published
Clock icon May 12, 2025

Contact sales

By filling out this form and clicking submit, you acknowledge our privacy policy.

Table of Contents

  1. Challenge

    Introduction

    In this Guided Code Lab, you'll use pytest and Python to refactor a spacecraft control system from one design to another.

    It's important that you remain close to a working model at all times with your code, and using a test harness as a correctness firewall will help ensure this. The project begins with a working and passing test harness that can ensure the correctness of the current design of the system.

    By making gradual changes and ensuring correctness with TDD, you'll safely transition to the design of the control system from a conditional dispatcher design to using the classic Command pattern. Examine the code in the src/control_system.py file. The structure inside execute_command is called a conditional dispatcher. Conditional dispatchers work, but they are considered brittle and hard to update.

    Next, look at the code in the src/main.py file. You'll see that this is a simple script to call two branches of the dispatcher, NAVIGATE and COMMUNICATE.

  2. Challenge

    Validate the Current Design Using TDD

    Open the tests/test_control_system.py file. This file contains the test suite that validates the spacecraft control system. Briefly examine each function — each one exercises a different branch of the conditional dispatcher in control_system.py and asserts that its output is correct.

    Although your refactoring will change the system’s design, it should not alter its output. This will allow you to use the test harness as a way to verify the correctness of your changes. The pytest tests command will execute all of the test files in the tests folder, though there’s only one for now. Still, it saves some keystrokes.

  3. Challenge

    Refactor a Single Path to a Command

    The first step in refactoring the conditional dispatcher to use the command pattern is to create an abstract command class, along with the code that concrete implementations will override. Next, you will create the first concrete command, NavigateCommand. This command will replace the logic in the NAVIGATE branch in the dispatcher. WIth your NavigateCommand class ready for action, the next step is to make the SpacecraftControl class use it. In the next task, you'll modify the code to import the module and check its command registry for the command before falling back to the conditional dispatcher. With the execute_command modified, your NavigateCommand class should be in place.

    In the Terminal, execute the unit tests and validate that your work is correct with the following command:

    pytest tests
    
  4. Challenge

    Refactor the Remaining Paths to Commands

    Having refactored a single path to a Command, two other paths remain. In this step, you'll refactor those other two commands and eliminate the conditional dispatcher altogether. In the Terminal, validate that CommunicateCommand changes with the following command:

    pytest tests
    

    The unit tests are passing, ensuring that your system is still behaving correctly as you refactor the conditional dispatcher away. WIth the final path refactored, execute the main script with this command:

    python3 src/main.py
    

    That should execute two of the paths correctly. To validate them all, execute the unit tests with the following command:

    pytest tests
    ``` Excellent! Your refactoring is complete, and the conditional dispatcher is entirely gone. Here are some advantages of the new design:
    
    1. Commands can be tested independently of each other.
    2. Adding a new command is easier - simply add an import and add the new command to the `self.commands` collection.
    3. Each path's code is now independent, more readable, and can be executed independently of the script in the `main.py` file.

Chris B. Behrens is a writer, speaker and software developer, specializing in DevOps. He has been a developer and architect for more than twenty years focusing on small to medium size companies and the development changes they face.

What's a lab?

Hands-on Labs are real environments created by industry experts to help you learn. These environments help you gain knowledge and experience, practice without compromising your system, test without risk, destroy without fear, and let you learn from your mistakes. Hands-on Labs: practice your skills before delivering in the real world.

Provided environment for hands-on practice

We will provide the credentials and environment necessary for you to practice right within your browser.

Guided walkthrough

Follow along with the author’s guided walkthrough and build something new in your provided environment!

Did you know?

On average, you retain 75% more of your learning if you get time for practice.