Featured resource
2025 Tech Upskilling Playbook
Tech Upskilling Playbook

Build future-ready tech teams and hit key business milestones with seven proven plays from industry leaders.

Check it out
  • Lab
    • Libraries: If you want this lab, consider one of these libraries.
    • 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.

Lab platform
Lab Info
Level
Beginner
Last updated
Jul 31, 2025
Duration
40m

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.
About the author

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.

Real skill practice before real-world application

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.

Learn by doing

Engage hands-on with the tools and technologies you’re learning. You pick the skill, we provide the credentials and environment.

Follow your guide

All labs have detailed instructions and objectives, guiding you through the learning process and ensuring you understand every step.

Turn time into mastery

On average, you retain 75% more of your learning if you take time to practice. Hands-on labs set you up for success to make those skills stick.

Get started with Pluralsight