Looking for advice in managing code in related applications (long)
-
The problem might be in your accounting and business model. Many companies have solved this by building an extensible core product and then having a separate consulting branch to do customizations. You get a balance of steady core licensing money that can scale out with a variable amount of customization for installation and upgrade. Customers own the output of consulting but only license the core. 100% consulting work doesn't scale. Even with outside consulting, the entire "ecosystem" can be more profitable for the company than trying to own the whole thing.
I can imagine the sinking feeling one would have after ordering my book, only to find a laughably ridiculous theory with demented logic once the book arrives - Mark McCutcheon
+1, this is how we do things and it works great. We built a couple core products and rigged them with a "plugin" architecture with extensibility points all over the place. We sell the core product along with some standard plugins, and just bill time for developing custom plugins.
-
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
My company is also struggling with a similar issue. We have lots of customers and lots of different requests for tweaks and features. We want to maintain a single codebase, but we've had to compromise in several areas. Essentially we've optioned the crap out of the system. We do this on several levels: - Master settings, the functionality exists in the base code, but we can turn it on/off or make it work like A/B/C on our end. The customer has no control over this - User settings, the code exists for everyone and the customer has the ability to flip switches that will make it work A/B/C - Custom inline code, just chunks in the common codebase that says 'if customer=="A" do this, else do that' - these make my head hurt and make bugs hard to reproduce - Custom pages, places where the whole app will branch over to a different page depending on the customer. essentially where there would have been WAY too many custom inline codes, and so now its a whole different module Of course, this is all(supposed) to be done at the UI layer, and the Data and BL layers are common to everyone, but there are exceptions there too. My suggestion? Tell the customer no. Tell them that you already have A1, because you built it for someone else, and it's A)Cheap B)Done and C)Less buggy because it's been in production a while. If they really have to have A2 or B12, raise the price. I think most customers would go with the cheap, finished, proven solution. I mean, I'm sure we'd all like to customize windows and office and visual studio, but I'd rather buy it for 300 than pay microsoft 15k to make me a custom version. This of course assumes that we're talking about a few wrinkles here and there and not massively different functionality. But if it WERE massively different functionality, I wouldn't give yourself a headache with reuse, just have multiple codebases, call em different products and bill it all separate. As a dev it makes me cringe to reinvent the wheel, but sometimes its easier than trying to build a wheel that fits a bike, a skateboard, and a ferrari.
-
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
We did this for a family (~20) of Visual Studio solutions. We called them "base" and "child" solutions. Any child solution could also be the base for other solutions, so you could have chains and trees of solution dependencies. We created a Visual Studio add-in that would import a selected version of some base solution (we versioned the solution builds) and put its exported assemblies in a solution folder in the child solution. Projects in the child solution would then reference (using the Browse tab) these base assemblies. As part of the import, we generated and maintained in the child solution a manifest that noted the imported solution's version (including the assembly versions it contained). A custom MSBuild task would verify that the assembly versions matched the manifest at build time. In base solutions, projects marked as exportable were copied to an export folder. This way, we could keep e.g. unit test projects or application projects in the base from being brought down during import. It worked very well, not only supporting the solution dependencies, but also rolling updates: one child solution could import an updated base, while another could wait until a appropriate time to make the upgrade. The only icky part was when a child had multiple parent solutions that themselves inherited from the same base (a diamond-shaped dependency tree). In that case, both parents had to update their base solution version at the same time or else the child could not be built. The process also supported import of the debug compile during development and then import of the release compile on the build box. There was also a temporary import that allowed you to import a base solution on your own dev machine (for when you're making updates to the base and need to get them to the child to complete testing). It did not take all that much work to get this set up. Not sure why Visual Studio/TFS doesn't have support for it or something similar. unfortinately, i don't own what code there was, so can't share it. But I think it's the concept that's significant.