Tutorial :Managing Custom Client Releases



Question:

As an alternative to this question what is the best way to manage custom versions of software for a particular client?

Most of the differences between client releases is changes to the user interface to customize the software to look like it is owned by the client. More often then not, this is a simple logo change. Occasionaly the color scheme will change as well. But there are occassions where features will be enabled or disabled based on the client. What is the best way to keep all of these releases up to date and make them easily available to the users of a particular client?

At this point we have five different clients and each has their own build of the software and their own installer (complete with their logo in the installer). This is becoming a pain to manage, and it will only get worse as more and more clients start using our software.

So assuming the linked question isn't the way to go, what is the best way to manage these releases?


Solution:1

"This is becoming a pain to manage, and it will only get worse as more and more clients start using our software."

The only way to really solve this part is to make sure your software has an architecture that supports the customizations as a layer on top of your core product. Ideally, they would simply be runtime configuration options (colours, logos and enable/disable are perfect for this). If you get (or want) a very large number of clients, push the configurability right into the core product and enable the clients to do the customizing themselves.

When updating, you build (and test) the core product once, and build the custom versions by simply linking to (referencing) the already-built core product as a library. You could have each client in a separate build, or you could have a single build process that generates updates for all the currently-maintained client builds (the latter is probably better for a larger number of clients). If you have a "vanilla" version, you could build that as part of the core or along with the client versions, it would depend on your particular case.

Depending on your technology, it might be possible to have the customization layer be built independently from the core product. In this case, client rebuilds will rarely be necessary (perhaps only for certain significant changes) -- you can simply link to the updated core product at runtime. For deployment to the client, you would only need to deploy the updated core, if you have a deployment method that supports this.

It's hard to say more detail without knowing your platform, but you've graciously kept this question agnostic.


Solution:2

  1. Separate the common and the custom parts in your source tree. This can eliminate the great majority of merges, depending on your testing and release policies. There is always a way to abstract out and customize a build resource, even if your build process has to invoke script to rewrite some file.

  2. Judicious use of branching in a good Source Code Management system. These aren't called "Configuration Management" systems for nothing. They are the tools optimized for precisely this task, so you're probably not going to get anything better without building on top of one.

Subversion is good at setting up multiple branches, but last I checked it could only do the 3-way merge on a single file at a time. Perforce is awesome in this department because it tracks your branching history on a file-by-file basis and uses this to automate merging of whole sets of changes between whole branches. It really is the cat's pajamas here.

Git and darcs may have similar power, but I haven't used them. They seem to be based on the idea that each working checkout tree will have a copy all changes ever since the beginning of time. That sounds impractical to me since I need to keep some large and changing SDKs under SCM control.


Solution:3

Arguably, the only difference needs to be a branch of whatever release you have, with the customer-unique changes in it. So for example:

/project     /trunk      /branches        /release-v1     /customer-branches        /release-v1-google        /release-v1-microsoft   ....  

Where your client releases are branches of your customer releases. Since these branches won't ever get rolled up into trunk or another release branch, don't pollute the regular development /branches tree.


Solution:4

I guess it depends on the level of customization you need for each client, but could you make your base app "customize" itself based on a config file?, so you could have the trunk being the full app and then have special config files for each customer that control the look & feel, as well as features that are enabled, and your release process would take the correct config files to deploy in your installers.

Seems that if you are always delivering custom(ish) versions of your app for each client, it would be worth the time to extend the app in this way.


Solution:5

I set up a header file called branding.h which contains a bunch of #ifdefs like the following example to change whatever bits need changing. In Visual Studio, it is easy to set up multiple builds with the appropriate client symbol defined.

#if defined BRAND_CLIENT1  #  define COMPANY_NAME  "Client 1"  #  define PRODUCT_NAME  "The Client 1 Widget App"  #  define LOGO_FILE     "res/logoClient1.ico"    #elif defined BRAND_CLIENT2  #  define COMPANY_NAME  "Client 2"  #  define PRODUCT_NAME  "The Client 2 Super Widget App"  #  define ENABLE_EXTRA_MENU  #  define LOGO_FILE     "res/logoClient2.ico"    





        
Previous
Next Post »