views:

34

answers:

1

I've been working on a series of applications with related functionality with each app being delivered for a different customer. The apps have significant amounts of functionality in common but there are some features unique to each customers requirements which cannot be provided to any of the others.

Because all the versions belonging to our customers (A1, B2, A3) so far were funded and developed separately and in sequence in each case we simply took a snapshot of the prior customers source put it in a new SVN repository and started making changes from there. We've managed OK so far but with more customers expected in the future and plans in place to roll some of the improvements from customer A3's application back into a new version for A1 our current setup isn't going to remain manageable with our current process.

What I'm looking for is information about how this sort of thing has been done elsewhere and what would be the best way for us to proceed. I'll describe my thoughts on how we proceed along with concerns I have about it and am looking for feedback on it.

We envision our customers being split into two main groups based on some high level capability differences. My prefixing our customer IDs with A and B reflects this; A1 and A3's versions of the software have significantly more in common than B2's. At present we don't expect there to be a C category to be added but can't rule out that changing several years from now.

Our basic idea is to split the common parts of functionality (both backend and win form classes) into common core libraries for A and B type customers; and to then inherit the common classes and implement customer specific functionality for each version in a separate solution. We might also have a top level common library for things shared with both A and B although there're enough differences between A and B that I'm concerned we'd end up overriding enough of the methods that it ends up only adding complexity to the situation.

The reason I think I need to put each customers application into a separate solution instead of having a single solution and just selecting which customers app to run is severalfold:

The first is that due to customer specific NDA's we're likely going to have new developers who won't be allowed access to apps done previously because without their being tasked to work on customer X's application they can't meet the externally imposed need to know requirement for NDA approval.

The second is that because we're working directly on a specific customers money we can't make changes to the common libraries functionality (eg moving something from customer specific to the core or vice version) and then update each customer specific app to continue to work with the new core. This constraint is a large part of why we initially went with the independently maintained code bases concept and has the potential to make validating the "correctness" of where we split common and customer specific functionality a challenge at the contractual level.

The third is related to the second. For security reasons if customer X can't have feature Y, then X's application cannot have methods to implement Y in the common library even if X's application doesn't have any way to call the method because if they were clever enough they could do reverse engineering write their own front end that sits on top of the common library.

Edit: This question seems to've mostly died here, but I did get a decent amount of discussion on another site.

+1  A: 

I haven't been in quite this situation but hopefully this will be helpful.

I think you're onw the right track to keep clients in seperate solutions; repeating code might be extra work at development time initially - but it's still pitance next to the sheer volume of grief you can get into when managing dependancies goes astray - and the overhead in having to manage them in the first place.

I'd keep the Stable Abstractions Principle and Stable Dependencies Principle in mind: farm out as much common and low-level code into libraries that won't change too much and which the more volitile (and politically sensitive) packages can reference.

To me there is an important distinction between "library" code that offers low level "coding" or system level services (saving files, accessing confog, etc) and pure business logic code / modules. So I would have thought a bit of sensible re-use here was acceptable.

Also in-line with SAP and SDP is the approach of abstracting out implementations as much as possible: Dependency Inversion and the Strategy pattern will be helpful here.

Although what you're doing is not a multi-tenant application I think you might find a few common issues - and hopefully some useful solutions or approaches.

All the suggestions I've made here seem to be at the code / architectural / pattern level - I'm aware I haven't volunteered much on the practical code management / QA / Release side - sorry.

Adrian K
"All the suggestions I've made here seem to be at the code / architectural / pattern level - I'm aware I haven't volunteered much on the practical code management / QA / Release side - sorry." That's not a problem all of it ultimately flows together.
Dan Neely