Looking for advice in managing code in related applications (long)
-
First off -- can branching do what you need? Second -- when you deliver the source code, do you send a repository? Or a group of files? I'm only acquainted with two version control systems: I've used OpenVMS' CMS layered product and I've read up on Subversion because I was going to try it out before I got laid off from my last job. Having used CMS, I see that Subversion (and probably every other popular system out there) is hindered by a lack of the grouping and flexibility that CMS provides. The company that used CMS considered VSS, but the lack of grouping was a show stopper. Having said that, I have thought some more on this subject and I have come to the conclusion that basically what we were doing was a form of branching the hard way. Otherwise, we did no branching, we didn't need it. So... what am I talking about? Subversion et al seem to only group files in "directories" -- this is not how I was trained, we just put all the files in one directory and build it. Grouping files in directories makes no sense to me primarily because you can't put a file in multiple directories without making multiple copies, which would eliminate many of the benefits of using a version control system. CMS has groups and a file may be in multiple groups. CMS also has classes which are similar to groups, but contain particular versions of files (these were used extensively by the build process). In CMS you can also refer to multiple libraries (which may be the similar to repositories) at once. What we did (and I don't intend to claim any credit; it was in place when I got there) was have a library for common code and separate libraries for each client system. One client library had no knowledge of the others. And by using groups, we could control which subsystems were to be included in a particular client's product. During the build, only the requested versions of the specified files were fetched and built. Obviously, we couldn't send a repository, but we could have ZIPped up the files and sent them if we wanted to (we didn't). Since I left there I have only worked at places with essentially no version control system X| , but I have often thought about writing my own -- taking lessons from CMS. A year ago (2009-07-30, according to my comments) I finally got around to a starting to do it. What I have now has most of the features I intended to have -- except for the ability to query the repository for its contents :~ -- I'm stuck on deciding what I want. I've barely looked at th
PIEBALDconsult wrote:
First off -- can branching do what you need?
Maybe but I doubt it. We'd need to be able to control access permissions to each customer branch independently. that seems esoteric enough that I kinda doubt it'd be a feature.
PIEBALDconsult wrote:
Second -- when you deliver the source code, do you send a repository? Or a group of files?
Group of files. Take the latest svn snapshot, delete all the bin/obj folder junk. Delete all the .svn folders. Plop onto CD. Stuff into box. Ship. Get filed in customers CM system and forgotten about.
PIEBALDconsult wrote:
Grouping files in directories makes no sense to me primarily because you can't put a file in multiple directories without making multiple copies, which would eliminate many of the benefits of using a version control system.
From what I've been told SVN does support symbolic links if the file system of the server supports it. Moot point in my case since our companies infrastructure is windows based whereever possible; and either NTFS junctions don't do what SVN needs or do it in a way that offends punguinland sufficiently that they're unwilling to implement it. The latter reason probably applies to not implementing 'fake' symbolic links in software even if the underlying FS doesn't support them. Rational ClearCase does support symbolic links; but in every other way sucks far worse than SVN as a developers tool.
PIEBALDconsult wrote:
I'll close by asking what features you would like in a version control system to help alleviate your problems?
The lack of symbolic links is a pita so I definitely want that. To put everything in a single repository (vs having to pull from two to build any single customers app) would need setting access permissions at a folder level. Otherwise I'm fairly happy with SVN's current feature set. The blame tool is something I'd look for if switching to a new repository. This would be more useful in a document management than code management but the server being able to create customizable per user views (as in show me Foo.CS version 20, branch NewStuff everywhere it exists, latest file version for everything else) and expose them on a network share type interface (but without actually creating 100 shares with 100 copies of every files if the
-
PIEBALDconsult wrote:
First off -- can branching do what you need?
Maybe but I doubt it. We'd need to be able to control access permissions to each customer branch independently. that seems esoteric enough that I kinda doubt it'd be a feature.
PIEBALDconsult wrote:
Second -- when you deliver the source code, do you send a repository? Or a group of files?
Group of files. Take the latest svn snapshot, delete all the bin/obj folder junk. Delete all the .svn folders. Plop onto CD. Stuff into box. Ship. Get filed in customers CM system and forgotten about.
PIEBALDconsult wrote:
Grouping files in directories makes no sense to me primarily because you can't put a file in multiple directories without making multiple copies, which would eliminate many of the benefits of using a version control system.
From what I've been told SVN does support symbolic links if the file system of the server supports it. Moot point in my case since our companies infrastructure is windows based whereever possible; and either NTFS junctions don't do what SVN needs or do it in a way that offends punguinland sufficiently that they're unwilling to implement it. The latter reason probably applies to not implementing 'fake' symbolic links in software even if the underlying FS doesn't support them. Rational ClearCase does support symbolic links; but in every other way sucks far worse than SVN as a developers tool.
PIEBALDconsult wrote:
I'll close by asking what features you would like in a version control system to help alleviate your problems?
The lack of symbolic links is a pita so I definitely want that. To put everything in a single repository (vs having to pull from two to build any single customers app) would need setting access permissions at a folder level. Otherwise I'm fairly happy with SVN's current feature set. The blame tool is something I'd look for if switching to a new repository. This would be more useful in a document management than code management but the server being able to create customizable per user views (as in show me Foo.CS version 20, branch NewStuff everywhere it exists, latest file version for everything else) and expose them on a network share type interface (but without actually creating 100 shares with 100 copies of every files if the
Dan Neely wrote:
The lack of symbolic links is a pita so I definitely want that.
I'm unlikely to do that because I prefer the "stick 'em all in one directory" (per client system) approach. The directory tree approach only causes this kind of "problem". It's really a matter of operating system limitations and having the software development process follow what the IDE wants rather than the other way around.
Dan Neely wrote:
The blame tool
I may have to re-read up on that.
Dan Neely wrote:
control access permissions to each customer
Oh, yeah, I forgot about that; I don't currently support controlling access to libraries (or any other content). That might be important. CMS supports that sort of thing, but I've never seen it used -- all developers had full access to everything.
-
If I go with something different than my original idea I can post a brief update. *mutter* NDAs *mutter* *mutter* can't write about in detail needed for an article *mutter* *mutter* *mutter* *mutter*
3x12=36 2x12=24 1x12=12 0x12=18
Regarding symbolic links could you not use the Subversion externals http://svnbook.red-bean.com/en/1.0/ch07s03.html[^] where you can ink 2 repositories together Eg Common code repository C and then A and B would share this reference. Also regarding not exposing certain api's from a common set just have another layer in between that can pick and choose which common apis are exposed to A or B clients. If you were using C sharp you could use the internal's access modifier and then the internals visible to property if you wanted more separation of libraries. David Ooops replied to wrong post was suppose to be on PIEBALDconsult link
-
PIEBALDconsult wrote:
First off -- can branching do what you need?
Maybe but I doubt it. We'd need to be able to control access permissions to each customer branch independently. that seems esoteric enough that I kinda doubt it'd be a feature.
PIEBALDconsult wrote:
Second -- when you deliver the source code, do you send a repository? Or a group of files?
Group of files. Take the latest svn snapshot, delete all the bin/obj folder junk. Delete all the .svn folders. Plop onto CD. Stuff into box. Ship. Get filed in customers CM system and forgotten about.
PIEBALDconsult wrote:
Grouping files in directories makes no sense to me primarily because you can't put a file in multiple directories without making multiple copies, which would eliminate many of the benefits of using a version control system.
From what I've been told SVN does support symbolic links if the file system of the server supports it. Moot point in my case since our companies infrastructure is windows based whereever possible; and either NTFS junctions don't do what SVN needs or do it in a way that offends punguinland sufficiently that they're unwilling to implement it. The latter reason probably applies to not implementing 'fake' symbolic links in software even if the underlying FS doesn't support them. Rational ClearCase does support symbolic links; but in every other way sucks far worse than SVN as a developers tool.
PIEBALDconsult wrote:
I'll close by asking what features you would like in a version control system to help alleviate your problems?
The lack of symbolic links is a pita so I definitely want that. To put everything in a single repository (vs having to pull from two to build any single customers app) would need setting access permissions at a folder level. Otherwise I'm fairly happy with SVN's current feature set. The blame tool is something I'd look for if switching to a new repository. This would be more useful in a document management than code management but the server being able to create customizable per user views (as in show me Foo.CS version 20, branch NewStuff everywhere it exists, latest file version for everything else) and expose them on a network share type interface (but without actually creating 100 shares with 100 copies of every files if the
Regarding symbolic links could you not use the Subversion externals <a href="http://svnbook.red-bean.com/en/1.0/ch07s03.html">http://svnbook.red-bean.com/en/1.0/ch07s03.html</a>[<a href="http://svnbook.red-bean.com/en/1.0/ch07s03.html" target="_blank" title="New Window">^</a>] where you can ink 2 repositories together Eg Common code repository C and then A and B would share this reference. Also regarding not exposing certain api's from a common set just have another layer in between that can pick and choose which common apis are exposed to A or B clients. If you were using C sharp you could use the internal's access modifier and then the internals visible to property if you wanted more separation of libraries. David
-
Chris Maunder wrote:
Sometimes things (and when I mean "things" I mean "business rules dictated by competing or potentially conflicting needs") are just plain complex.
Of course... maybe I was being too simplistic. But given a choice between moderately complex and very complex - all things being equal I'll pick moderately complex. As an example: We use mostly Siemens CNC controls on the machine tools we manufacture. We often use a large Siemens application called Step 7 for machine logic. It's a 45 minute install (with various add-on libraries) and consumes about 1 Gb of HD space. No big deal, right? Well, over time my install became unstable and Siemens tech support recommended a full uninstall of all Siemens software and e-mailed me the documentation on how to do it. Something along the lines of: Go to control panel "Add / Remove Programs" Uninstall "Step 7" Uninstall "Step 7 Library ABC" ... Uninstall "Step 7 Library XYZ" Run registry editor and delete HKLM\Software\Siemens Go to Program Files\Siemens and delete *.* Go to C:\WINDOWS\SYSTEM32 and delete S7*.* I did all this without any problem. Rebooted and then on a hunch re-ran the registry editor and searched for terms like Siemens, Step 7, S7, Sinamics, Sinumeric (All Siemens product and trade names). Over 7000 registry entries remained!!! Seriously! With over 7000 orphaned registry entries is it any doubt that the system was unstable? Complexity gone wild!
modified on Wednesday, July 28, 2010 6:52 PM
Taking a guess, that's probably COM object registration cruft. Cleaning it up properly usually requires intimate knowledge of the application. If Siemens is willing to provide a documented procedure for doing a complete 'cleanup' operation, they ought to simply automate it and clean the registry while they're at it. Â Â Â Â - from the Been There, Done That files
Software Zen:
delete this;
-
I won't say nothin'. Promise.
cheers, Chris Maunder The Code Project | Co-founder Microsoft C++ MVP
Just a little note to 7,000,000 of your closest friends, right?
Software Zen:
delete this;
-
PIEBALDconsult wrote:
First off -- can branching do what you need?
Maybe but I doubt it. We'd need to be able to control access permissions to each customer branch independently. that seems esoteric enough that I kinda doubt it'd be a feature.
PIEBALDconsult wrote:
Second -- when you deliver the source code, do you send a repository? Or a group of files?
Group of files. Take the latest svn snapshot, delete all the bin/obj folder junk. Delete all the .svn folders. Plop onto CD. Stuff into box. Ship. Get filed in customers CM system and forgotten about.
PIEBALDconsult wrote:
Grouping files in directories makes no sense to me primarily because you can't put a file in multiple directories without making multiple copies, which would eliminate many of the benefits of using a version control system.
From what I've been told SVN does support symbolic links if the file system of the server supports it. Moot point in my case since our companies infrastructure is windows based whereever possible; and either NTFS junctions don't do what SVN needs or do it in a way that offends punguinland sufficiently that they're unwilling to implement it. The latter reason probably applies to not implementing 'fake' symbolic links in software even if the underlying FS doesn't support them. Rational ClearCase does support symbolic links; but in every other way sucks far worse than SVN as a developers tool.
PIEBALDconsult wrote:
I'll close by asking what features you would like in a version control system to help alleviate your problems?
The lack of symbolic links is a pita so I definitely want that. To put everything in a single repository (vs having to pull from two to build any single customers app) would need setting access permissions at a folder level. Otherwise I'm fairly happy with SVN's current feature set. The blame tool is something I'd look for if switching to a new repository. This would be more useful in a document management than code management but the server being able to create customizable per user views (as in show me Foo.CS version 20, branch NewStuff everywhere it exists, latest file version for everything else) and expose them on a network share type interface (but without actually creating 100 shares with 100 copies of every files if the
Dan Neely wrote:
Group of files. Take the latest svn snapshot, delete all the bin/obj folder junk. Delete all the .svn folders.
TortoiseSVN :thumbsup:, so i assume that other clients probably have it too, has a function called Export that does all of that for you. Just in case you didn't know. Manually finding those .svn directories can be a pain in a large project.
-
Dan Neely wrote:
Group of files. Take the latest svn snapshot, delete all the bin/obj folder junk. Delete all the .svn folders.
TortoiseSVN :thumbsup:, so i assume that other clients probably have it too, has a function called Export that does all of that for you. Just in case you didn't know. Manually finding those .svn directories can be a pain in a large project.
Steven Nicholas wrote:
Just in case you didn't know.
I did not. Thanks.
Steven Nicholas wrote:
Manually finding those .svn directories can be a pain in a large project.
Doing a search for ".svn" in explorer let me cleanup in a minute or three on a fairly large sized project but delivery day is always a rush...
3x12=36 2x12=24 1x12=12 0x12=18
-
Macros might work in theory but one of our deliverables is source code to A1 (who in sells the system our app's part of to the other users); trying to explain that the IFDEF's mean that even though an item we can't give to the end user is in the source isn't in the executable is somewhere we don't even want to think about going. Even if we crossed that bridge new developers not having NDA access to what we did for old customers would be a show stopper. Include files are out because it's a C# app; not C/++.
3x12=36 2x12=24 1x12=12 0x12=18
.. o.k. I'll say this right off.. it's not elegant.. but: You could really Hack up your libraries, into a partial class definition for Each method, and build a class "library" then when you compile, you can use an internal reflection tool ( i recently saw something similar for projects, but while playing with it i noticed you can get fairly granular) to get just the methods you actually want to give that particular client, .. this method would be tedious but would have very little.. housekeeping while the code was in development.. Alternatively you could do MyClass_Common.cs,MyClass_AI.cs, myClass_A2.cs.. using the same MyClass namespace for each of the "MyClass_{blah}" files, this forces you to do housekeeping, and you will need every permutation of company sharing represented in your file base.... easy to do if you have one or two companies, but you get a much larger file base (and more complicated) if you take on a new client... (3 clients: 3!+1 = 7files, 4 clients: 4!+1 = 25, 5 clients: 5!+1 = 121)!... so not a very good choice if you want to keep getting new clients... :-D
I'd blame it on the Brain farts.. But let's be honest, it really is more like a Methane factory between my ears some days then it is anything else...
-
.. o.k. I'll say this right off.. it's not elegant.. but: You could really Hack up your libraries, into a partial class definition for Each method, and build a class "library" then when you compile, you can use an internal reflection tool ( i recently saw something similar for projects, but while playing with it i noticed you can get fairly granular) to get just the methods you actually want to give that particular client, .. this method would be tedious but would have very little.. housekeeping while the code was in development.. Alternatively you could do MyClass_Common.cs,MyClass_AI.cs, myClass_A2.cs.. using the same MyClass namespace for each of the "MyClass_{blah}" files, this forces you to do housekeeping, and you will need every permutation of company sharing represented in your file base.... easy to do if you have one or two companies, but you get a much larger file base (and more complicated) if you take on a new client... (3 clients: 3!+1 = 7files, 4 clients: 4!+1 = 25, 5 clients: 5!+1 = 121)!... so not a very good choice if you want to keep getting new clients... :-D
I'd blame it on the Brain farts.. But let's be honest, it really is more like a Methane factory between my ears some days then it is anything else...
-
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
You have the right ideas on the refactoring. To address the security concerns, make a solution for all the common code, and separate solutions & branches in your repository for each individual customer. Control access to the per-customer source as needed.
Dan Neely wrote:
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.
You could do ifdefs and the like. I'd use a per-customer visual studio properties page or a solution build environment to control the settings of the ifdefs for each customer. That way, your developers and build machine won't accidently get it wrong. However, if all you're trying to prevent is them using features they haven't paid for, there's way easier solutions. First off, your license likely already explicitly prohibits reverse engineering, so doing do is a direct violation of the licent agreement. Make it hard for them to unintentionaly find and use those functions. Put those features under license control (ie. have your license system specifically lock or unlock those features). Then let the threat of legal action be their deterrent. Having to find and use, and especially defeat license restrictions, shows intent to violate the license agreement. If that customer has deep pockets or significant reputation established, they won't take the risk.
patbob
-
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
1. As another poster mentioned. Use branching, not copies of repositories. Security can be developed around branches with a little more work than separate repositories, but merging and creating "soft" copies will be a lot faster. If you must stick with separate repositories, there should only be one repository of the core that could have branches as needed for different needs. This repository should be 100% NDA encumbered. 2. Consider inverting your design. You keep talking about Core libraries loading the custom code. Invert this thinking. 1. Have the custom apps load the core components (OSGI?) 2. Break the core components into very granular pieces. The core components should all be non-NDA encumbered pieces. 3. If you are using C/C++ which it sounds like ... When required to deliver the source code to the customer. Deliver the output of the pre-processor! Not the original file with all of the ifdefs. In fact, change your "retail" build process to do this to ensure that the same post processed source will compile correctly. This will meet your contractual obligations without tipping your hand to things that other customers have asked for. 4. For NDA hell, you should be able to come up with one NDA that all developers sign and one NDA that all customers sign. Worse case, you should be able to have an attorney help you here. Are you allowed to use sub-contractors on a project? Isn't it funny how that sub-contractor "Core Components" gets spec'ed to write all of the core libraries. They don't know who and will never know who's custom app uses this piece, so there is no possiblity of incorrect disclosure, but dang it if it doesn't look like something that they just wrote last week. Also, remember that you could incorporate the pre-processor into any language, not just C. It can be an independent build step. 5. use interfaces wisely. Customer specific implementations just support that interface.
-
1. As another poster mentioned. Use branching, not copies of repositories. Security can be developed around branches with a little more work than separate repositories, but merging and creating "soft" copies will be a lot faster. If you must stick with separate repositories, there should only be one repository of the core that could have branches as needed for different needs. This repository should be 100% NDA encumbered. 2. Consider inverting your design. You keep talking about Core libraries loading the custom code. Invert this thinking. 1. Have the custom apps load the core components (OSGI?) 2. Break the core components into very granular pieces. The core components should all be non-NDA encumbered pieces. 3. If you are using C/C++ which it sounds like ... When required to deliver the source code to the customer. Deliver the output of the pre-processor! Not the original file with all of the ifdefs. In fact, change your "retail" build process to do this to ensure that the same post processed source will compile correctly. This will meet your contractual obligations without tipping your hand to things that other customers have asked for. 4. For NDA hell, you should be able to come up with one NDA that all developers sign and one NDA that all customers sign. Worse case, you should be able to have an attorney help you here. Are you allowed to use sub-contractors on a project? Isn't it funny how that sub-contractor "Core Components" gets spec'ed to write all of the core libraries. They don't know who and will never know who's custom app uses this piece, so there is no possiblity of incorrect disclosure, but dang it if it doesn't look like something that they just wrote last week. Also, remember that you could incorporate the pre-processor into any language, not just C. It can be an independent build step. 5. use interfaces wisely. Customer specific implementations just support that interface.
englebart wrote:
3. If you are using C/C++ which it sounds like ...
C# actually.
englebart wrote:
4. For NDA hell,
The NDA hell is coming externally from the people who're making the larger system our app is a part of. There's nothing we can do about it, my bosses tried... :sigh:
3x12=36 2x12=24 1x12=12 0x12=18
-
Steven Nicholas wrote:
Just in case you didn't know.
I did not. Thanks.
Steven Nicholas wrote:
Manually finding those .svn directories can be a pain in a large project.
Doing a search for ".svn" in explorer let me cleanup in a minute or three on a fairly large sized project but delivery day is always a rush...
3x12=36 2x12=24 1x12=12 0x12=18
WRT version control a distributed system might work better for you, as this would enable you to have a production repository per client. WRT to the general nature of the original post - I'll have to echo the sentiments that have already been expressed: it's not a software problem and can't be solved in the software.
-
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.