Tuesday 21 June 2011

A change in attitude - Legacy code

Attitude is a little thing that makes a big difference.  ~Winston Churchill 
Not long ago, I gave a talk about Software Craftsmanship where I asked who liked to work on greenfield projects. Almost everyone raised their hands. Then I asked who liked to work with legacy code. Besides one or two friends that were there, almost everyone kept their hands down.
It is always nice to start a project from scratch, be able to choose the technology, use the latest frameworks and have a lot of fun writing code without worrying about breaking existing features or having to understand existing code. Working on greenfield is great, mainly with an experienced and disciplined team using TDD since day one. Progress flows naturally and quickly.
But as soon as we are working with code written by people that are long gone, no tests, no documentation, we go mental. We notice we are going mental by the number of WTF we say during the day. We may get moody and start hating to work on a specific system or in parts of it. Frustration becomes a constant.

A change in attitude

If you don't like something change it; if you can't change it, change the way you think about it.  ~Mary Engelbreit
Although I wrote "we" and "us", that was really how I used to feel when working with legacy code. However, in the past few years, I learned many things. An obvious one is that moaning, complaining and cursing won't make my life easier or better. If I want things to be better I need to do something about it.
Today, when I look at legacy code, instead of moaning and getting frustrated, my attitude is to try to understand it and make it better, constantly applying the Boy Scout Rule.
As my friend David Green said in a twitter conversation, what I agree 100%, improving and understanding legacy code can be massively rewarding. The process of trying to make sense of a big ball of mud seems daunting but if we just focus in small parts of it, one at a time, and start improving them (writing tests, extracting methods and classes, renaming variables, etc), bit by bit, things become much easier and enjoyable. 

Working with legacy code is almost like solving a big jigsaw puzzle. We don't do that all at once. We start by separating the pieces into groups, often starting with the edges and corners and then separating other small pieces by colour, pattern, etc. We now have a few (logical) groups and we start to form a higher level model in our head. What before was a bunch of random pieces (or a big ball of mud), now is a bunch of smaller groups of random pieces. Still not very helpful or encouraging, but nonetheless some progress. Bit by bit, we start working on one of these groups (parts of the code) and we start putting some pieces together (writing tests for the existing code, which will help with our understanding of the code, and refactoring it).

Once we start putting some pieces together, we start seeing a small part of our jigsaw puzzle picture. We get excited because now it's getting real. It's starting to make sense and we are happy we are making progress. The more pieces we put together the more excited we are about finishing the jigsaw puzzle. The more pieces we put together, the easier it gets to put more pieces together. And that's exactly the feeling I've got when working with legacy code now. For every piece of code I make better, more I want to make the whole code better. The feeling of achievement is really rewarding. What before was something I could barely read and took ages to understand, now reads like a story and every developer can understand it with no effort at all. Maybe when a good part of the code is stable (covered by tests, loosely coupled, well defined responsibilities, etc), I could even introduce the cool and new frameworks that I always wanted to use. I could upgrade some library versions. I could even throw a lot of code away and replace it with a framework because now my code is clean and modularised and replacing one part of the system will not break another. I don't even need to envy my friends working on greenfield projects any more. 

Different challenges 

Another cool thing about legacy code is that it forces you to think in a different way. In greenfield projects, when developing a new feature, we write a test and start implementing stuff. In legacy, sometimes you can't even instantiate a class in order to test it due to all its dependencies. A change in one place can cause an impact in obscure parts of the system. We have an option here. We can see these challenges as a pain in the ass or can be see them as very interesting problems to solve. I prefer the latter.

The professional side 

Although it is OK to have fun and enjoy what we are doing, we always need to remember that we are professionals and being paid to write software. Software is an asset and a lot of money and time is invested on it. As every investment, clients want to maximise the return of their investment. The more we improve and keep the software clean, the longer the client will be able to benefit from it. Stretching the lifespan of a software also maximises the client's return of investment.


At the end of the day, it does not matter if you are working on a green or brownfield project. It's your attitude towards your job that will make it more or less enjoyable.


J.J said...

Not so long ago I worked on the migration of a web application from the old Jetspeed 1.0 to Spring 3.0.X.

None of the original authors of the webapp worked for the company any more (plus I never got to meet any of them so I couldn't contact them to ask questions if I needed to) so all that I had was a very big and old piece of software that nobody knew how it worked.

I couldn't believe how complex and ugly was the code that I was reading when I started working on it. So you can imagine that the first weeks working on this project felt like a living hell to me.

After a month, I started making real progress and changed my way of approaching the task: I went from "bloody hell this is BAD" to "I think that I'm gonna make it through this :)"

I needed 5 months to complete the task. It seems like a lot of time, and it was, but when I was done I simply felt that I was a better software engineer than before.

Great article!

ehsavoie said...

I am working on such a project and while you might hear me yell sometimes when I step upon a piece or particularly BAD code I think that working on a legacy project (and trying to bring it to the new shinning world) is a very enriching experience. Something every developer should have to face in the beginning of their developer life so that afterwards they will try to leave the code a little cleaner before each commit.
I did a presentation (in French) about theses last three years on such a project (and this is not the end of it) : J2EE m'a tuer (which could be translated roughly as J2EE killed me)

Bruce said...

I am a person who actually LIKES to work on legacy code - and at my age, legacy goes back to Mainframe COBOL! The problem is, companies won't admit to hiring people for legacy code - they ONLY (and I do mean ONLY) want the person to have the absolutely latest and greatest; and, if you're talking mainframe legacy, it has to be the EXACT machine they have, they EXACT software release level, etc.

dB. said...

If you watch a lot of bad theater, you'll start appreciating it.

While you're fighting someone else's mess they are creating more new mess. The latter is created a lot fast than you can untangle it. Maybe now that you've seen the bad stuff it's time to start writing some new good code?

Sandro Mancuso said...

@dB.: In general that is definitely the case. We cannot clean the code as fast as we would like to and more and more bad code is added.

This needs to be a collective effort, where the whole team is committed to it.

For me, the way forward is to disseminate the software craftsmanship principles, practices and attitude to all the developers. Having mentors (not team leaders or ivory tower architects) are also a great way to motivate and teach less experienced developers. They should be very senior developers that spend 100% of their time pair-programming with other members of the team, sharing their passion and skills and constantly rotating.

Unit testing existing code and refactoring should be part of every developer's daily activities. All new code is written in a TDD fashion.

IMO, that's a good strategy moving forward and one I'm pursuing myself. I believe that bit by bit we will get there. :-)

Anonymous said...

I enjoy working on legacy code too. It's a great way to learn new tricks.

There's a mindset among literally every developer and sysadmin I've worked with that the legacy stuff they're exposed to is crap and needs to be redone. None of them can comprehend that they too have plenty of legacy crap out there that somebody else is cursing as well. What it comes down to is that legacy code isn't necessarily bad, it's just legacy. Just because you didn't do it doesn't make it bad.

Post a Comment