Beefy Boxes and Bandwidth Generously Provided by pair Networks
go ahead... be a heretic

Legacy Code: "Dominoes = Bad"

by sundialsvc4 (Abbot)
on Apr 26, 2011 at 22:47 UTC ( #901434=perlmeditation: print w/replies, xml ) Need Help??

In my peculiar line of work, I see a lot of legacy code.   In fact, I see a lot of bad legacy code, written (in most cases) by a “lone wolf” programmer who happened to be learning <Perl | PHP | Ruby | etc.> “by the seat of his pants, (making it up...) while going along.”   This painful experience has emphasized one thing:   “Dominoes = Bad.”

“Bad legacy code” is a chain of dominoes.   It’s a disaster waiting to happen.   The only reason why any of it works, is because the rest of it works.   Magic-value tests (e.g. $state eq 'I') are scattered willy-nilly all over the code base, with no particular rhyme or reason.   The application “works” only because (and therefore, only if) all of the planets are in perfect alignment at all times.   When any change needs to be made, anywhere in the code, the “ripple effects” can branch out ... not only across “space,” but also (quite literally) across “time.”   You might find yourself trying to wrap your head around observations like these, upon which the existing code utterly depends:

$state shifts from 'I' to 'S' only after the user does ..whatever.. after doing whatever-else..., therefore the code that I am looking at right here tests for 'S' ...

“Good code,” whether it is “legacy” or not, contains no temporal assumptions.   Or other assumptions, for that matter.   Instead, the code that you are looking at is “a statement of present fact,” with no prerequisites or co-requisites.   It stands alone.   And, if something is nonsensical about whatever it sees, it is the one to raise the alarm.

“Good code,” “bad code,” it’s all really a matter of maintainability.   Good code consists of carefully placed, well-defined and well-defended “islands” of functionality with a minimum set of interdependency upon “everything else.”   Bad code is precisely the opposite.   The only way to understand “bad code” is to understand everything at once.   Which is a lost cause.

Opinion yours?

Replies are listed 'Best First'.
Re: Legacy Code: "Dominoes = Bad"
by danb (Friar) on Apr 27, 2011 at 20:23 UTC

    Good post, sundialsvc4. I would characterize what your saying as granularity, modularity, and/or atomicity. Code is easier to understand when it is small (e.g. functions of 80 lines or less) and does not require knowledge of other parts of the system to understanding.

    That said, while such granuarlity/modularity is important, it's only one factor in the list of things that I could consider in evaluating the goodness of code. There's also style, simplicity, artistry, suitability of the algorithm, etc.

    Also, I would argue that "contains no assumptions" should be "contains no *unstated* assumptions".


Re: Legacy Code: "Dominoes = Bad"
by maio (Acolyte) on Apr 27, 2011 at 21:55 UTC

    I can feel your pain. :) For last few years we have been fighting/taming big legacy system written in Perl with a lot of chain of dominoes that you are talking about. But I have to say it's been great learning experience for me.

    At the beginning, it took us months to deliver fixes/new functionality and each release was followed by days of fixing things that we broke by that release. Than we had this 'great' idea to do complete rewrites instead. It took us one and half year and resulted in completely new legacy code. There are several articles on web why rewrites are bad idea and now I totally agree with them.

    Fortunately we finally did find way to do it better and now we are able to make big changes across whole system in just few days. A lot of things that made it possible are summarized in Michael Feather's book Working Effectively with Legacy Code.

    Because of this legacy experience I now really-really appreciate code that is as simple as possible and is fully covered by tests.

Re: Legacy Code: "Dominoes = Bad"
by raybies (Chaplain) on Apr 28, 2011 at 13:10 UTC

    Unfortunately many of the longterm safe/quality practices don't always matter to those initially in charge of a project, and so you'll find a group that develops and then goes on to do something else that's never been done before--without thought to how they might've made it last forever and ever.

    The mindset is often that there will always be something newer and better, and why maintain something when you can always rewrite what doesn't work later?

    In some ways it's a matter of "We'll cross that bridge when we come to it." Also designers often take an anything goes attitude because they tend to get paid a lot, while code maintainers (the IT grunts) get paid a lot less to keep it working. I would expect that some developers probably have nary a thought of them or their feelings, they're paid to prove concepts.

    When i worked with coders in the game industry, one of the most difficult motivational tasks for me as a project manager was getting the expert coders to do the boring coding... the stuff like tweaking the AI, fixing typos, and organizing code in a production release. All that takes a lot of discipline that was not appealing to the hot-blooded trailblazers of the coding universe.

    It isn't always so, however. I know some folks who are proud their code is still being used after a decade. Though they're often the first to claim it's not good code.

    finally there's an aspect of budgeting for maintainability that's hard for a lot of folks to swallow. It's the idea that if it's an expense in the future, that it's an expense at all. If I'm a manager and have a forty million dollar budget, thirty of which is for maintaining the project over the lifetime of the project, what are the chances I won't be tempted to spend that now? Or that my upper management won't cut that eventually anyway, because it's a huge expense that's just hanging out there unspent... future expenses are liabilities that make accountants nervous. Heck, accountants don't like it when you save up too much vacation time...

    Of course those are external factors to what really should be self evident. I do wonder what some would consider "maintainable Perl" because I've heard a lot of folks claim that Perl isn't maintainable (mostly because they don't know it... which maybe is part of the problem with Perl... you have to hire a Perl expert in order to maintain it... and that's another expense that may not be worth the effort economically speaking, when Java coders are a dime a dozen in some country where wages are even less than that...)


      I would quite frankly say that my chosen market-niche as of late consists of finding the “cast-off” code ... that (former) developers are quick to have a “Mission::Impossible™ attitude” toward ... (“the State Department will disavow all knowledge of your actions”) ... but that is very much still in service ... and staging an effective turn-around for that project.

      “Life’s been good ... to me ... so far ...”

      It would, indeed, be a wonderful thing if a software project ever actually reached the point:   GAME OVER.   “Congratulations, Mr. Phelps.   You won the game.   And the game, having now been won, will most assuredly never change.”   In my experience, “the game” is not like that ... and I, for one, am very glad indeed that it is not.   Because, if it were, I would not have a career.   Life goes on.   Business does not stop.   Everything that you accomplished last year, doesn’t mean one frippin’ thing this year.


      And as for the “cheap (sic...) Java coders” .... well ... just because your accountant proclaims that something is “cheaper,” does not actually establish that it actually is.   (And if you don’t believe me on this, just ask your accountant what he or she thinks about “a ’cheaper’ accountant.”)

        Everything that you accomplished last year, doesn’t mean one frippin’ thing this year.
        Too bad for you. A lot of what I've accomplished last year is still generating revenue for my employer this year.
        Buwahahahaha! I'm definitely using that "cheaper accountant" thing... Great thoughts, --Ray
Re: Legacy Code: "Dominoes = Bad"
by JavaFan (Canon) on Apr 26, 2011 at 23:09 UTC
    “Good code,” “bad code,” it’s all really a matter of maintainability.
    Eh, no. Good code is code that solves whatever problem needs to be solved, and does it on time.

    And the users of your code don't give a penny whether the code is maintainable.

    Maintainable code is nice, but I won't hire anyone who thinks maintainability is in the top 3 of criteria code should be measured on.

      Eh, no. Good code is code that solves whatever problem needs to be solved, and does it on time.

      That's not good, it's just working code, perhaps delivered on schedule, which are properties that pertain to good code also.

      It may be useful 'as is' and generate revenue to them as sell crap, but still continues to be bad code.

      What do you think are the relative expenditure on initial development and maintenance of your code base?

      'cos over here your maths doesn't work, anything that is going to be used by someone else should be maintainable, one-off solutions excepted. If someone else is going to use your code they need to be able to depend on it, use modules within it for undreamed of purposes and fix it when it goes bad (and it will go bad). Unless it is allowed for in the initial design and implementation you will pay far more to "retro-fit" maintainability

      print "Good ",qw(night morning afternoon evening)[(localtime)[2]/6]," fellow monks."
        use modules within it for undreamed of purposes and fix it when it goes bad (and it will go bad). Unless it is allowed for in the initial design and implementation you will pay far more to "retro-fit" maintainability

        By your own words, the things that will need changing are "undreamed of".

        So all the effort you put in at the beginning to cover off all the possibilities that you can dream of--95% of which will never be needed--is wasted effort. And you won't have thought of the undreamed of things that are needed.

        But it is almost always worse than that. All the complexity you added trying to facilitate all those things you predicted (guessed) might be needed, but never will, will make the adaptation to the one thing you didn't dream of 10 times harder.

        So, now you wasted time and money up front, and it costs you 2x, 5x, ... more to make the change once you actually know what that change is.

        Predicting the future is a mug's game. And the more obvious the future you predict seems to be, the harder you will be bitten and the more it will cost you when it doesn't come true.

        More money has been wasted, more projects scrapped before they ever saw production, and more good money thrown after bad in the software industry because of whatifitis, and its close cousin, wouldntitbeniceifitis, than all other causes combined. And that includes crude, naive and just plain badly written code.

        From experience, it is far easier to maintain, re-factor and upgrade simple, but crude code than it is to so for nicely structured but heavily nested O'Woe code written to try and cater for every possible future.

        With the former you know that what code there is serves a useful purpose, even if it gets it wrong sometimes. With the latter, your first task is to try to work out what of the morass of code is actually ever exercised by real workloads, before you can begin the process of correcting its flaws or adapting it to new requirements.

        Simple is always best. Even if you think something might be required at some point. Don't add it until is is required. Because you can bet your bottom dollar, that often it won't be required, but will get in the way of what actually is.

        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.
        Unless it is allowed for in the initial design and implementation you will pay far more to "retro-fit" maintainability
        Really? Do you have some data to back that up? Can you quantify that bold statement?

        Note that I nowhere said one should write horrible code. But paying now for possible future happenings isn't always the smartest decision. Sometimes it is, and it's hard to know when that sometimes is. I'm not claiming I will always know when it's smart to spend more time now to save time later, but I do know it's certainly not always the case.


      I suppose that, at the time, the code I’m dealing with today “solved whatever problem needed to be solved, and did it on time,” but ... now it’s ten years later, and the code in question is still in service (and in front of the faces of literally thousands of people, and f*cking-up in front of every one of them) ... and, miracle of miracles, “maintainability” is suddenly a huge issue, indeed.

      “Software has a life-span.”   Imagine that...   :-/

        Sure. But how much of the code you have written needs to be modified after 10 years? There's a lot of code that's being written that either won't survive 10 years, or, after having survived 10 years, will do another 10 years without modifications.

        It's often not wise to pay an extra cost *now* just so you *may* save some costs in the future. The time you spend now to make code more maintainable cannot be spend on writing code that generates revenue. That's 10 years of revenue you'd have to compare against the savings of having to deal with harder to maintain code 10 years from now. Now, in some businesses coding for maintainability makes sense; I'm not arguing that. But I take issue with blanket statements - just because it sometimes makes sense, doesn't mean it always make sense.

      JavaFan, I would agree with you if the cost of the making the code maintainable from the outset was more than the cost of problems caused by its unmaintainability; however, in my experience, such cases are exceedingly rare for code that is executed more than once a year and requires more than an hour to write.


      I will not work for anyone who thinks maintainability is not in the top 3 criteria code should be measured on.

      I would like to spend my time creating new and interesting things, not cleaning up my predecessor's mess where fixing one thing creates two problems elsewhere.

        I will not work for anyone who thinks maintainability is not in the top 3 criteria code should be measured on.
        Which one do you sacrifice:
        1. Does the job.
        2. Is finished when needed.
        3. Runs fast enough/doesn't consume too many resources.
        Or let me ask it this way. Do you prefer to get your salary at the end of the month, or do you want to wait for the perfectly maintainable code that processes the payroll?

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlmeditation [id://901434]
Approved by planetscape
Front-paged by Arunbear
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others about the Monastery: (4)
As of 2018-07-15 23:28 GMT
Find Nodes?
    Voting Booth?
    It has been suggested to rename Perl 6 in order to boost its marketing potential. Which name would you prefer?

    Results (328 votes). Check out past polls.