Search
Close this search box.
Search
Close this search box.
Search
Close this search box.

Legacy Code: Extract-FirstUT-Cover-Refactor-TDD

Facebook
Twitter
LinkedIn
Pinterest
WhatsApp

Recently, I had the opportunity to work on legacy code with several teams from various organizations. I would like to share my experience.

We usually start by choosing a piece of code that is “painful”: changing frequently and “scary” to touch because of its complexity. We explain that our purpose is to make the code simpler, readable, and easy to change. Establishing the motivation for what we do is important!

In essence, the steps we take are:

  1.       Use extract method/rename to make the code more readable (specifically applicable for very long methods).
  2.       Write and execute the first unit test (that’s usually the toughest part) as described by Michael Feathers.
  3.       Add more unit tests until the area you want to refactor is satisfactorily covered.
  4.       Refactor to make the code more maintainable (working in very small steps, as described by Joshua Kerievsky).
  5.       Make the required change using TDD.

The purpose of (1) is to see the forest, not the trees. Long methods tend to be unreadable. Using the “extract method” helps you see clearly what’s going on. Once you gain vision, you can start to rename. Arlo Belshee talks about this.

As an example, look at these two statements:

At the first, if statement, we have extracted the condition to a method. Remember that what you do most of the time with code is read it. You need to make it readable.

Item (2), as mentioned above, is the difficult part. You need both to master the technique and have the resolution to do it. I usually do it with the entire team and so, together, we have the required courage.

For instance, take a look at this behemoth method.

Pure fun, eh? This is something I call an amusement park method. We usually start by trying to call it null. Sometimes it actually works and we have a first-unit test. Then we start to slowly fill in the parameters. Maybe instead of a null send an empty dictionary. Maybe instead of an empty dictionary send a dictionary with two entries. And if there’s no choice sometimes we run the actual application and serialize the parameters, to be deserialized in the unit test later.

Sometimes we change a method from private to public, sometimes we add a method to better control a member, and there are more vicious things we do. Sometimes it can take a whole morning to do this. However, once you understand this, it becomes very simple.

Then you start looking at coverage.

Once you have the first test, things start to move faster (3). You start adding more and more tests. You start looking at coverage reports to see which lines of code are covered and which aren’t. If something is not covered, you can add another unit test to cover it.

Now (4) we can start to make bigger changes. Once you have the unit tests in place you feel free. You make a small change, you run the test. Another small step and the tests run again. Some IDEs have plug-ins that run the tests every time something is changed.

This is the time to get better familiar with the automatic refactoring tools of your IDE. Make sure you are familiar with introducing parameters, fields, and variables. Extract class is a very nice one and so is the ability to convert a method to static and move a method. The trick here is to make as fewer manual changes as possible and move the code around fluently.

Many times by this point, there is a small disappointment. The code you feared in the morning now looks quite simple. The real challenge is making the code simple and solving the puzzle.

Now we reached the point when we can quite easily add some code to fulfill a new requirement (5). We can add a new test, see it fail, make the required change, see it pass, and maybe do a little refactoring. Nothing like the joy of seeing unit tests turn from red to green.

(the above are unit tests from a very nice exercise called Gilded Rose)

And that’s it.

Subscribe for Email Updates:

Categories:

Tags:

Agile India
Scrum and XP
Spotify
Nexus Integration Team
Manage Budget Creation
Kanban Game
Continuous Deployment
Agility
speed at scale
Built-In Quality
Scrum Master Role
QA
Certified SAFe
Systems Thinking
Keith Sawyer
Agile Release Management
Video
Perfection Game
Continuous Integration
EOS®
Agile Mindset
Agile Assembly Architecture
Agile Project Management
Lean Agile
Scrum Values
Product Ownership
Effective Agile Retrospectives
Lean and Agile Principles and Practices
Certification
Risk-aware Product Development
SA
User stories
ART Success
Tips
NIT
Daily Scrum
Professional Scrum Product Owner
Story Slicing
The Kanban Method
SAFe Release Planning
Agile Exercises
A Kanban System for Software Engineering
Applying Agile Methodology
Agile Marketing
Planning
Continuous Improvement
Lean Startup
chatgpt
What Is Kanban
ScrumMaster Tales
Agile Product Ownership
Scrum
GanttBan
Releases Using Lean
Process Improvement
Games and Exercises
Value Streams
Atlaassian
Coaching Agile Teams
Agile for Embedded Systems
Agile Community
SAFe
Scaled Agile Framework
Risk Management on Agile Projects
Limiting Work in Progress
AI Artificial Intelligence
Artificial Intelligence
Agile Israel
Accelerate Value Delivery At Scale
Continuous Delivery
Hybrid Work
LeSS
Professional Scrum with Kanban
Agile Risk Management
The Agile Coach
Agile Project
Pomodoro Technique
Advanced Roadmaps
Entrepreneurial Operating System®
Risk Management in Kanban
TDD
Agile
Large Scale Scrum
Operational Value Stream
Portfolio for Jira
Iterative Incremental Development
Lean and Agile Techniques
PI Objectives
Agile Israel Events
Reading List
Agile and DevOps Journey
Lean-Agile Budgeting
Jira admin
Webinar
Agile Delivery
AI
Nexus and Kanban
Agile Games and Exercises
An Appreciative Retrospective
Implementation of Lean and Agile
DevOps
lean agile change management
Frameworks
Release Train Engineer
Jira Plans
Agile in the Enterprise
Professional Scrum Master
Agile Release Planning
Business Agility
speed @ scale
Kanban
Slides
Covid19
BDD
Kaizen
Presentation
Nexus vs SAFe
Sprint Retrospectives
ROI
Lean Software Development
Agile Product Development
Software Development
Nexus
PI Planning
Development Value Streams
Product Management
Amdocs
Software Development Estimation
Elastic Leadership
Enterprise DevOps
RTE Role
Principles of Lean-Agile Leadership
Atlassian
Lean Agile Leadership
Test Driven Development
Kanban 101
RSA
Code
Agile Program
Managing Projects
Agile Contracts Best Practices
IT Operations
LPM
Sprint Planning
Scrum With Kanban
ARTs
Achieve Business Agility
LAB
POPM
Tools
Scrum Guide
agileisrael
ATDD vs. BDD
Change Management
Quality Assurance
Nexus and SAFe
Lean Agile Management
Lean Risk Management
Team Flow
Program Increment
SPC
predictability
Legacy Code
Jira
Agile Games
System Team
Managing Risk on Agile Projects
Sprint Iteration
WIP
Introduction to Test Driven Development
Scrum.org
Agile Testing Practices
Kaizen Workshop
Lean Agile Organization
Agile Techniques
Scrum Primer
SAFe DevOps
Scrum Master
AgileSparks
Continuous Planning
Rapid RTC
Kanban Basics
Engineering Practices
Lean Budgeting
ATDD
Introduction to ATDD
RTE
ALM Tools
Agile Basics
Legacy Enterprise
System Integration Environments
Agile Outsourcing
Lean-Agile Software Development
Lean Agile Basics
Jira Cloud
Acceptance Test-Driven Development
Self-organization
Kanban Kickstart Example
Agile Development
System Archetypes
AgileSparks
Logo
Enable registration in settings - general

Contact Us

Request for additional information and prices

AgileSparks Newsletter

Subscribe to our newsletter, and stay updated on the latest Agile news and events

This website uses Cookies to provide a better experience
Shopping cart