Modifying library code

Tuesday 14 March 2006

One of the joys of developing software these days is being able to build on top of high-quality libraries. Finding just the right package to solve one of your problems can remove a huge burden from your development shoulders.

Unfortunately, sometimes you experience the disappointment of realizing your beloved library has a flaw. A bug, a missing function, whatever. Then you have to try to fix it. If you don’t have the source, forget it, you have to work around it. But if you do have the source, do yourself a favor: before modifying the code, put in some protection to make sure your product really is using the modified source.

The problem with modifying library code is that you shift from using the library as shipped to using your modified version, and subtle changes is build or deploy environments can switch you between the two without even knowing it. For example, modified include files have to be found in a product tree before searching the standard include directories. So the first modification to the library should be to mark it as your modified version, and your product code should assert that it is using the modified library.

For example, in C++, in one of the headers, add a macro definition:

// ReportGeneratorLib.h header file

#define INITECH_REPORTGEN_LIB 1

//.. blah blah rest of the header ..

Then in your code where you include the library, check that you have the right version:

// Initech TPS Report system

#include <ReportGeneratorLib.h>

#ifndef INITECH_REPORTGEN_LIB
#error We need the Initech modification to ReportGeneratorLib.h
#endif

// .. rest of product code ..

This way, if a build machine’s configuration changes, or a new devloper doesn’t set up his enviroment properly, a very visible error message will appear, rather than subtle bugs manifesting themselves.

The same technique can be used in Python. Mark the library file:

# ReportGeneratorLib.py

IniTechReportGenLib = 1  # Mark our customizations

and then assert in the product code:

# Initect TPS Report system

import ReportGeneratorLib

assert ReportGeneratorLib.IniTechReportGenLib == 1

# .. rest of product code ..

It’s a very simple technique, but can save headaches later, after you’ve long forgotten about having made the changes to the libraries.

Comments

[gravatar]
Grig Gheorghiu 9:36 PM on 14 Mar 2006

Nice technique. My only observation would be that you don't necessarily need to modify the production code, but you do need to add that assertion in the unit tests for the code that is using that library. You could for example add the assertion in the setup method of your unit test module(s), so that it's picked by any unit test function/method that's exercising that code.

Grig

[gravatar]
Gary Capell 2:50 AM on 15 Mar 2006

Brilliant! Why the !#$!@ haven't we been doing this all along at my company. *slaps forehead*

[gravatar]
Peter Fein 3:09 PM on 15 Mar 2006

I do it both ways:

1. some stuff gets patched in source. I maintain either diffs or vendor-branches in Subversion
2. all of the rest of our monkeypatching is done from one module.

[gravatar]
James Gray 10:19 PM on 18 Mar 2006

Great idea. My solution has been to rename the library file. Which causes a lot of changes to import/include statements throughout the code. (Of course this can be done automaticly)

Add a comment:

Ignore this:
Leave this empty:
Name is required. Either email or web are required. Email won't be displayed and I won't spam you. Your web site won't be indexed by search engines.
Don't put anything here:
Leave this empty:
URLs auto-link and some tags are allowed: <a><b><i><p><br><pre>.