Even though it seems that managing software is overly complicated, in some aspects it is similar to managing buildings. Let’s explore an analogy.
Say you are the manager of a new multi-story building in your city. It is brand new, so naturally, everything is in tip-top shape.
Some time into the future, the first issues started to pop up, though the business was still going well. People still paid their rents, so you carried on. You saw an opportunity to expand, so you did. You built more floors on top of the old ones because in this analogy it’s possible. What’s more, you kept adding more and more floors, while the older parts started to crumble.
As you disregarded the state of the first building, the plumbing started leaking, so you just taped everything together and called it a day. The wiring was dangerous, though there is not a thing that a proper amount of duct tape won’t solve, right? Rinse, and repeat.
Fast-forward again, and the property you manage started to be more tape than anything else. At this point, the property started to be dangerous to live in, though the scope of repairs overwhelmed you. Turns out that saving time and money on regular repairs is not that economic after all.
Again, though, people still lived there, as the core purpose was satisfied; there was a roof over their heads, so that’s fine, isn’t it? Assuming this would continue far into the future, you would one day be faced with a choice: do I bulldoze everything down to the ground, and start again, or do I start the painstaking process of renovations? As you started to deliberate, the property started to be a ticking bomb; it looked as if it was about to collapse.
The situation with code can be similar. As “[t]he only constant is change”, we have two choices when maintaining software. You might:
Of course, speaking long-term, it is much more preferable to continuously modify the existing foundations to not accumulate issues over time - and perhaps, more importantly, to save money. The codebase needs to be modified eventually, and the later that starts, the worse for you. Starting from now, we will use the verb “to refactor” instead of “to modify”. Refactoring is the improvement of the internal state of your product, without changing what it does.
In terms of steps or stages of developing software, what happens during the process of refactoring does not differ too much from what happens during writing a system for the first time. Of course, besides that detail, it’s fire and water. Refactoring is carrying out internal repairs without changes in external functionality versus tearing everything down, and building everything once again.
The stages of software development are decided by a framework that architects and managers have been following for about 60 years now (starting from around the 1960s).
This framework is the Systems Development Lifecycle (SDLC) that describes the process of developing IT systems. Importantly, the framework will not become irrelevant at any point in the future, as all steps will have to be eventually repeated.
The whole process generally looks just as the image above describes it, though naturally, there are exceptions. One has to base the process on a case by case analysis. For example, it might be the case that managers would like to modify the framework to better suit them.
If you’re already familiar with the SDLC, you may skip to the next section.
This is where the team will gather info about the system and plan how the entire operation is supposed to go. When solving a specific problem, the wider context is also important; the wider set of goals of the organization are relevant when approaching the challenge.
We may then start defining the goals of our operation, and plan how exactly we will achieve them. Additionally, it is good to engage real users (or potential users) to be able to refine the problem definition and how we can fix it.
This stage is all about mapping the agreed upon solution. First the team produces a general plan, and then moves to detailed planning.
During the design phase, all necessary and relevant design documents reach the hands of the client. The documents we receive describe the system in such detail that software developers and engineers should have no issues developing the product.
This is the “juicy” part. Only during the third phase does the actual coding happen. We want to avoid being the Headless Horseman.
In this stage, we showcase that what we have created indeed conforms to the requirements and goals we had set up beforehand.
We are almost good to go. Now the tricky part, however. We need to deploy our creation, step by step, simultaneously checking if everything works as it's supposed to. If all the steps before are performed carefully, and correctly, it should be a breeze. Of course, life is life, and in rare cases, things don’t work as they’re supposed to.
The last step. We need to define tasks that have to be performed for us to keep having a healthy codebase.
Of course, the maintenance step often is the longest one. This phase lasts for as long as we don’t decide to add new features or functionalities or change existing ones. Should we want to add/change anything, we repeat the whole cycle again.
Here, we make sure that we have a healthy foundation for the current, and future features.
A rewrite of an improperly managed software not only has the difficulty bar raised high in itself;you might also not have proper documentation, nor even anybody to talk to about the changes that were implemented in the past.
Your morale, or the morale of the entire team, can drop. While the team is hard at work, business advantages are often seen only months, or even years, down the line. It is not as if we are upgrading an old Fiat to a new Mercedes-Benz instantly.
Even though that is the case, perhaps disappointingly so, an eventual refactoring is a necessity. Code needs to be updated and maintained, just like a machine. Should one team fail to oil the machine for years, another team will have to perform the necessary repairs after the machine starts breaking down more and more frequently, and as it turns into a ticking bomb.
The rescue party cannot be a group of “random” developers, either. They have to be the best of the best, with a rare fascination with the older bits and parts of programming languages and development platforms. Of course, the code they are authoring uses all the newest tricks and frameworks, though that’s only part of their work. After all, they are primarily diving head-first into a bowl of old spaghetti code on fire.
The managers who are tasked with organizing everybody’s work have to be on top of everything at all times. For one, changes that would be correct according to the art of programming are not always good to make. After all, the client is waiting for us to deliver something that is going to add value to their solution — not making the codebase “cosmetically” correct.
Once the refactor is ready, it is the moment of truth. Upon deployment, no problems should occur, however, naturally, some do. Every so often there are missing files, there can be issues with setting the correct environment variables (for configuration purposes); there can be issues with versioning, such as overwriting a file when it was not meant to be done, and vice versa, and so on.
Another difficulty is sometimes one has to deploy to production with the hands of a developer from abroad - for example in cases where access restrictions are present due to sensitive or confidential data. Not entirely an issue, though at times this can be a challenge. Misunderstandings between the team abroad, and the engineer at the company occur. Occasionally, they can compromise the whole operation.
Magdalena Lewandowska, whom we talked to, to get insights about the process, was a part of a massive refactoring project this year. As the year is about to finish, she, and her team, can be proud: they managed to finish it with a complete success.