#ifdef considered harmful (was: DData)
Alastair Reid
alastair at reid-consulting-uk.ltd.uk
Fri Apr 16 15:35:30 EDT 2004
On Friday 16 April 2004 13:25, Wolfgang Jeltsch wrote:
> The very big problem with the preprocessor approach is,
> in my opinion, that it's awkward to add a new platform. With Robert's
> approach you just add some new files and don't touch the existing code.
> With the preprocessor approach you need write access to the source code of
> the library in question, I'd say.
I find that it works a little differently in practice (when writing C, at
least):
1) You write the code for one platform.
2) To add a second platform, you refactor the code by designing
a portable interface to the functionality of the two platforms
and splitting the code into a portable top half and two
platform specific bottom halves.
[In practice, the first two steps are often combined since many
of us develop for two platforms at once.]
3) You add a few minor variations on the original platforms with little
effort.
For very closely related platforms (Win98 and Win2K, Debian and Redhat,
versions 3.4 and 3.5 of <whatever>), you might have just one or two lines
of changes. Suppose you need to change just one line out of 100 lines
of code, do you further subdivide the platform-specific module,
do you use ifdef or do you cut and paste 100 lines of code.
[Complication: the person doing the port might not have access to
the original platform so they can't test the modified code. No problem if
you're writing a completely fresh implementation but a major issue if
you have to refactor an existing implementation.]
4) You try to port it to a less familiar platform: Mac, HPUX, etc. which
views the world from a different angle from Unix and Windows and have
to change the design of the portable interface to all the implementations.
This requires that you change the code in all implementations.
[Complication: again, you may not have access to the other platforms.]
Refactoring the code into multiple modules can play a part in porting code but
conditional compilation plays an important role too. In particular, if you
find yourself changing code that you can't test, you can use conditional
compilation to leave the bulk of the code unchanged so that simple tools
(e.g., diff) can help you hand-check the changes you can't check.
Of course, we don't see this in Haskell much but that's because we don't try
very hard to support multiple versions of a library...
--
Alastair Reid
More information about the Libraries
mailing list