8

Possible Duplicate:
When do you rebuild an application or keep on fixing the existing one

I am currently working on a project that has been in development for the last few years used throughout the organization but the way the project has been coded the maintainability of it is completely shot.

Reading the code presents with pages and pages of Anti-Patterns and trying to identify the path of a business workflow takes on occasion days. At this point I would probably classify the software in its current state as "Working by accident" rather then as intended. So I am looking for some wisdom as to the following:

At what point would you consider simply dumping the project into an abandonware pile and starting from scratch?

P.S. I understand that in a lot of cases organization would consider it cheaper to maintain the existing project.

Karlson
  • 815
  • 1
  • 7
  • 14
  • 3
    You probably won't get any buy-in from higher-up unless you can show them that it really *is* cheaper to rebuild instead of maintain. If it's a relatively small app with many small and frequent changes that just add to the existing problems, this may be easy to show. – FrustratedWithFormsDesigner Jan 20 '12 at 15:23
  • It's a fairly large revenue generating app where a lot of small and large amounts of changes needs to be made frequently. I can probably put some costs behind the cons of maintaining the product but I would need to ask the developers to classify their time by some list which is what I am looking for. – Karlson Jan 20 '12 at 15:29
  • 3
    Why does it always seem like the most rushed and horribly implemented software is always the software that generates the highest revenue? :( – maple_shaft Jan 20 '12 at 15:39
  • 1
    @maple_shaft 'cuz it always is. :) – Karlson Jan 20 '12 at 17:13
  • @maple_shaft If code is important, the customer wants it now. The devs can take their time only if it isn't really that important. – DJClayworth Jan 20 '12 at 20:38

5 Answers5

5

You almost certainly should not rewrite, it is very unlikely to make business sense. Joel Spolsky puts it much better than me though: http://www.joelonsoftware.com/articles/fog0000000069.html

Dealing with this code is a reality of software engineering that you may have to learn to accept, but don't dismay, you aren't the first and there are tools and methods for dealing with this problem, I highly recommend Working Effectively with Legacy Code:

http://www.amazon.com/Working-Effectively-Legacy-Michael-Feathers/dp/0131177052

Eoin Carroll
  • 652
  • 5
  • 12
  • If functions that have been coded were 2 pages or even 5 pages long I wouldn't even bother. There are some that are a few thousands lines of code. – Karlson Jan 20 '12 at 15:38
  • 4
    And if Joel Spolsky was always right, we would still be using descendants of Windows 3.11/95/98/ME today... – nikie Jan 20 '12 at 15:50
  • 1
    @Karlson Call me when you have to fix a bug in a 1k LOC method that contains 20 levels of nested conditional and loop blocks, only to be interupted every single day to go to a meeting where the micro managing VP is literally shouting at you for an hour over how long it is taking you to fix a client-found issue. It may not be a good idea to refactor, but Joel doesn't say anything about burning the office down. :) – maple_shaft Jan 20 '12 at 15:55
  • @maple_shaft What's your phone number ... :) Joel refers rewriting software based on the fact that you had code creep because of various bug fixes and feature adds on a software that had some thought put into design that you can decouple functionality and data in one object from another, which is only used to provide some enumerated values defined in it... – Karlson Jan 20 '12 at 16:03
  • "My Code Has No Structure" is one of the chapters in the book I mentioned. It's not necessarily easy, but these techniques are usually better than starting from scratch with all the cost that involves (including recreating old bugs and exciting new bugs!). The very first thing I wanted to do when I started working in a software company was rewrite the awful awful system they had there. That is a natural instinct but you should learn that it is naive. – Eoin Carroll Jan 20 '12 at 16:10
  • @EoinCarroll I'll take a look at that book but after being in support for number of years my first instincts are: 1. Don't touch the ... cuz it stinketh. 2. What can I do to make my life easier? – Karlson Jan 20 '12 at 17:15
  • @Karlson There are always refactoring tools to help make that bit a little easier, but in general for an easier life, try another field of work. For business value, learn how to work with horrible code, all the while slowly turning it into not-as-bad-as-it-was code. – Eoin Carroll Jan 20 '12 at 17:24
  • @EoinCarroll I know how to work with horrible code. That wasn't the point. – Karlson Jan 20 '12 at 17:29
2

At what point would you consider simply dumping the project into an abandonware pile and starting from scratch?

When the actual cost of maintenance exceeds the value to the organization.

That is, it's cheaper to do things manually than it is to continue using (and maintaining) the software.

This is actually an easy test to apply. How many users? How much time do they spend using the app? What's the alternative? How much time do you waste on it? If you've only got a few dozen users, you can list the hours-per-day usage to determine the actual cost.

Value is sometimes harder to discern, but it should do something of value, and someone should be able to say that the software saves (or makes) some amount of money each year.

It's best -- of course -- do make the decision before the software actually becomes a liability instead of an asset.

S.Lott
  • 45,264
  • 6
  • 90
  • 154
1

You're going to have to figure out what the code does anyway. I doubt there is any clear and up to date specs anywhere. Just fix it.

Unless it is written in a language that you can't find a compiler/interpreter/run-time to run it on the availble hardware, fix it.

You may have the resources to create a new app, but the business does not.

I don't know how many change requests you have, and per change it will take longer along with some refactoring, but that will not exceed the time for devvelopment and business staff resources.

Fix what is broken. Refactor as much as you can in the mean time.

JeffO
  • 36,816
  • 2
  • 57
  • 124
  • Refactoring... I'd love to be able to do it... Except the objects in the project are so tightly integrated that refactoring certain components that actually need it takes weeks and in some cases many weeks. – Karlson Jan 20 '12 at 15:55
  • @Karlson - and weeks later it will either be weeks later with more managable code or with the same mess you have now. Two months into a rewrite will give you what? – JeffO Jan 20 '12 at 22:47
  • A framework that will allow me to hang objects for various business functionality off of. – Karlson Jan 21 '12 at 01:55
1

Keep in mind that in 10 years your code will be seen by someone as "a horribly architected mess that must be rewritten to save maintenance time." And then 10 years after that, that design will be seen as a mess. This is just the natural behavior of programmers.

Developers very frequently think everyone else's design and code is crap. An unlike an industry where you bend steel and have even bigger things that do the bending, one person can go muck up the entire product and "redesign it," so we have this phenomenon in software engineering.

All that said, a successful business won't rewrite code that works, remember that 10 year old code might be a nightmare, but it also has 10 years of testing and bug fixes which won't be had on any new design. The absolute worst is when a rewrite is committed to and never matches the functionality of the original (so people say "we used to be able to do that"). Sad but it happens. If it is contract software it's a nearly impossible sell ("I'm going to pay you 300k for... the exact same thing I have now? Do you think I'm stupid?").

Do not rewrite. The inclination to rewrite everything from scratch is a frequent tendency in inexperienced developers. Resist the urge, there is almost always no business sense in it.

anon
  • 1,474
  • 8
  • 8
0

Well I can imagine hypothetical scenarios where I might just throw out the existing code base (hypothetical situations where the bucky balls have zero weight and volume, where no one cares if we lose weeks or months of productivity as we scramble to add overlooked features and bug fixes into the system, and where the system is so trivial and hated by an organization that I can replace the entire thing and army of servers with notepad++ and a netbook in ten minutes and boost everyone’s productivity and moral across the board.)

For almost any real world scenario though I would just recommend refactoring in place. ^_^. There tend to be too many hidden, unanticipated costs to rewrites when undocumented legal and business requirements start to pop-up and the last minute hacking things together last minute starts to ensue.

==Refactoring in Place for greater good, and stuff==

Refactoring legacy code with the regular old incremental approach,

  1. If you have the chance convert to UML and document what little knarly architecture there is.
  2. If you are on version control look into generating some code churn reports and figuring out which files and file sections have been changed the most frequently. Make a note of these as they will likely be the areas you will want to deal with first.
  3. Before you change any code always try to add some test coverage (even ugly full stack functional tests will do). If dealing with large messy procedurial code extract logic you intend on changing into some reasonably named method or function and if possible add some test cases that verify your new method. make whatever god awful hack you have to and if possible paramatize the change if it is something commonly tweaked like margin width or title so it will be a little more straight forward to update the next time.
  4. Use the adapter pattern and work away at hiding the knarly bits of legacy code under a rug of logically named classes and methods so that for most common tasks you and the other developers perform you wont need to worry about the scary bits that are going on behind your back behind those nice little clean methods and classes you've hidden that legacy code behind -- like those nice families that keep deformed murderous zombie former family members in barns so that they don't spoil the day to day going-on’s of the farm . . . normally.
  5. As you continue to whittle away and clean up the sections of the code continue to boost your test coverage. Now you can dig down even deeper and "rewrite" even more code when needed/desired with ever increasing confidence.
  6. Repeat, or apply additional refactoring approaches to continue to improve your codebase.

Branching By Abstraction

  1. Define the trouble spot in the code you want to remove (the persistence layer, the pdf generator, the invoice tally mechanism, the widget generator, etc.).
  2. run (write if necessary) some functional test cases (automated or manual but you know automated) against the code base that targets this functionality along with general behavior.
  3. Extract logic related to that component from the existing sourcebase into a class with some reasonable interface.
  4. Verify all code is now using the new interface to perform activity X which was previously dispersed randomly throughout the code(Grep the code base, add a trace to the new class and verify pages that should be calling it are, etc.), and that you can control which implementation will be used by modifying a single file.(object registry, factory class, whatever IActivityXClass = Settings.AcitivtyXImplementer();)
  5. rerun functional test cases that verify everything is still functioning with all of Activity X throwin into your new class.
  6. Write unit tests where possible around the new activity X wrapper class.
  7. implement a new class with less insane spaghetti logic than the legacy implementation that adheres to the same interface as the legacy class.
  8. verify that the new class passes the unit tests you wrote for the legacy class.
  9. update your code by changing the registry/factorymethod/whatever to use the new class instead of the old class.
  10. verify that your functional tests still pass.

Open Closed Principle and a Common Business Logic/Persistence Layer

To some extent you might be able to get away with separating out your presentation, business and persistence layer and writing a new app that is fully backwards compatible with the legacy solution, or at a minimum can still handle data inputted by legacy solution. I would probably not recommend this approach but sometimes it is a reasonable compromise of time/schedule/resources/required new functionality.

  • At a minimum separate the presentation layer away from the business and persistence layers.
  • implement a new ui and better presentation layer that uses the same common business and persistence layer.
  • Verify that data created with new ui does not break old ui. (you're going to be in hot water if users of the new tool interrupt users of the old tool). If you are striving for full backwards compatibility you should be saving everything to the same persistence layers. If you just want forward compatibility into the new tool then use a new database and new tables or extension tables to track data not in legacy system.
  • For new functionality and persistence layer needs add new tables and methods don't change existing legacy logic, or add columns, constraints to existing tables. e.g. if you need to start tracking employers emergency contact and some other fields don't modify the existing employee table (we have no idea what assumptions the legacy data makes about that table) add an extension table employee_ext id, employee_id, emergency_contact_id, etc_id.
  • Slowly migrate users onto new system. if possible put legacy system into read only mode, or just add some warning telling users it will no longer be available after date X.
  • implement any hi priority missed functionality or business requirements in the new ui
  • roll over users base.
  • continue on to clean-up the business logic and persistence layer users other refactoring methodologies.
Keith Brings
  • 486
  • 2
  • 5