Fog Creek Software
Discussion Board

How do you manage software variations?

At the company I work for, a small software shop, we build serveral (Linux based) products based on a single C/C++ code tree. For specific markets and client, we roll out different versions based on this set of code, executibles, web pages and data files.

The products share about 90% of the code and files but, as you would guess, the 10% of differences is a pain. It requires tedious and error prone book keeping of the various differences in code, data files, 3rd party software and their location in the target setup, and all this over different revisions. Currently that means a lot of #defines, symlinks, duplicate files, blood, sweat and tears.

So I'm looking for options on how to make it easier to create, build, deploy and maintain multiple variations and revisions of the project in parallel. Though I suppose many developers must have solved these issues, I haven't found much literature or tools on it. Did I miss the obvious? What do you do/use to manage this?

Btw, this is what we already use for CM:
- CForge for IDE, GNU make and a bunch of shell scripts to do the (daily) builds.
- version control to keeps track of revisions, branches and merges. CVS.
- change management to keeps track of issues and changes. Now Mantis, soon FogBUGZ.

Thursday, February 26, 2004

If it's possible, keep your variations in terms of data only.  That is, you have your source code shared for all clients, and what is client specifc are only files, variables, images, etc.  If more powerful customization is needed, try and do it through plugins.

It might pay to break your development into two groups.  One group handles the source that is generic across clients.  The second group would handle and track client customizations.  This would reduce the temptation for a programmer to tack another #define in the shared source.

Thursday, February 26, 2004

Is it possible to move to a plug-in framework, where you have a consistent base, and then have various plug-ins available for your user?

Thursday, February 26, 2004

Modularize all the variations.  Capacity for product variation is not a function of fancy "configuration management" incantations but of good programming.  Refactor when you have a variation, striving to isolate that variation into a component containing all the variations for a particular market or client.  You can usually even statically bind particular variations into your programs by hardcoding the configuration of factories and such at the highest levels of your programs, having a unique "main" for each variation.

Since you say C/C++ rather than C++, that makes me worry that you're not taking the OO route.  If so, you might have a somewhat harder time.  Keep in mind that subtyping in OO is primarily an act of specialization, or said differently: making special variations of something.  Using abstraction patterns such as Abstract Factory, Template Method, and Factory Method, along with sensible class design, you should be able to produce endless variation simply, without a preprocessor or tricky builds, just by normal skillful programming and a component-based programming perspective.

Thursday, February 26, 2004

Sounds like a perfect application of objects.

Per "Design Patterns Explained"  by Shalloway and Trott:

If you find yourself using a lot of Select Case statements then you may want to encapsulate that functionality in an object.

Or, put another way:  take the feature/code that will be likely to change and put it into an object.

BTW, most programmers who tout the benefits of OOP talk about reusing the OBJECT. In reality, I've found (and the above book illustrates VERY WELL) that the benefit is that by changin the OBJECT, you can reuse the other 99% of your code.

I.e., benefit of OOP is reusing the NON-OBJECT code.

I view an object like video game cartridge. You slip a new cartridge into the game console and viola!  you've now got a completely different game. But you only changed one (physically) small piece of the device.

Now... I do realize that it's hard to do this after the fact and that the variances between the different software versions can spread out all OVER the application, making it difficult to just move that code into an object.

But the real benefit is ... when you want to create yet another variation.

Also... obviously if each software variation differs in different ways, an object approach is not of benefit. (.e.,g if you've got 10 variations and they each change one thing.... argbhhh.... nighmare)

The real Entrepreneur
Thursday, February 26, 2004

Strange, I put the video game cartridge in and... piano-accordion!

Thursday, February 26, 2004

You *can* do it as an afterthought, even with an existing design that doesn't support variation well.  Write a really good tests, then refactor, refactor, refactor.  Look at the subtitle of Fowler's book.

The original poster uses CVS, which in my opinion makes refactoring less fun -- CVS can't track the frequent renames, moves, etc. without pain -- but it's far from impossible.

What you can't do without is skill.  But then without skill, all is hopeless anyway.

Thursday, February 26, 2004

Thanks for the feedback so far. I understand the concern regarding reuse in terms of objects (the project's code is OO except for some 3rd-party software running as different processes) but the issue I have goes beyond code alone. I'll have to manage various 'distributions' including library dependencies, file locations, etc.

Example. One product includes an email feature, the other does not. That means optional wrapper functions, libraries, depencies of libraries, configuration files, cgi and html. A third product might have the email feature but with different default values (in configuration file).

Thursday, February 26, 2004

Yes, modularize it.

#ifdefs are your enemy.  Polymorphism is your friend.  The majority of your code goes in the parent class; the SKU-dependent versions are subclasses that override virtual functions in the base class.

Thursday, February 26, 2004

This isn't an OO vs. procedural vs. functional issue.  All those styles have adequate means of coping with customization.

> Example. One product includes an email feature, the other does not. That means optional wrapper functions, libraries, depencies of libraries, configuration files, cgi and html. A third product might have the email feature but with different default values (in configuration file).

Why do you have to do this?  To be blunt, it sounds like your program does not offer smooth customization.  Ship the email feature disabled by default.  Whoever wants to use it can enable it if they want by entering the configuration information in a GUI (rather than having you write a cryptic config file for them).

If I want the Mozilla browser but not their email tool, do I have to download a completely different version from everyone else?  Do I have to tell Mozilla what my email server is so they can #define it in their source?  The image is funny, but thankfully they don't work that way.

Friday, February 27, 2004

*  Recent Topics

*  Fog Creek Home