One of the biggest benefits of Open Source Software is the fact that you can customize it completely towards your needs and business processes. Unfortunately, it also tends to be one of the biggest drawbacks. Yes, you can customize, tune, and generally make it fit exactly what you're looking for, but now you've taken a turn down a dark path…
Whenever you customize a piece of Open Source Software, you've created a fork. Forks are inherently difficult to deal with for a simple reason, they're a new piece of software:
a project fork happens when developers take a copy of source code from one software package and start independent development on it, creating a distinct piece of software.
As my friend and colleage Duane Gran has noted, this provides a strong motivator to contribute back to the community, but there is one consideration missing:
What if these customizations are part of your competitive advantage?
Suddenly, everything becomes much more complicated.
First, you want and need to protect your advantage. Your shareholders – whether they're public or just you – probably didn't invest time, money, etc in your business unless they wanted to make money. It's one thing to release back fixes to the infrastructure but to give up something that makes your business successful is generally a bad idea and in some circles could be considered irresponsible.
Second, you will have to update/re-apply your changes every time you need to upgrade anything. I don't know about you, but I have more important things to do. In fact, when I upgrade core infrastructure or tools, if I lose more than an hour or two, I'm probably farther behind than I began.
Finally – and most importantly – at any given time, a change could happen in the Open Source package which makes your customization difficult or worse yet, completely incompatible with the core system. Therefore, each time you apply the customization, you drift farther and farther from the core project.
So how do you fight something like this? It's not exactly easy, but the solution is to cleanly segment your changes from the core system while simultaneously adjusting the core system for your needs.
For example, the dotProject Files Module allows you to attach Files to any Project – or even Task – within the system. By design, it stores all files on the local filesystem and performs some simple versioning. But what happens if you want to store your files elsewhere such as an existing document repository? You could create your own File Module which interacts with your repository but you run into the problems noted above. Instead, you can stop to evaluate the existing Files Module and how it interacts with the local store, and finally where the changes need to be made. By applying a bit of analysis and creativity, you could create a pluggable module which could support numerous storage backends. By passing back this new module, you can effectively keep your customized backend internal while ensuring future compatibility with the core system.