views:

561

answers:

20

Sometimes for testing/developing purposes we make some changes in the code that must be removed in a production build. I wonder if there is an easy way of marking such blocks so that production build would fail as long as they are present or at least it will warn you during the build somehow.

Simple "//TODO:" doesn't really work because it is ofter forgotten and mixed with tons of other todos. Is there anything stronger?

Or maybe even if I can create some external txt file and put there instructions on what to do before production, and that ant would check if that file is present then cancel build.

We are using Eclipse/Ant (and java + Spring).

Update: I don't mean that there are big chunks of code that are different in local and production. In fact all code is the same and should be the same. Just lets say I comment out some line of code to save lot of time during development and forget to uncomment it or something along those lines. I just want to be able to flag the project somehow that something needs an attention and that production build would fail or show a warning.

A: 

Maybe if you mark those classes/methods as depricated, then they would be flagged during compilation time?

T Reddy
+5  A: 

Add a unit test that fails if the block is present. Maybe the block sets a global variable CODE_BLOCK_IS_NOT_DELETED = true; that the unit test checks for.

However, your bigger problem is that you test/develop with code that you don't need or use in production. That doesn't sound right.

Terry Lorber
That's really clever. I would never have thought of that.
Nathan Lawrence
Nice answer, it adds a feel to the code.
Secko
+2  A: 

One somehow dirty suggestion would be to create a class with a static method lets say

class Prod {
   public static void uction(){
   }
}

and then mark the places you want with

Prod.uction();

Then before production simply delete the class and you will get compiler errors where needed :D

Savvas Dalkitsis
Although this is dirty indeed, I don't agree with the downvote. It would actually help.
Jorn
seriously down vote? Boy are we grumpy today... Thank you Jorn.. (a vote up then might help :P )
Savvas Dalkitsis
I like the idea of this, can be used anywhere in the code, doesn't require access to the build system. Doesn't scale well above the individual, but meh, quick and dirty and your IDE can take you straight to the source of the problem. +1 :-)
Grundlefleck
A: 

For our production environments, we have a couple of simple C tools for stripping out sections using a very special comments. /*#BEGIN_SKIP*/ and /*#END_SKIP*/. Stick to standard C run-time, and you can compile on any environment.

You can change your entire build cycle to replicate the source code, transform it, and compile it.

MathGladiator
+1  A: 

TDD and Dependency Inversion concepts might help you here. By putting the code that varies into a class that implements an interface, you can control when the Test version of that code runs and when the prod version runs.

Then you have a file, clearly named as being for testing, that you can leave out of your build.

jlembke
A: 

I would try to avoid this as far as possible. - An alternative approach would be to use dependency injection to inject different implementations for testing.

Or...

Add an inTest boolean field to the objects and wrap the optional code in an if statement.

if(inTest) {
testMethod();
}

You could set this vboolean with dependency injection or read it from a passed in system property (-DinTest=true)

Hope this helps.

Pablojim
A: 

You can use a java preprocessor. For j2me applications I use antenna preprocessor. The code looks like this

public void someMethod() {
    //#ifdef DEBUG
    doDebugStuff();
    //#endif     
}
Daniel Moura
+11  A: 

Avoid the necessity. If you're placing code into a class that shouldn't be there in production, figure out how to do it differently. Provide a hook, say, so that the testing code can do what it needs to, but leave the testing code outside the class. Or subclass for testing, or use Dependency Injection, or any other technique that leaves your code valid and safe for production, while still testable. Many such techniques are well-documented in Michael Feathers' fantastic book, Working Effectively with Legacy Code.

Carl Manaster
A: 

Eclipse allows for other markers than just //TODO, you can add, for example, //TOBEREMOVED and give it a high priority, so it shows up before all the other TODO markers.

Jorn
It would be perfect solution if I can somehow check if those exist from Ant.
serg
it shouldn't be that hard to check it from Ant
Carlos Heuberger
A: 

The obvious way to solve this is to have a unit test that only runs on the production build (or checks if the current build is production and runs the test if it is) and fail the build if the test fails.

You won't ever forget. In terms of what kind of test, ideally it would actually check for whatever the code does. If this is not possible, then a global static as Terry Lorber suggested would be a lot better than what you have now.

Yishai
A: 

Just add some //TODO: -- then make a c# script (cs-script.net) which looks for //TODO in your code and displays them. You can then add this script to your automated builds (if you're doing that), so each time you do a build, you can see what there is to do. Review your code's todo list before deploying.

Alternatively to writing your own script, there's some instructions on how to integrate vstudio with some tool that points out your todo lines as well: http://predicatet.blogspot.com/2006/12/show-all-tasks-in-visual-studion-2005-c.html

However, it seems to me, setting up that tool is more of a pain than writing a simple C# script with a regex.

A: 

In projects I've worked on, I've had various tidbits of code that are in place to enable easy testing during development. I wrap these in an if block that checks a final boolean. When the boolean is true, the code can be accessed. When the boolean is false, I depend on the compiler removing the code from the resulting .class files as an optimization. For instance:

public class Test {
    public static void main(String[] args) {
     final boolean TESTABLE = true;

     if (TESTABLE) {
      // do something
     }
    }
}

Typically, I manage these variables on my own, using them during development and setting TESTABLE to false when I'm done. A development team could easily agree to a convention for variable names, like TESTABLE, and the build file's production target could check for and fail if any source files had a TESTABLE variable = true.

dcoke23
+10  A: 

You could also just define stronger task comment markers: FIXME (high priority) and XXX (normal priority) are standard in Eclipse, and you could define more task tags (Eclipse Properties -> Java -> Compiler -> Task Tags)

If you want to fail your build, you could use the Ant (1.7) contains file selector to look for files containing specified text:

<target name="fixmeCheck">
  <fail message="Fixmes found">
    <condition>
      <not>
        <resourcecount count="0">
          <fileset dir="${pom.build.sourceDirectory}" includes="**/*.java">
             <contains text="FIXME" casesensitive="yes"/>
          </fileset>
        </resourcecount>
      </not>
    </condition>
  </fail>
</target>

<target name="compile" depends="fixmeCheck">

Obviously, change ${pom.build.sourceDirectory} to your source directory, and FIXME to the comment that you want to search for.

Does anyone know a nice way to print out the files found in this fileset in the build file (other than just looking in Eclipse again)?

paulcm
A: 

I use the //FIXME keyword that eclipse displays, together with //TODO, in the Tasks View (you can filter what to see on it). You shouldn't go out to production if there is some //FIXME around :)

diega
A: 

In addition to all the above suggestions (what's with all the manual crap and adding cruft to the code? automate things people...), I notice that you're using Eclipse, Spring, and ANT. Eclipse supports multiple source folders - separate your code out into a "source" and "testing" folder, put anything for production in the source folder and put anything "not production" in the testing folder. Spring allows you to have multiple configurations that reference different implementations - so you can have a production configuration that references classes only in production, and testing configuration(s) to run with your testing code. Have the ANT script build the production and testing versions of your app - for testing add the "testing" folder to your compile path, for production leave it off. If a class references a testing class from production you'll get a compile error - if a production Spring configuration references a class from testing in production, it will fail as soon as it tries to load it.

Nate
A: 

My solution is to work on two seperate branches of code. One production branch which only gets clean code without any debugging code and another (Sometimes I even have several of these) for testing, debugging, trying new struff etc.

In eclipse these are separate projects (or groups of projects).

Mercurial is a nice VCS for this type of work but CVS and subversion are good too.

+2  A: 

However you technically solve this, I would recommend to do it the other way round: do not do something special for the production build but structure your code and build environment in such a way that the magic happens during the development build. The production build should be as foolproof (or Murphy proof) as possible.

If something goes wrong in the development build: so what.

Anything going wrong in the production build will hurt much more.

jdisk
+2  A: 

[edit:] Works for C++... :-)

Use these preprocessor defintions and all your problems will be solved:

#ifdef _DEBUG
#define COMMENT (code)  /* code */
#else
#define COMMENT (code) #error "Commented out code in release!"
#endif

Not sure if the syntax is entirely correct, but you get the idea.

Danra
I've done a similar thing in Java using private static final boolean DEBUG = true. I believe the compiler will optimise away blocks of test code within if (DEBUG) { ... statements if DEBUG is set to false.
Adamski
A: 

I do not have an answer, but I wondered if annotations could be used for this?

Or perhaps, have them in a separate project, which is linked in in the test ersion but not in the production version. This would require the production versino to be built by a continuous integration server separate from the developers.

Thorbjørn Ravn Andersen
+1  A: 

We added a trigger to subversion that blocks \\NOCOMMIT: You could have a \\NODEPLOY: tag that your build script would look for before allowing a build.

Konrad