"Your work won’t be off-shored .. "
This is simply not true. A large fraction of the code outsourced to India consists of ancient code-wrecks in "musty languages",( to quote the author, nice turn of phrase by the way!) no one in the West wants to touch any more, while green field development with the latest cool tech stays in the US.
I've known of COBOL, RPG, PowerBuilder etc code bases maintained (well) for years in India. Infosys and co make large chunks of money this way. And anyway outsourcing (relatively) low value/cost work makes some sense. I am not saying it is a good or bad thing. Just the way it is.
I am by nature an optimist, but this does not match my experience, particularly with regards to improvements that the client cannot easily perceive. (Some days I wish apps had an XP bar so I could award a few points for e.g. "Won't die if the school gets about two dozen Chinese students who prefer English to Japanese - actual bug, by the way.)
I went through a lot of pain before I realized I needed to toot my own horn more. After that, suddenly they were very grateful that I was fixing bugs in their application. (To be fair, they were very grateful at first, too, when the bugs were really obvious and costing them money daily.)
There's no harm in letting them know exactly how much you've improved their system. They really will appreciate it.
Over that time, my attitude has changed greatly. In the early days, all code looked like crap to me. I thought I could do so much better, and in some cases I could. But when I finally got to building my own systems, I ran into lots of compromises and loose ends - sometimes unavoidably. And under the pressure of deadlines, I can't say that I always documented clearly from whence came my spaghetti.
I've gained a certain respect for a system that _works_, no matter how ugly. Only time can shake most of the bugs out, and once they're gone, you try not to put any back in. Sometimes you have no choice but to rewrite; but the tendency to napalm everything must be resisted.
Disclaimer: nobody knows what testing means in this industry.
However, the giant downside to maintenance programming is the sheer amount of frustration possible when trying to fix it, even when the programmer you want to kill is your former self.
I think if you say to yourself "this system makes money", no matter how bad it is, maybe you can see the silver lining.
The sad truth is that if the system makes money then very likely for someone else...
The experience I gained helped my career incredibly. But then something changed - I kept being transfered from one battlefield to another (thats what happens when you're the best for solving crappy situations). That might be fine and dandy, if your solutions stick. But in my situation juniors were doing greenfield work (since they weren't capable of doing maintaining after themselves - which is kinda ironic) and I got to clean up the mess that I could of easily prevented by getting to apply the experience and knowledge I got solving mess day after day. This kind of situation wears you out pretty fast and so I quit.
So if I got asked how to become really good at doing software. Look for work nobody wants to do and say "Bring it on!". Learn to love the crappy work, then toot your horn and demand fair compensation. But be weary of burn out and thus be prepared to bail out when you start hating what you do. This strategy has many good aspects to it: Customers appreciation levels are way higher - since at greenfield level work everybody expects latest and greatest of impeccable quality in contrast when maintaining - any improvement is considered minor miracle. Plus if you get any good at this kind of work, even if you act out a diva now and then, no one will hold it against you :)
The only thing I ever learned from maintenance programming was what not to do.
Over the years, I have maintained the work of hundreds, maybe even thousands of programmers on everything from clearly rushed fixes to large scale commercial software packages. And almost everything I ever encountered sucked. I bet I've seen the work of less the a dozen really good programmers.
Maybe it's selction bias...perhaps the work of the best programmers needs less maintenance, so it's much less likely that I'll ever get to see it. But thanks to the bell curve and the infancy of our industry, 99% of all programmers I've ever followed have significant shortcomings in the work...
I hate not instantly knowing what a variable stands for.
I hate 4 different variables for the same thing.
I hate program variables that don't match the file variable.
I hate the same line of code twice.
I hate 100 lines of code when 5 lines would have sufficed if the programmer only had a clue.
I hate steady violations of pre-agreed upon standards (whatever they are).
I hate spaghetti code. Especially where touching one little thing breaks everything because no previous programmer anticipated any of the 42 likely things that would happen in the life of this program.
I know that the rewrite debate comes up often, but once I reach a certain subjective tolerance threshold, a rewrite is a certainty. I like to think that:
a. This horrible shit will be banished forever.
b. This will finally work the way I think was originally intended.
c. This will finally look like it should have in the first place.
d. I'll be the last one who ever suffered maintaining this module.
Don't believe me? Just hit "View Source" on any random web page to reveal the mountain of shit that's about to fall out upon you.
Joy? I'd rather chew razor blades.
I've also learned that what I think is the right way to solve a problem isn't the only way. Most often I am rewriting bits of crap code, but I also learn new techniques and approaches.
I love green fields programmers who know the best way to do everything. Their projects frequently flame out, leaving a desperate client and an almost-working code base that fell short of someone's idea of perfection, but is fairly close to working after some practical compromises are made.
The best thing about maintenance programming is working on real code with real users. I don't miss spending three-fourths of the project schedule arguing data structures with three other programmers and a nervous client.
Sometimes you'd love to refactor a bit of 10 year old C code to be more readable, or less bug-prone. But you can't because it's not a bug.
In some cases it's even worse and you can't even fix bugs that you find. Only bugs reported by customers count as bugs. Of course, a customer will eventually stumble on it, but heh.
I don't mind maintaining code as long as it's focused on structural improvement, not on manouvring through the code very carefully hoping the whole thing won't collapse.
The challenge in decelopment coding is "how can we make this happen?" - both coding skill and creativity involved. The challenge in maintenance coding is "how can we get this to work without breaking everything else" - lot less creativity, lot more patching of a leaky boat.
A good reliable bugfix can require a lot of creativity, sometimes more than for writing new code.
Turns out it is kind of fun to do, particularly if the programmer who went before you was kind of bad, because then there is this puzzle solving aspect to it, of figuring out:
(a) what it is that the code actually does
(b) what it is that the bad programmer intended it to do
(c) how to reconcile (a) with (b)
On the other hand, doing maintenance work professionally is terrible, because most clients put you in this catch-22 situation:
(1) the code is running in prod (with various kludges and workarounds to get around the broken bits)
(2) because of #1 they don't actually want you to make any changes because they might break the system
(3) any fix involves change
(4) hence you cannot fix anything without the client freaking out, even though you are specifically hired to fix things
Maintenance work in that kind of scenario sucks big time.
Disclaimer: I can actually design code properly, so unlike the author my green-fields projects don't turn into unmitigated disasters.
The most depressing thing I've ever seen in maintenance was a project that got sent into prod with 300+ known defects, they hired other people to fix the defects, when the defect count got below ~50 they bought back the same guy who had screwed up phase 1 so badly to do phase 2 for them.
Most of the best practices I've picked up were working on existing established code bases at Match.com and TI. I work mostly with startups where you have a lot of freedom but the experience I picked up at those big companies has really stuck with me and my code is probably 10x more maintainable because of it.
For example, I had to unlearn to use clever algorithms and optimized data structures. Stupidly simple code is more maintainable, because the sad but true reality is that for a dozen different reasons the next guy who will be working on it doesn't have their head in the game.
Another thing I found hard to accept was that you don't touch code that is fully functional, not even if it's horribly ugly, not even to fix that one little line of awkwardness. Ugly code that works is always better than clean code with a bug.
What gets me is that the original developers get the praise and recognition that comes with releasing something, and are then moved onto new projects. They never have to deal with fixing the bugs they've created, so they have little idea what a pain in the ass it is to maintain their code and do the same shit on the next project (which we'll have to maintain soon enough).
When I do a good job of fixing bugs it makes it look like their shitty code works, but when I fail to fix a critical one in a timely it reflects badly on my abilities (even though it's primarily due to a poorly written and poorly documented code in the first place) and makes my team and the company look bad.
Anyway, I suppose I've not really contributed much to the discussion but maybe this rant will take the sting out of going into work tomorrow.
I have worked plenty of late nights and weekends on "cool" projects that never shipped. A project gets canceled. A startup runs out of money. No user would enjoy the fruit of my labor. My code gathers dust in some archived copy of the source repository.