This discussion is archived
7 Replies Latest reply: Feb 2, 2011 12:53 AM by jwenting RSS

Equivalent to C's #ifdef

835709 Newbie
Currently Being Moderated
I'm trying to solve a development problem. In C, this would be solved by using #ifdef.

Basically, I have huge chunks of code that are experimental replacements for existing code. I want to enable this experimental code while developing, but I want to ensure that the tested algorithms are used when building a release jar.

Much of the searching I've done online recommends using "final static" variables. This does not solve the problem, though, because our developers have to manually flip the values of these variables around when developing, then flip them back when checking in to our central code repository, which opens up way too many opportunities for mistakes.

Another suggestion that has been made is to use System.getProperty() to extract the desired behavior from environment variables at run time. This doesn't solve the problem either, since I can't then compile a jar and hand it to a non-technical person to test -- I have to provide them with instructions or some other nonsense to get their environment variables set up properly first, which is error-prone even with technical people, but even more so with non-technical testers.

No. I'd prefer to have an easy way to ensure that a particular jar is only capable of running one of the algorithms. What I need to really do this right is the equivalent of C's #ifdef. I want each developer to set an environment variable in his/her IDE once, and ensure that they're always compiling with the algorithms that are under development. And I want our dedicated environment for building production jars to have an environment variable set that guarantees that it always builds with the production algorithms. In a perfect world, the unused code wouldn't even be included in the final .class files, to keep the size of the resultant jar smaller, but that's not strictly necessary.

I could use either of the two presented options ... both will get the job done (although less cleanly, and with more possibility of error). If there really is no better way, the environment variable and System.getProperty() are probably the closest, but I'm hoping that I'm just searching poorly and that there IS a better solution.

Any thoughts?
  • 1. Re: Equivalent to C's #ifdef
    tschodt Pro
    Currently Being Moderated
    832706 wrote:
    A suggestion that has been made is to use System.getProperty() to extract the desired behavior from environment variables at run time.
    You do not get env.var. content with getProperty().
    C:\> set foo.bar="environment variable"
    System.out.println(System.getenv("foo.bar"));
    
    c:\> java -Dfoo.bar="property value"
    System.out.println(System.getProperty("foo.bar"));
    Any thoughts?
    A configuration file.
  • 2. Re: Equivalent to C's #ifdef
    796440 Guru
    Currently Being Moderated
    This sounds like a job for a version control system.

    Java does not have an #ifdef per se, but you can use the C preprocessor on Java files. I recommend very strongly against this approach however. Just use proper source code control.
  • 3. Re: Equivalent to C's #ifdef
    800554 Newbie
    Currently Being Moderated
    Sometimes I suppose it would be handy to have a preprocessor in Java. Then again, having something go through your code and replace parts of it just seems error-prone. Even if it works, you still have to worry about what the real code is that's passed to the compiler - the preprocessor output. I'm guessing that's why the designers of Java decided not to have a preprocessor. The code you write is what gets compiled.
    If you want to enable or disable parts of the code, why not just have a global constant that changes based on parameters passed into the main program? Just read the args[] string in the main method and if it contains say "--debug" then set the global debug flag otherwise disable it.
    And I don't think System environment variables are that bad. Testers should have some idea what environment variables are set. You do have to jump through a bit more hoops in Windows 7 compared to previous versions of Windows (on *nix systems it's even easier - you just set the variable, perhaps in the startup script), but after doing it a few times it won't be that big of a deal. 
    If it's a debug flag specific to the program then it probably makes more sense to pass it as a parameter. If you want to have the system itself in a debug/release mode, then the Environment variable probably makes more sense.
  • 4. Re: Equivalent to C's #ifdef
    796440 Guru
    Currently Being Moderated
    radtad82 wrote:
    Sometimes I suppose it would be handy to have a preprocessor in Java. Then again, having something go through your code and replace parts of it just seems error-prone.
    PLUSPLUS!
  • 5. Re: Equivalent to C's #ifdef
    tschodt Pro
    Currently Being Moderated
    832706 wrote:
    Any thoughts?
    You could possibly use assertions.
    The [url http://java.sun.com/docs/books/jls/third_edition/html/statements.html#14.10]JLS describes how a boolean primitive is silently assigned 'true' as a side effect of evaluating an assertion,
    as well as describing possible pitfalls.
    Personally I am not entirely convinced this is a good way to use assertions.

    And still you would face the same issue of having your testers run with assertions enabled.

    Delivering your application.jar along with
    an application.bat file for normal running, and
    an applicationBeta.bat for your testers to test algorithms under development
    should solve this regardless of what mechanism you opt for.
  • 6. Re: Equivalent to C's #ifdef
    835709 Newbie
    Currently Being Moderated
    Thanks to everyone for all the suggestions. To be honest, I'm not really comfortable with any of them, perhaps I just have the C way of doing things too hardwired in my head, but in any event I have a number of things to try, and figure out which one seems to work best for us.

    If anyone is curious, I've started another thread to address a related issue:
    Convincing JAX-WS to ignore all certificate problems
  • 7. Re: Equivalent to C's #ifdef
    jwenting Journeyer
    Currently Being Moderated
    radtad82 wrote:
    Sometimes I suppose it would be handy to have a preprocessor in Java. Then again, having something go through your code and replace parts of it just seems error-prone. Even if it works, you still have to worry about what the real code is that's passed to the compiler - the preprocessor output. I'm guessing that's why the designers of Java decided not to have a preprocessor. The code you write is what gets compiled.
    Have done it at times using ANT scripts to replace markers in a source with actual content from its configuration files.
    Mainly on things like server-specific WSDL variations and autogeneration of configuration files for different environments to be included in ear files.

    Not a perfect solution maybe, but IMO beats having to go in and manipulate files in an ear or worse, on a production server, by hand as part of each deployment process.

Legend

  • Correct Answers - 10 points
  • Helpful Answers - 5 points