Wikipedia’s article on software rot puts forth a familiar example. An application instance is deployed into the wild and is customized to meet the specific needs of its user-base. Over time, this fork is maintained by a series of individuals that inevitably increase its complexity. With small development teams and any standard amount of turnover, the new system will drift to the point where it’s too architecturally distinct to merge back into the base code. This is the dangerous position I’d like to speak to.
The key issue is that the base code’s development will continue without you. It doesn’t sound bad at first until a bug fix, performance optimization or fancy new feature is developed that your end-users want. When you write these yourself, you’re wasting time playing catch-up, throwing away a free development team. On top of that, the base code might get a new internal API making certain features trivial to implement that are infeasible in your fork.
If you get to this point, you need to look into migrating your data to a new system.
- Determine the key features that make up your application. Ignore the eye-candy and focus on the functional requirements.
- Compare these requirements to the features in the latest version of the base code. Does the new version support a reasonable plugin architecture? Chances are it didn’t at the time you forked, otherwise you wouldn’t be in this mess. Consider alternate code bases that are friendlier to module development.
- Build a prototype in the best-fit framework and confirm that it meets the requirements from the first step. It doesn’t need to look the same as your legacy system; It just needs to accomplish the same goals.
- Transition data and only data from your legacy system. You’ll need to map the two datasets and build a conversion script, which could take months depending on the complexities.
There are a number of frightening unknowns with this process. You don’t know how long the total transition time is going to take. Key features might need to be rebuilt from scratch using the plugin system. Database compatibility issues might arise while transitioning your data. These concerns make modernizing your application risky, but their risk is less than that of the issues you’re already dealing with. In the long term, the development investment pays for itself.
The heuristic I’m getting at is to keep things as simple as possible and you can do that by offsetting a large portion of development to an external community. This helps minimize the number of complex components you need to be concerned with, resulting in an application that’s easier to understand for current and future developers.