Or taking ownership of software, developing it, then handing it back.
Quite recently Rowe IT was asked to further develop a web-based Java/Spring application that was originally developed as a prototype by another company. This set me thinking – the commercial and open source models of software development means that the ownership of code is changing.
It is less common now for there to be closed source code projects where an individual or group of individuals own the code and works on it for eternity. It is more common for project teams to change, adapt, for people to move around and projects themselves to change ownership and move around. So, the question then is:
Given that this is happening, how should we handle it?
My first thought was this is a bit like the old school game of “tag” or “it”. The code is passed onto you, you work on it and pass it onto someone else. A good analogy? The more I thought about it the less I liked it. Thinking it through: Software tag – given the code, didn’t want it, try to pass it on as quickly as possible by any means to somebody else who doesn’t want it, generally to slower or weaker people, chaotic.
If not “tag” then what? The being handed something for a period and then passing it on is more akin to a relay race. This analogy seems to fit better:
Software relay – being handed somebody else’s code in a controlled manner, know how long you have the code to develop and add value to the code before passing on to somebody else who is ready, willing and able to accept it in a controlled manner, orderly.
It is typical, generally the norm, in software development to pick up and develop other people’s code. This may be an internal project, you may join an existing team, or it may be that like us your company is engaged to further develop or maintain a project developed by another company.
It is important to remember that code you are inheriting is written by professionals – just like you. When picking up a project or starting on a project you won’t necessarily know the full history of why it is like it is, why decisions were made and under what conditions those decisions were made.
It is very unlikely that you like all of what you see. It is only natural to say, “I wouldn’t have done it like that”, “What were they thinking”, or tapping a colleague on the shoulder and saying, “Have you seen this?” or often simply WTF. As an exercise, look at some code you wrote 5 years ago – a proper, critical look. Your reaction will probably be the same.
So, one way of approaching this is to think that you have two customers: the explicit customer who is providing the requirements and paying your wages and an implicit customer – the person or team that will pick up the project/code to develop or maintain. These people are going to be professional software developers, like you.
Bear in mind that that the project will be handed over to somebody else in the future. The question is then –
What are you handing over? Would you be happy to accept it? Will the next team have the same reaction as you did?
Stage 1: Being handed the baton
Hopefully this is a managed handover – ideally with a crossover for developers. In some cases, though it will simply be picking up a code base that was left by the previous team.
- Establish a baseline – create a stake in the ground so you know exactly what you have been given and can always go back to is and refer to it. This might simply be a tag in a version control system, it might require something more complex like creating a reference system.
- May need to do some formal acceptance of what you have been handed over.
- Is it just code? What about documentation, existing tickets, plans, procedures, development guidelines, testing procedures, document describing decisions that have been made, road maps? All depends upon the scale of the project and where it is in its development life-cycle.
- Test what you have inherited.
- Review and critique (bear in mind all points made earlier) – any technical debt, FIXMEs, TODOs, suspicious comments in the code.
- Start off simple – add code quality tools if not already in place to get a measure of what you are starting with. Record the number of messages, warnings and so on. (Java CheckStyle, FindBugs and other static analysis tools). There may be code coverage figures available.
- Review outstanding tickets and issues if you have access to them.
- Turn compiler and IDE warnings up to 11 to flush out issues.
- Look for bad code smells – in Java things like Thread.sleep().
- How up to date is the code and its dependencies? Are there any outstanding CVEs relating to dependencies? Not just the build time dependencies but also the tools being used to build the code – so maven plugin versions, node and npm versions.
- Is the code build repeatable? Can you build what you have been given? Do you have access to all the dependencies? Do you access to the same versions of the dependencies? Is it built against released version of dependencies? No SNAPSHOTS or use the latest version in node.
- What is the road map of the dependencies being used? Is a new version just about to drop?
- What is the lifespan of the dependencies and frameworks? For example, what is the lifespan of a user interface framework? 3 years? 5 years?
- Match code formatting so don’t introduce unnecessary diffs when checking in/out code. Hopefully the code formatting rules are documented or even better a suitable configuration file made available that can be used in the IDE.
Stage 2: Running with it
Develop using your normal development practices. But remember, eventually you are going to hand over the code so it should be in a better state than when you picked it up. It should certainly be no worse.
Start off small, make minor changes. Understand the functionality. Build up the test cases.
Record why changes have been and the rationale behind decisions that have been made. It is important to document reasons for why code is as it is. You don’t necessarily have to describe what or how something works – developers can look at the code and see that. What is useful is to document and describe why it is like it is – things that are not clear just from the code. A decision log is one way to do this. This can be quite informal – regard it as a diary or a one-way conversation with your future self. It may be somebody else who reads it, it maybe you.
Comments in code – don’t state what the code is doing – you can see that from the code: a loop is a loop, an if/then/else is an if/then/else. If you have to explain code at this level, then think about changing the code so it needs no description. Comments can describe chunks of code and the reasoning behind it. Again, treat comments as a conversation with the future you or another dev.
TODOs and FIXMEs? Should they be left in when handing over the code? Ideally not, realistically then yes. Unless there are tickets raised in the issue system for the project then these are effectively hidden issues in the code and can almost be regarded as technical debt. It will probable need to be paid back at some time, either by yourself or whoever inherits the project. You won’t be thanked if it is hidden.
Stage 3: Handing over the baton
This is easy – it is simply stage 1 from the other perspective. Everything still applies.
Remember whoever is picking up the baton is likely to go through the same process you did when you first picked it up.
The code should be neat and tidy with no loose ends, any technical debt clearly identified and documented.
The code base should be better than it was when it was first picked up – those metrics should have moved in the right direction – fewer warnings, better code coverage etc.
No hidden surprises.
Move onto you next project and pick up the baton again.
By Paul Illingworth