liveBook · Manning

Refactoring

As explained in The Art of Unit Testing 3e

Refactoring is changing the internal structure of code without changing its externally observable functionality.

Refactoring changes code without changing its functionality. Renaming a method or splitting one large method into smaller calls counts when behavior stays the same. The payoff is code that is easier to read, maintain, debug, and change. section 1.10.1

Refactoring is not feature work: add functionality by changing production code until a test passes, then improve the code’s structure without losing the behavior already proved. In test-driven development, tests provide the safety net for redesigning both production code and tests. section 1.10.1

Keep refactoring safe by working in small increments:

  • Make one small structural change at a time rather than attempting a large rewrite. section 1.10.1
  • Run all relevant tests after each change to catch behavior accidentally broken by the restructuring. section 1.10.1
  • For legacy code with no unit tests, first add integration tests against the real system to establish the working behavior. section 12.3
  • After a large refactoring, replace most broad integration tests with smaller, more maintainable unit tests. section 12.4

Protecting a legacy configuration change

A C++ XML configuration manager had no tests and was difficult to isolate from dependencies. Integration tests first saved and loaded real configuration data, establishing existing behavior. A further test exposed a missing attribute; after adding it, all three tests passed, showing that the new feature had not broken the old behavior. section 12.3

Refactoring for testability can be hard when existing code lacks seams for replacing or extending components. Start with components that are easier to test when a team is gaining confidence; before broad changes, preserve important behavior with integration tests. section 12.0 section 12.4

How The Art of Unit Testing 3e covers it

How deep it goes
Defines refactoring and gives incremental, test-backed procedures, while deferring detailed techniques and gotchas to another reference.
Examples
Uses method renaming, method splitting, and an XML configuration manager protected by real-system integration tests.
What you can do after
Apply it via incremental code changes and repeated tests, including integration-test baselines when legacy code lacks unit tests.
How it connects
Connects refactoring with test-driven development, unit tests, integration tests, maintainability, code duplication, and legacy code.

Also explained in

Compare how 22 books explain refactoring →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of The Art of Unit Testing 3e. The section links point to the parts of the book it draws on.