It's not a particularly bad habit to have to want to get output when debugging (the worse habit is to not debug).
Its just that we programmers are just so gosh darn lazy. Want output? Look there...
System.err.println("Got an error: " + e);
That's really easy. You don't need to worry about what logging framework you have, nor what log level it should be at. And this is why we do it all over.
But here's the thing... if you have a project of reasonable size, you have logging in it. If you don't, that's a bad habit. Once you have this logging, and it is something sensible (i.e. not java.util.logging
), its really easy to set up an appender that spits out to standard error.
And to this, there's not really an excuse why not to do it that way.
package c.s.p.m.logging;
import org.apache.log4j.Logger;
public class Main {
private final static Logger LOG = Logger.getLogger(Main.class);
public static void main(String[] args) {
LOG.debug("Oops");
LOG.info("This is awkward");
LOG.error("This is bad");
}
}
and (yep, I'm one of those oddballs that uses the xml format - note that this may not be the optimal one)
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j='http://jakarta.apache.org/log4j/'>
<appender name="console" class="org.apache.log4j.ConsoleAppender">
<param name="Target" value="System.err" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n" />
</layout>
</appender>
<appender name="file" class="org.apache.log4j.RollingFileAppender">
<param name="append" value="false" />
<param name="maxFileSize" value="10MB" />
<param name="maxBackupIndex" value="10" />
<param name="file" value="logs/someFile.log" />
<param name="threshold" value="ERROR" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern"
value="%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n" />
</layout>
</appender>
<logger name="c.s.p.m">
<level value="DEBUG" />
<appender-ref ref="console" />
</logger>
<root>
<level value="ERROR" />
<appender-ref ref="file" />
</root>
</log4j:configuration>
and there, in red on my console, I see:
2015-04-30 20:18:34 DEBUG Main:9 - Oops
2015-04-30 20:18:34 INFO Main:10 - This is awkward
2015-04-30 20:18:34 ERROR Main:11 - This is bad
Meanwhile, in my log file:
2015-04-30 20:18:34 ERROR Main:11 - This is bad
The thing is, there's not really an excuse if you've set it up to just use logging. It's a few more lines in the config file for the console appender.
Once you've got that as a habit to set it up, the logger is much better than System.err
ever was and you wonder what took you so long to step away from the println. Time stamps, log levels, line numbers... all for free. You'll find yourself stepping away from that console appender too with a little bit of time. You'll have different log files for different classes (and the aggregate log file too) with a log file watcher. You'll debate putting in crazy appenders...
And best of all, no more silly looks from co-workers because you accidentally checked in a System.err.println()
that filled up the console in production.
While System.err.println()
isn't bad and isn't a habit that you need to break (as long as you make sure you clean up after yourself and wash your hands afterwards), you will find that once you step away from it there are so many better options out there that are even fewer characters to type.
Best Answer
Well, if you've got access to an interactive debugger with breakpoints and watches and all, I'd suggest that. If you don't want an interactive debugger, how about a logging utility? Log4J is a good logger for Java apps, and there's a .NET equivalent as well (log4net).