The forgotten lifecycles of software

By Joshua Angnoe
April 2019

Formalized methodologies for developing software have been around since 1960. Lots has changed since then and the field of software development methodologies has grown ever since. Their formulas seem simple: Follow the process, deliver software that meets user expectations in a timely manner and godspeed (example, example). Being active in the field of web development since 2006 I’ve noticed a pattern: (Web)software usually doesn’t last forever, and not all companies survive the difficult times when there software starts falling apart. After delivery you're entering uncharted waters without a map to guide you. In this article I want to address the phases software might go through. Phases that, in my experience as a web developer, receive nearly any attention. I'll describe these common phases first, afterwards I'll give some tips.

Forgotten phase 1: Business as usual

The first forgotten phase of software is business as usual. Bugs are fixed, feature requests are implemented, business model tweaks are incorporated. Every addition and change is executed within expected and reasonable velocity. All is good. People change roles, some leave, new people enter the scene. At some point velocity starts to drop. It gradually becomes more difficult for developers to change the system. Bugs, regressions and uncontrolled repercussions may occur. Maybe developers start to enjoy working on the software less. Some may leave to find better pastures.

Forgotten phase 2: Decline

Phase 2 starts when all parties involved understand that the situation is becoming unworkable and something needs to be done to stop the decline. Resources can be allocated to take immediate actions, maybe an investigation into structural deficits is launched. Maybe enough work can be done to restore to the business as usual phase. Maybe not all problems are fixed and the cycle continues from business as usual to eventual decline. One thing is certain though: if decline cannot be stopped and/or faith can not be restored, at some point someone may start to think: if only we started anew. A clean slate. The world would be better. It’s not an uncommon thought.

Forgotten phase 3: Can we rewrite it?

Phase 3 starts when we declare that the software is broken beyond repair and new software should be built to take its place. The feasibility of building new software should be investigated. It’s entirely possible that it is impossible for the business to come up with the costs to do a complete rebuild. Maybe alternatives may be conjured up. Maybe you can renovate, you’ll go back to phase 2. Everyone understands that the current software must remain intact until alternatives are ready to take over. It may take a considerable while, and what will you do with feature requests and enhancements, you probably can’t close shop for existing and new customers. Are people still motivated to work with the unworkable software… A real dilemma. But this is surely something you may encounter when software goes through these ‘natural’ phases. If new software can be built, actually what happens is a new software will start its lifecycle, maybe using one of the formalized methodologies, including these forgotten ones. This time round you’ll either accept that software has a finite life, or you set yourself up for running into these dilemma’s in a few years all over again.

New software is being built. Old software is kept alive. At the next milestone we’ll enter phase 4

Forgotten phase 4: Painful migrations

New software is in the works. Maybe you’ve chosen for a waterfall method, writing the new software in its entirety and performing a massive migration at once. Maybe you’ve opted for a more sensible gradual migration, which allows for more control and less frustration on part of your loyal users. Maybe both systems (new and old) can coexist and the new system may gradually take over functions. The old software plays a part in this as well; years ago, when we followed some formalized methodology, no one ever considered it necessary, practical or relevant to think of ways we can possibly migrate away from the (current) software. Maybe we’ve built the current software in such a way that it will not allow you to dual run. Then a waterfall is probably the only possible option, which is a very risky endeavour. I do hope you get through this to reach phase 5.

Forgotten phase 5: Glorious decommission

It was a painful migration. But now all users have been migrated to the new software. The old software just sits there on a server, doing nothing. Now there is that silence after the storm which raged heavily. It’s a moment to reflect on the years of loyal service this codebase ended up doing. It helped grow the business. It grew beyond, it collapsed. It caused a lot of trouble. But the fight is over now. Be happy that you’ve reached this phase, because time has told that not few companies can ever reach this phase.

Some tips to keep out of trouble:

  1. Even software that was properly designed probably wasn’t designed for everything you’re doing with it now. No one can look into the future.

  2. Accept that software and codebases may have a limited lifespan of a few years. Regularly changing the software decreases the longevity of the codebase.

  3. It should always be possible to replace / decommission (parts of) the software. Without this capability we are definitely going to get stuck in phase 3 and 4, never being able to get rid of the burden we've built. Not a great place to be.

  4. When replacing old software with newer software that's less replaceable, you are not improving, you’ve not learned anything, you are setting yourself up for repeating cycles. Not an intelligent thing to do.

  5. Code is basically a means to an end. We write code because we want to produce effects. The things we try to achieve is what matters. When we consider software, its growth, its potential demise, it’s not the code that needs to be preserved, it’s the effects we are trying to preserve and the code that implements these effects is something we deem to be in need of replacement. Let's continually capture and preserve data about what effects our software should produce, instead of cementing it in such a perishable medium as code. If we capture this information we can take this and compile new code that implements these effects any time current software becomes unworkable. This is one of the ways we can remain free, and unstuck ourselves.

  6. Stop building entangled monolithic code where everything depends on everything. It will be impossible to replace anything. Also, stop looking at microservices as a solution to your problems. Fighting complexity with more complexity never results in less complexity. The building blocks of the experience (the effects you try to produce) should be organized in a more isolated fashion, so you can swap implementations out at any time. Remember. It’s not the code we intend to preserve, it’s the effects we try to preserve.

For a more in-depth discussion see the notes.

Final words

I’ve seen a lot of companies get into the troubles i’ve described here. I think it’s not uncommon for this to happen. Business won’t have the expertise to turn this around, they might propose using some hot acronyms and hope it helps. Developers will seek solutions in newer and better tech. I haven’t come across people who have tried to get to root causes and learn from these types of failures. Often the software that fails wasn’t yours anyway, the previous developers messed it up, and you can obviously do a much better job. I believe the solution isn’t in technique but rather in principles, and maybe accepting that software (concrete implementation in code) just is perishable.

Contribute

Is this a problem that has already been solved? Know any further reading I can add? Please let me know, here's how to get in touch. or comment on this Hackernews thread