Why version() ?
Walter Bright
newshound1 at digitalmars.com
Tue Feb 10 17:16:22 PST 2009
Derek Parnell wrote:
> On Tue, 10 Feb 2009 14:01:29 -0800, Walter Bright wrote:
>
>> Derek Parnell wrote:
>
>>> ... it creates a new problem; code
>>> duplication.
>> I don't think that duplicating a small run of code is a problem.
>
>
> My apology. The problem is more than run-time performance issues. The more
> pressing problem, IMHO, is the one of maintenance costs. Duplicated code is
> a significant cost burden. Not only may each duplication require updating,
> but there is extra effort in analyizing every duplicate to see if it *does*
> need updating. And every act of updating increases the opportunity for
> introducing bugs.
Let's take an example, like the enum for O_XXXX in std.c.linux.linux.
Some of those values are common between platforms, and some are unique
to particular platforms. So you might be tempted to write:
enum
{
O_RDONLY = 0,
O_WRONLY = 1,
O_RDWR = 2,
O_CREAT = 0100,
version(OSX) O_SYMLINK = 0x200000,
}
instead of:
version (linux)
{
enum
{
O_RDONLY = 0,
O_WRONLY = 1,
O_RDWR = 2,
O_CREAT = 0100,
}
}
else version (OSX)
{
enum
{
O_RDONLY = 0,
O_WRONLY = 1,
O_RDWR = 2,
O_CREAT = 0100,
O_SYMLINK = 0x200000,
}
}
else
{
static assert(0); // need platform support
}
The first version is definitely shorter. But is it easier to maintain? I
argue that it is *harder* and *buggier* to maintain. Let's say I am
using linux and I need to add O_APPEND to it. I just stuff it in like:
enum
{
O_RDONLY = 0,
O_WRONLY = 1,
O_RDWR = 2,
O_CREAT = 0100,
O_APPEND = 02000,
version(OSX) O_SYMLINK = 0x200000,
}
and it works great for linux. Now I port my code to OSX, and it
mysteriously dies. After much frustration, I discover that O_APPEND for
OSX is 8, not 02000. (Yes, this kind of thing has happened to me. I only
found it by suspecting the problem, and then going through every fscking
definition comparing it to the one in the system .h file. Yeech.)
Now let's try the other way. I add O_APPEND to the linux branch, and
linux works great. Now I port to OSX, and the compiler dies with
"O_APPEND is undefined". I know immediately exactly what is wrong, look
up the .h file, and insert the right O_APPEND into the OSX version of
the declaration.
Furthermore, when I build a FreeBSD version, the compiler bings at me
for every declaration that needs some porting attention, instead of
silently using the wrong values.
This would be even better if the OSX and linux declarations were split
into separate "personality" modules. That way you can develop happily on
OSX without fear of accidentally breaking linux support. You can defer
dealing with the linux version until you actually on the linux machine
and are in an efficient position to take care of it.
> Coders need languages that help them do their job, and one way to help is
> to reduce the need for duplicated code.
I know there's a risk by getting in the way of programmers wanting to do
things a particular way. To do it, I have to be pretty convinced that
there is a better way. The C preprocessor is like crack, everyone knows
it's bad but they snort it anyway because it feels so good <g>. C++ was
supposed to get a bunch of features that obviate the preprocessor, but
have a look at the premier C++ library - Boost - which uses the
preprocessor heavily. Boost also uses every last iota of what the
preprocessor can do, because if your cpp implementation is not 100% most
of Boost will not compile (I know this from experience, DMC++ is 100% now).
>>> Duplicating (nearly all of a) source file is NOT, repeat NOT, a
>>> satisfatory solution.
>> I'm not insensitive to this as I do it myself in maintaining Phobos. It
>> is a problem, but not a huge one. I find that the meld utility (on
>> linux) makes this chore a snap.
>
> Because of D's limited support for text macros, I am using third party
> tools to get me out of this problem too.
meld is particularly nice. Andrei showed it to me:
http://www.linux.com/feature/61372
More information about the Digitalmars-d
mailing list