Legacy Software Systems: How to Live with Aging Software Architecture?
stratoflow.com
stratoflow.com
It's doubly bad when your website is designed for software embedded in kiosks and the like.
Of course there’s no real dictionary we can go to for this, but I’d define RDD as “chasing technology trends without business or engineering justification”.
Why are we switching to JS-Framework-De-Jour? Why are we using this graphdocumentjsondistibutedimmutablelog database all of a sudden? How does this improve the business? How do see a path to a positive ROI from this decision?
I'm not sure your false dichotomy holds. The definition of resume driven development is not whether there's a business case of not for a change, and the definition of legacy system is not the cost of upgrading it.
> Why are we switching to JS-Framework-De-Jour? Why are we using this graphdocumentjsondistibutedimmutablelog database all of a sudden? How does this improve the business? How do see a path to a positive ROI from this decision?
False dichotomies. You're assuming that not maintaining your software is free from cost or business impact, and you're assuming that switching to the latest and greatest does not bring any operational advantage.
But,
1. That may or may not mean a full rewrite of the app. Even in terrible old legacy apps, there usually is at least somewhat of a separation between the backend and frontend logic.
2. While not exactly uncommon, the scenario you describe is a subset of legacy apps. A lot of them work just fine, other than the fact that they're not in the latest version of the latest cool framework.
(i'm only half joking after seeing an error message like: you have rustc version 1.58.0, you need at least 1.58.1)
And I do work on project exactly like that. I am paid more then would be market rate for same position and everyone is scared we (as in seniors) are going to leave. It has advantages, not just in pay, definitely. But some of these advantages are disadvantages for the company to be frank ... like that the whole environment gets biased toward more passive and sort of sleepy. (If you are non sleepy you get pay raise, they are trying to reward it, but the force of the system is strong.)
It does not result in the best spend for customer or a company.
Companies go off the rails and get trashed talked when they clamp down and go for zero fun, 100% financially justifiable task lists.
As a tech ages out you can’t find anyone good to work on it. And when you make them, morale craters.
And sometimes you get landed a fun legacy one where you have to rebuild some binary by de-compiling first (thanks for not stripping the binary previous long-gone dev) and then spend days re-factoring it to work with updated AT commands on the new hardware. And nobody's rushing you, cause you're like the only one doing it; and finding another person to even WANT to do this is $HARDWORK.
I'm still out here doing VB6/VBA, Perl as well.
Amongst a group of people I talked about this with, we estimated that places that allowed resume farming saw between 6 and 9 months longer average employe retention times. For a place aiming at 3-4 year turnover that’s a substantial fraction of your goal.
Yeah never take such a job, this is the manager trying to screw you.
Security is a big word, from stability to observe-ability to hack-ability, there is no way to secure a system without touching it.
The saying 'penny-wise but pound-foolish' applies in many cases.
The software industry is stuck in a rolling thunder: We engineer things to last for 5 years, precisely because programmers expect to have to prepare their resume for the 5-year-newer-tech.
Only Linux and Postgres beat this doom.
Apparently the trend in SW development is to compile one moving target with another moving target.
Chad Fowler had an interesting slide in one of his talks (circa 2009 I think) where he had a graph of something like frequency of errors produced by working code versus number of changes to that code. Code could end up in one of four quadrants:
- frequent changes, lots of errors: suggesting that the domain was still being discovered or there were quality issues
- frequent changes, few errors: suggesting the domain was changing or growing but quality was good
- few changes, lots of errors: suggesting that the code was not adequately maintained or even understood, perhaps poor quality as well
- few changes, few errors: this is the “legacy” code that works hard and costs less to keep running
Clearly it’s a good thing to have that “legacy” code, by this definition, but I remember that he listed some downsides as well, but not the downsides that the junior dev who wants to rewrite then whole system comes up with.
Edit: I think it might have been "Measuring & Analyzing Things That Matter When You Have Too Many Things To Keep Track Of"
At 36:00, he talks about a ruby gem called for Rails "Turbulence" that measures code complexity against number of modifications https://vimeo.com/38252887#t=2160s
He also references this article by Michael Feathers: "Getting Empirical about Refactoring" https://www.stickyminds.com/article/getting-empirical-about-...
This hasn't been a problem in the places I've worked. Perhaps I'm lucky or it's the fact that I don't live in a very hierarchical society (Sweden).
I've worked both places. Unsurprisingly, I don't stay too long at places where I find myself working with a team full of shortcutters.
You have to start with the smallest and most conservative to the most "refactory" ones:
- figure out what enters and what exits from the program, and create a test suite that reflects every known combination
- move parts of main() to funcions
- figure out what variables can be converted from mutations to returned values
- move thr ifs(){} to maps, early returns and such
- figure out the database schemas from newly written data
- infer model relationships fro further writes
- attempt to implement some pattern design, even if its just dummy variables
Sometimes you even have to do it at the last stretch of time of your workday, and slowly the mess will become clearer, your test suit more exhaustive and comprehensive.
And at some point it will achieve feature parity with the legacy service
In part to maintain sanity in a toxic environment, and in part because I knew they just accepted it if it was handed to them.
https://yosefk.com/blog/people-can-read-their-managers-mind....
Either you’re successful AND your managers have an epiphany that you were right and they were wrong, or you fail and your managers will punish you for ignoring their instructions. It’s a risky strategy for an employee.
In the same way, there is legacy software and legacy software. In a decade of contracting I have seen both pieces of crap with 50%+ of dead code which are inmodifiable beyond adding/removing fields from some CRUD entity, and 15+ year old J2EE competently designed, maintained and documented systems, where the only difference to a fancy new project is that there is xdoclet instead of annotations and a ton of plumbing code around.
The big difference is in telling them apart in advance - with cars you know that some brands are more maintainable than others as you see them on the road and as all of them share the same components/weak spots it doesn't take long to figure out if it is an oldtimer or a piece of junk. With software it is much more complicated.
Documenting and archiving your build tools is also important. I knew a team that checked everything into source control, even Visual Studio. This ensures the tools were all preserved, everyone is using the same versions, and the code is synchronized with the tool versions.
Development for UNIX started in 1969. It was done in a documented way, using well defined APIs (that later became standard) by world class engineers.
The original code (in C) is still readable. Running it on modern hardware would be a challenge, since computer architectures changed quite a bit, and modern CPU architectures were simply not invented yet! But it's not legacy code; the interfaces, ideas and libraries from 1969 have been improved on and are the foundation of the modern computing landscape.
Yet spaghetti code from two years ago, written by "best value" programmers in a language that's 100% still supported is very much legacy code. Unintelligible comments, no tests, copy-pasted code, inline queries, the list goes on. Often simpler to just re-write.
Those that built the system inevitably leave over time, and now you’re stuck unable to attract talent because “old tech stack”, and without staff that could build something new.
Don’t stay at a company that’s gotten into that state. If your young, try and gain a mix of experience so you can actually gain those design skills.
Of course, this is not the case. The problems arise when the software updates are not budgeted. Especially the finance sector is notorious for underinvesting in R&D and instead of spending money on stock buybacks - stockholders appreciate.
However this cycle is broken when the world actually changes. If there is no proper maintenance, usually in the form of software R&D, the legacy software change cost has gone prohibitive high and the parent company is unable to do anything. This change is often Schumpeter's creative destruction. There is a new technology. A new startup raises as a competitor, using more efficient software where they can do changes, and execute their core business, with much lower cost, outpacing the established competitors.
Some industrial, like early mentioned finance, are however very-well protected due to barries of entry like the cost of initial capital and regulation. Thus, you are going to see more legacy software in industries where there is never need for a change.
I think a problem for software as an industry in it's infancy is that we've built a lot of stuff, and it's really easy to build new stuff, but it's hard to just keep the trains running on time. No one wants to pay for that. So you take the team that delivered the system and move them on. Or you stop them hiring and they age out of the product. The ghost plane fly's on for a long time untill you start to see mountains and need to change course. Then it's panic stations.
Java cracks out a new release every 6? months now. There's a lot of java 8 out there. And it's not going to get upgraded without costly effort.
btw, I have no solutions. I just think we're still at the early stage of this problem. And in truth in the built world. people rip down good buildings to rebuild shiny new ones all the time.
I haven't been programming for long enough to see it or maybe it changes too slowly to notice, but I feel like the new programming languages of the last 15 years have been similar enough (at a high level) while the programming languages of 50 or 60 years ago are vastly different. If that's the case, maybe some of today's software has a better chance of lasting longer.
There's a Java LTS version for people that don't want to upgrade every 6 months. Almost all Java 8 code will run on Java 17 LTS so as a developer I don't see that 'costly effort' you're talking about. It's just build, fix and test as usual.
https://news.ycombinator.com/item?id=28571931
And two presentations from the author, Marianne Bellotti
"We Killed These Things With Fire | Øredev 2019" https://www.youtube.com/watch?v=XoEfV0kXXDY
"Future Proofing Systems with Marianne Bellotti" (2020) https://www.youtube.com/watch?v=_ICzo5r-7vY
I like this analogy.
#2 Don’t rewrite what you don’t have to
#3 Maintain good documentation, gather the necessary knowledge
If not, all you've done is just replaced a bad system with another bad system. I've also seen that lately. You're right that often it's just "different" and not better, and that makes it hard to sell the case when a rewrite is truly needed.
This is often a career limiting decision. Rewrites are often much more difficult, particularly when you are dealing with a system that is not fully understood. This often leads to what should be a quick re-write taking > 3x more time and money than projected. In the end no one will remember why the technical reason for the rewrite, but they will remember who made the decision.
I've made this mistake a few times in my career, and I always thought, this project, it is the exception to the no-rewrites rule.
We were quite convinced the team needed to rewrite but then things like cost, time, priorities stepped in. We needed other areas addressed. So, the code stayer because it worked, enough, unfortunately.