I'm working on a large software project which is highly customized for various customers arround the world. This means that we have maybe 80% code which is common between the various customers, but also a lot of code which has to change from one customer to the other. In the past we did our development in separate repositories (SVN) and when a new project started (we have few, but large customers) created another repository based on whatever past project has the best code basis for our needs. This has worked in the past, but we ran into several problems:
- Bugs which are fixed in one repository are not patched in other repositories. This might be a problem of organization, but I find it difficult to fix and patch a bug in 5 different repositories, keeping in mind that the team maintaining this repository might be in another part of the world and we don't have their test environment, neither know their schedule or what requirements they have (a "bug" in one country might be a "feature" in another).
- Features and improvements made for one project, which might also be useful for another project are lost or if they are used in another project often cause big headaches merging them from one code base to another (since both branches might have been developed independently for a year).
- Refactorings and code improvements made in one development branch are either lost or cause more harm than good if you have to merge all these changes between the branches.
We are now discussing how to solve these problems and so far came up with the following ideas on how to solve this:
Keep development in separate branches but organizing better by having a central repository where general bug fixes are merged into and having all projects merge changes from this central repository into their own on a regular (e.g. daily) basis. This requires huge discipline and a lot of effort for merging between the branches. So I'm not convinced that it will work and we can keep this discipline, especially when time pressure puts in.
Abandon the separate development branches and have a central code repository where all our code lives and do our customization by having pluggable modules and configuration options. We are already using Dependency Injection containers to resolve dependencies in our code and we are following the MVVM pattern in most of our code to cleanly separate business logic from our UI.
The second approach seems to be more elegant, but we have many unsolved problems in this approach. For example: how do handle changes/additions in your model/database. We are using .NET with Entity Framework to have strongly typed entities. I don't see how we can handle properties which are required for one customer but useless for another customer without cluttering our data model. We are thinking of solving this in the database by using satellite tables (having a separate tables where our extra columns for a specifiy entity live with a 1:1 mapping to the original entity), but this is only the database. How do you handle this in code? Our data model lives in a central library which we would not be able to extend for each customer using this approach.
I'm sure that we are not the only team struggling with this problem and I'm shocked to find so little material on the topic.
So my questions are the following:
- What experience do you have with highly customized software, what approach did you choose and how did it work for you?
- What approach do you recommend and why? Is there a better approach?
- Are there any good books or articles on the topic that you can recommend?
- Do you have specific recommendations for our technical environment (.NET, Entity Framework, WPF, DI)?
Thanks for all the suggestions. Most of the ideas match those that we already had in our team, but it is really helpful to see the experience you had with them and tips to better implement them.
I'm still not sure which way we will go and I'm not making the decision (alone), but I will pass this along in my team and I'm sure it will be helpful.
At the moment the tenor seems to be a single repository using various customer specific modules. I'm not sure our architecture is up to this or how much we have to invest to make it fit, so some things might live in separate repositories for a while, but I think it's the only longterm solution that will work.
So, thanks again for all responses!