views:

546

answers:

4

Every time I make a project I develop several generic routines/modules/libraries that I expect I'll be using with other projects.

Due to the speed of development I don't spend a lot of time making these modules perfect - just good enough for this project, and well enough documented and isolatable that I can easily add them to another project.

So far so good.

Now when I use them in another project inevitably I improve them - either adding new features/functions, fixing bugs, making them more general, etc.

At that point I have several problems:

  • I need to maintain the changes in the module for the code I'm working on
  • I need to maintain those same changes in a central "module" repository
  • I need to make sure that the updated modules are available for, but not automatically used in older projects, or sometimes even existing projects I'm already working on.

How do you manage this? How are these problems different when you have teams working on various modules in different projects?

+1  A: 

If the code is generic enough that you're using it in multiple projects, is it possible that you're reinventing the wheel? If, instead, you standardise on existing libraries, you'll have code that has already been well-tested and optimised, and you won't have anything to maintain.

Simon Howard
It would be great if code for my problems already existed. In embedded systems development, though, that's often not the case, or the licenses are more expensive/restrictive than developing internally.
Adam Davis
+1  A: 
PersistenceOfVision
A: 

Use version control, of course, as PersistenceOfVision said, and also keep a nightly build to make sure you don't break old projects.

Lev
Once a project is delivered to a customer it has to remain static - we can't change or upgrade the modules. I don't want to split the modules off, though, and have to re-integrate them if I do want to upgrade. Sounds like Subversion allows one to choose a release for a project reference, though...
Adam Davis
+5  A: 

If you're using Subversion for all your projects, you can simply use svn:externals: this allows one repository to reference another repository, optionally fixed at a particular revision. For example,

svn://svn/shared
svn://svn/project1
  |- dir1
  |- dir2
  \- svn:externals "shared -r 3 svn://svn/shared"
svn://svn/project2
  |- dir3
  \- svn:externals "shared -r 5 svn://svn/shared"

Commit your changes to svn://svn/shared, and modify the svn:externals property in the individual projects when you're ready.

Otherwise, using other VCS, you might simply keep a bunch of tags on shared, one for each project using shared, pointing to the version they use. Advance each tag to later versions when ready. This requires manually updating each project's copy of shared, though (one thing which makes svn:externals nice is that it happens automatically).

If you're forking/branching shared for each individual project... well, that can work, but it takes manpower to maintain and merge changes.

[Edit]

Further references:

See External Definitions in the svn book for a tutorial and more details on svn:externals, and git-submodule tutorial for a similar feature in the DVCS git.

ephemient
Do any DVCS (Mercurial, git, etc) support this technique? This sounds like the perfect solution (ie, the VCS knows about and understands inter-project references)
Adam Davis
Git has git-submodule for similar functionality. No other DVCS supports this, as far as I am familiar with.
ephemient
Excellent! Thanks! Here's a quick tutorial on git-submodule: http://git.or.cz/gitwiki/GitSubmoduleTutorial Please consider updating your answer with the git info as well.
Adam Davis
Always use the "fixed at a particular version" feature of svn externals.Otherwise, You will break revision control, because You will get the current version of the shared resource even for very old revisions. This may not even compile anymore!
Black
Note that Mercurial has some support for this, although not great, for several releases now.
Matt Joiner