Am 14.03.2014 19:50, schrieb H. S. Teoh:
On Fri, Mar 14, 2014 at 07:29:27PM +0100, Paulo Pinto wrote:
Am 14.03.2014 19:06, schrieb Iain Buclaw:
On 14 March 2014 17:53, Walter Bright <newshou...@digitalmars.com> wrote:
On 3/14/2014 10:26 AM, Johannes Pfau wrote:

I use manifest constants instead of version identifiers as well. If
a version identifier affects the public API/ABI of a library, then
the library and all code using the library always have to be
compiled with the same version switches(inlining and templates make
this an even bigger problem). This is not only inconvenient, it's
also easy to think of examples where the problem will only show up
as crashes at runtime.  The only reason why that's not an issue in
phobos/druntime is that we only use compiler defined versions
there, but user defined versions are almost unusable.


Use this method:


     --------
     import wackyfunctionality;
     ...
     WackyFunction();
     --------
     module wackyfunctionality;

     void WackyFunction() {
         version (Linux)
           SomeWackyFunction();
         else version (OSX)
             SomeWackyFunction();
         else
             ... workaround ...
     }
     --------


Some years down the line (and some platform testing) turns into:

--------
module wackyfunctionality;

void WackyFunction() {
     version (Linux) {
         version (ARM)
             _SomeWackyFunction();
         else version (MIPS)
            MIPS_SomeWackyFunction();
         else version (X86)
            SomeWackyFunction();
         else version (X86_64)
            SomeWackyFunction();
         else
           ... should be some wacky function, but workaround for general case 
...
     }
     else version (OSX) {
         version (PPC)
            iSomeWackyFunction();
         else
            SomeWackyFunction();   // In hope there's no other Apple hardware.
     }
     else version (OpenBSD) {
       /// Blah
     }
     else version (Haiku) {
       /// Blah
     }
     else
         ... workaround ...
}
--------



That is why the best approach is to have one module per platform
specific code, with a common interface defined in .di file.

+1. Once versioned code gets more than 2 levels deep, it becomes an
unreadable mess. The .di approach is much more manageable.


Back on my C/C++ days at work, any conditional code would be killed
by me during code reviews.
[...]

Ah, how I wish I could do that... over here at my job, parts of the code
are a nasty rats'-nest of #if's, #ifdef's, #ifndef's, and "functions"
that aren't defined anywhere (they are generated by macros, including
their names!). It used to be relatively sane while the project still
remained a single project... Unfortunately, about a year or so ago, the
PTBs decided to merge another project into this one, and by "merge" they
meant, graft the source tree of the other project into this one, hack it
with a hacksaw until it compiles, then call it a day. We've been
suffering from the resulting schizophrenic code ever since, where some
files are compiled when configuring for platform A, and skipped over and
some other files are compiled when configuring for platform B (often
containing conflicting functions of the same name but with incompatible
parameters), and a ton of #if's and #ifdef's nested to the n'th level
got sprinkled everywhere in the common code in order to glue the
schizophrenic mess into one piece. One time, I spent almost an hour
debugging some code that turned out to be inside an #if 0 ... #endif
block. >:-(  (The real code had been moved elsewhere, you see, and
whoever moved the code "kindly" decided to leave the old copy in the
original file inside an #if 0 block, "for reference", whatever that
means. Then silly old me came along expecting the code to still be in
the old place, and sure enough it was -- except that unbeknownst to me
it's now inside an #if 0 block. Gah!)


T



Ouch! I feel your pain.

This type of experience is what lead me to fight #ifdef spaghetti code.

--
Paulo

Reply via email to