Skip to main content

Strategies for ensuring project success and

reducing technical debt, Part 1

Legacy code. There’s no other words that scare software engineers as much as these two. In fact,

most of them probably stopped reading when they saw the word ‘legacy’. However, working with

legacy code is a large portion of what software engineers do throughout their career, and if they are

not working with legacy code then they are creating it for another engineer in the future. And,

unfortunately, many legacy applications and architectures were either not properly implemented or

maintained well as time went on. Code passes hands from the original developers to contractors to

new application developers and each day the two words every executive hates to hear becomes

more apparent— technical debt.

Just like financial debt, technical debt can begin to grow and accumulate “interest”,

draining precious resources from businesses. Often it can feel like you’re drowning in debt and

unable to modernize your system because of it. The good news is that by implementing some best

practices technical debt will be reduced over time and new projects will have a better chance of

success. Here are some strategies the engineers at ImagineX use to accomplish this goal.

 


Assessment

“If you don’t know where you’re going, any road will take you there.”

-Lewis Carroll, Alice in Wonderland

 

The first step we always take on any project of any size at ImagineX is a full technical assessment.

By getting a full picture of the current state of an enterprise ecosystem we can then develop

strategies about where the system can go in the future as well as the effort required to make it

happen. The assessment is crucial because this will eliminate additional future technical debt by

avoiding it altogether, and it will define the constraints of time and money to invest in the system.

We assess where current technical debt is, how it can be reduced, and how to mitigate it

given the budget and expectations of the client. Once assessed, we can then develop strategies to

meet a customer’s goals and expectations. Some applications can be refactored and moved into

the cloud while others may need replacing altogether and others are best left as is. Our aim is to

maximize the return on investment by getting the most benefit for the cost. With a good strategy

and plan in place it’s time to move to the next step.

 


Test

“Quality is not act. It is a habit.”

-Aristotle

Once we have made an assessment, have a strategy, then we just need to start making changes

to the code, right? WRONG. Changing legacy code is risky—-very risky. One little change in a

brittle system could bring the whole thing to a halt. This inevitably leads to someone asking, “Why

didn’t anyone test this!?!”, probably in a very angry, irritated voice. It’s always important when

dealing with legacy code to start regression testing even if and especially if it was never done in the

past.

 

A LOT of technical debt is due to untested code. This is simply due to the fact that

engineers cannot comfortably make changes knowing that they are not going to break something

else. And when changes do occur, as they always must, engineers spend a large portion of their

time debugging and fixing defects due to unforeseen effects of those changes. This can lead to the

most dreaded of development practices, Defect Driven Development.

Defect Driven Development, or DDD, is an anti-practice that goes like this: An application or

system created that does something and is then released into production for end-users to use. The

end-user discovers that the system is not behaving the way they would like or is not working

altogether. A defect is logged for the application and sent to the developer and sees it and says

“Oh, I didn’t know it was supposed to do that.” The change is then made and released to the enduser

in production who finds that the change is not exactly what they were expecting or that it

broke something else. A defect is logged….you get the point.

Avoid this painful development process by creating a full testing environment separate and

identical to the current production. This testing environment is then dedicated to Quality Assurance

(QA) team to test every part of the system before moving into the production environment.

Implement automated regression tests so any change to existing features that breaks something

else is found in QA before moving to your production environment. The biggest challenge here with

legacy code is that requirements are not always clear since it could be a piece of existing software

created years, even decades, ago.

Creating a test suite for legacy systems can be a huge undertaking, so careful planning

must take place to prioritize and create tests where appropriate. For example, if you know the

refactoring of an application will only affect certain parts of a system then the test coverage should

be limited to those areas initially. As time and budget allows, continue testing other areas of the

system. Defects will still arise because of unknown requirements and unknown effects of changes,

but, as additional testing is implemented to cover these defects, engineers can grow increasingly

confident their changes will not cause critical damage.

 

Part 2 Coming Soon – In the next post we’ll look at Continuous

Integration and Delivery, Refactor vs. Replace, and Agile Methods

Thomas McCracken

Author Thomas McCracken

More posts by Thomas McCracken