informat IDE survey

M

Mike Schilling

Daniele Futtorovic said:
Not even that. Not unless you can simulate all the logical branches
(which, incidentally, means doing your stepping through 2^n times, with
n being the number of branchings),

If they're two-way branches :)
in which case you'd have written a
unit test and might as well give it a run for itself and see in one go
whether there's a problem in the first place.

But if you want to check whether, for instance, your logic for exiting a
loop early works, you're not going to get with with a JUnit-type "is the
result right?" test. You may find it much later when analyzing performance,
but that won't be cheap.
 
M

Martin Gregorie

Sounds cool. But what if you want to have logging statements so as to
affirm that some expected thing happened?
If you have logging statements to report that stuff has happened then
that would go into the buffer.

Similarly, I'd expect your logging system could turn buffering on or off
at run time as well as setting a logging level level filter. I usually
control this via command line options but I might make it settable on a
server via a control and monitoring client as well.

My current Java tracing class provides an error() method, which outputs a
message and stops the run and a trace() method which can be used for,
err, tracing and debugging. All output goes to stderr but the tracing
level control is done via conditionals in the program because that saves
to overhead of an essentially null call method call when tracing is off.

I'm not currently using a circular buffer, but slotting it into the
tracing class and making calls of error() trigger a buffer dump are
obviously trivial to implement. I'd also make the buffer size
configurable and add a dump() method so I could also force a buffer dump
without needing a fatal error to trigger it. I might also add a clear()
method so that, e.g. a program could clear the buffer at the start of
each cycle round the main loop.
 
D

Dirk Bruere at NeoPax

I'm curious what people are using as their IDE to write Java code.
The biggies used to be Eclipse, NetBeans and IntelliJ. What are they
now? What are you using?

Forced to use Eclipse by Android
 
M

markspace

Sounds cool. But what if you want to have logging statements so as to
affirm that some expected thing happened?


I haven't actually tried to build such a thing, but Java logging has a
circular buffer built in (MemoryHandler) as well as the more standard
console and file handlers.

I would probably start by having two handler, one MemoryHandler and one
FileHandler. Set the priority on the FileHandler to "normal" levels --
Severe, Warning, Config, Info. If you want to "know that something
happened", write it out with one of those levels.

At the same time set the MemoryHandler to a much lower level, say
"Finer" or similar. When something does happen, dump the MemoryHandler.
Then you'll have both standard logs and the recent log of events just
before the event of interest. This seems to be what Martin is talking
about.
 
L

Lawrence D'Oliveiro

Daniele Futtorovic said:
It's either one or the other, lad. You can't see the big picture when
you've got to focus on writing the small one.

Are you admitting you can’t type and think at the same time?
 
L

Lawrence D'Oliveiro

The main Java IDEs have macros in a true sense of the term. You haven't
found them yet?

Macros are just a quick convenience. For anything more complicated, I want a
proper scripting language. Which Emacs has.
 
D

Daniele Futtorovic

I haven't actually tried to build such a thing, but Java logging has
a circular buffer built in (MemoryHandler) as well as the more
standard console and file handlers.

I would probably start by having two handler, one MemoryHandler and
one FileHandler. Set the priority on the FileHandler to "normal"
levels -- Severe, Warning, Config, Info. If you want to "know that
something happened", write it out with one of those levels.

At the same time set the MemoryHandler to a much lower level, say
"Finer" or similar. When something does happen, dump the
MemoryHandler. Then you'll have both standard logs and the recent log
of events just before the event of interest. This seems to be what
Martin is talking about.

Sounds really good, actually. I'm starting to like this.

Okay, but this does presuppose that you have one, or some very few, core
places to your application where things are run in some kind of loop and
where you can catch 'interesting events', doesn't it? I mean, you have
to trigger the dump somehow.
 
D

Daniele Futtorovic

Are you admitting you can’t type and think at the same time?

I'm claiming that on average neither I nor you nor anyone else can
concentrate on writing a specific line of code and at the same time on
the overall architecture that line of code is part of. It's like the
forest and the trees.
 
M

markspace

Okay, but this does presuppose that you have one, or some very few, core
places to your application where things are run in some kind of loop and
where you can catch 'interesting events', doesn't it? I mean, you have
to trigger the dump somehow.


Yes. I can think of two ways to do it, off hand. One would be to have
some sort of ad-hoc mechanism. You add some code to a known problem
area to call a "dump" method which triggers the MemoryHandler.

The second way I think would be to have some general mechanism. You
could try a logging Handler that, instead of logging (or in addition to
logging) also triggered the MemoryHandler when it gets a specific level
or type of Exception. You'd have to write such a class specially, but
once you did you'd have some flexibility to attach it to problem areas
wherever they are found, without having to modify code and recompile.
 
D

Daniele Futtorovic

Yes. I can think of two ways to do it, off hand. One would be to have
some sort of ad-hoc mechanism. You add some code to a known problem
area to call a "dump" method which triggers the MemoryHandler.

The second way I think would be to have some general mechanism. You
could try a logging Handler that, instead of logging (or in addition
to logging) also triggered the MemoryHandler when it gets a specific
level or type of Exception. You'd have to write such a class
specially, but once you did you'd have some flexibility to attach it
to problem areas wherever they are found, without having to modify
code and recompile.

Yes, this second one is the one I've been thinking about in the
meantime. Extremely neat and powerful. I think that's what I'm gonna
write tomorrow. Although I think I'll make the MemoryHandler attachable
to the Thread or the ThreadGroup...

Should be a lot of fun! Thanks for the inspiration to you, markspace and
Martin.
 
M

markspace

Yes, this second one is the one I've been thinking about in the
meantime. Extremely neat and powerful.


Here's what I came up with. Note that after checking the docs, I
noticed that MemoryHandler will self-push if its pushLevel is met or
exceeded. So if that's all the functionality you need you have it in
one class already.

The code below is completely untested.


package test;

import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.LogManager;
import java.util.logging.LogRecord;
import java.util.logging.Logger;
import java.util.logging.MemoryHandler;

/**
*
* @author Brenden
*/
public class TriggerHandler extends java.util.logging.Handler {

public TriggerHandler() {
setLevel( Level.SEVERE );
String slevel = LogManager.getLogManager().getProperty(
"logging.config.memorydump.trigger.level");
try {
Level level = Level.parse(slevel);
setLevel( level );
} catch( IllegalArgumentException ex ) {
// bail, log this?
}
}


@Override
public void publish(LogRecord record) {
if( record.getLevel().intValue() >= getLevel().intValue() ) {
String logger = LogManager.getLogManager().getProperty(
"logging.config.memorydump.logger");
if( logger == null ) {
logger = ""; // root logger
}
Handler[] handlers = Logger.getLogger(logger).getHandlers();
for( Handler h : handlers ) {
if( h instanceof MemoryHandler ) {
MemoryHandler mh = (MemoryHandler)h;
mh.push();
mh.flush();
}
}
}
// Assume parent handlers will be invoked.
}

@Override
public void flush() {
}

@Override
public void close() throws SecurityException {
}

}
 
R

Roedy Green

Single-stepping through newly-written code is an excellent way to determine
whether it's working as designed, or getting what looks like the right
answer for the wrong reason.

I get in trouble thinking code is working just because the results
look plausible. If I single step through some of the complicated
bits, bugs show up when I see behaviour that is not expected, even if
it does not lead to palpably wrong output.

One of the bugs I am discovering hides longest is writing regex
patterns that find only 99% of the instances they should. Often the
problematic case does not exist anywhere at the time I write the code.
It only shows up later.

You pretty well have to create a set of pathological examples and run
tests with them.
 
A

Arved Sandstrom

Macros are just a quick convenience. For anything more complicated, I want a
proper scripting language. Which Emacs has.

I won't deny that. But let's look at the original terms of reference for
this thread, which I'm trying to stick to: IDE's for writing Java code.
That context is why, for example, I'm skeptical of the advantage of
being able to squeeze out every last bit of ergonomic speed in typing -
we're writing *code*.

As for scripting of the IDE, the real discussion there is about the
ability to extend the capability of the IDE. In Emacs you do it one way,
in the main Java IDEs you do it other ways (although you can consider
"scripting" languages also).

Eventually you'll change the requirements to the extent that only Emacs
can satisfy them...like "editor must be extensible and customizable with
Emacs Lisp".

AHS
 
L

Lew

I won't deny that. But let's look at the original terms of reference for
this thread, which I'm trying to stick to: IDE's [sic] for writing Java code.
That context is why, for example, I'm skeptical of the advantage of
being able to squeeze out every last bit of ergonomic speed in typing -
we're writing *code*.

Implicit in your point is the necessity to think whilst coding.

If one uses the hundred-monkeys approach (bang at the keyboard enough and
you'll wind up with Shakespeare, or at least some code you can give to your
manager) then yes, typing speed is more important.
As for scripting of the IDE, the real discussion there is about the
ability to extend the capability of the IDE. In Emacs you do it one way,
in the main Java IDEs you do it other ways (although you can consider
"scripting" languages also).

Eventually you'll change the requirements to the extent that only Emacs
can satisfy them...like "editor must be extensible and customizable with
Emacs Lisp".

"No true Scotsman".
 
N

Nigel Wade

Pressing CTRL/S to start a search, typing the search string, then repeating
CTRL/S to step forward through all instances or CTRL/R to step backward.

and that's where Emacs falls flat on its face. CtrlsS is XOFF on a
serial link. I know it can be re-mapped, but then you usually end up
with different keymaps on different systems, and since Emacs is entirely
keymap based it becomes very, very confusing.

Press Enter to leave the point at the desired location, or CTRl/G to abandon
the search.

and using search in an IDE is just as simple and quick. With many added
benefits.
Pressing CTRL-X ( to start defining a macro, CTRL-X ) to finish it, then
CTRL-X e to execute it, e to execute again, repeat, repeat.

You need to spend time learning how to use an IDE.
Having multiple clipboards with CTRL/X r s 1, CTRL/X r s 2 etc.

is a messy hack.
Being able to execute a shell command and insert its output directly into a
text buffer.

is of very little advantage in windowed systems. On the very rare
occasions I need to do that I just type the command into a shell, select
the required portion of the output, and click the middle mouse button in
the IDE to paste the contents.
Basically, being able to type as fast as you can think.

is in general a bad idea. It just encourages you to type without
thinking through the consequences of what you are typing.
 
D

Daniele Futtorovic

Here's what I came up with. Note that after checking the docs, I noticed
that MemoryHandler will self-push if its pushLevel is met or exceeded.
So if that's all the functionality you need you have it in one class
already.

My company's code is tied to log4j. Since I already have my trusted
logging layer for that...

public static void log( Logger logger, Level level, Throwable t, String
format, Object... args ){
if( level.isGreaterOrEqual(logger.getEffectiveLevel()) ){
logger.log( level, String.format(format, args), t );
}
}

.... I took another approach. I installed a ThreadLocal circular buffer,
its contents instances of a subclass of log4j's LoggingEvent (to avoid
doing the String#format needlessly). Then, when the log method above is
called: if it doesn't pass the level, it goes into the buffer;
otherwise, if it's Level.ERROR, the contents of the buffer are logged;
fi; then the statement is logged; fi.

I'm going to have a look how it works out in practice, but first results
were pleasing. Considering the standard production mode where little
is logged under normal circumstances, I get the full monty when
an error occurs. Kinda of the best of two worlds: no unnecessary
clutter, and all the details I need when it matters. In development, the
level is on full, of course.

It's still a bit shaky to my liking, but as far as I can see the
pernicious idiom:

if( logger.isMyLevelEnabled() )
logger.myLevel( message )

prohibits anything more solid.

The code below is completely untested.


package test;

import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.LogManager;
import java.util.logging.LogRecord;
import java.util.logging.Logger;
import java.util.logging.MemoryHandler;

/**
*
* @author Brenden
*/
public class TriggerHandler extends java.util.logging.Handler {

public TriggerHandler() {
setLevel( Level.SEVERE );
String slevel = LogManager.getLogManager().getProperty(
"logging.config.memorydump.trigger.level");
try {
Level level = Level.parse(slevel);
setLevel( level );
} catch( IllegalArgumentException ex ) {
// bail, log this?
}
}


@Override
public void publish(LogRecord record) {
if( record.getLevel().intValue() >= getLevel().intValue() ) {
String logger = LogManager.getLogManager().getProperty(
"logging.config.memorydump.logger");
if( logger == null ) {
logger = ""; // root logger
}
Handler[] handlers = Logger.getLogger(logger).getHandlers();
for( Handler h : handlers ) {
if( h instanceof MemoryHandler ) {
MemoryHandler mh = (MemoryHandler)h;
mh.push();
mh.flush();
}
}
}
// Assume parent handlers will be invoked.
}

@Override
public void flush() {
}

@Override
public void close() throws SecurityException {
}

}
 
R

Roedy Green

Flipping back and forth between what? Emacs runs on Windows and,
with cygwin's bash shell, it's almost a not unpleasant development
environment.

Emacs and CUA user interfaces.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,774
Messages
2,569,599
Members
45,171
Latest member
VinayKumar Nevatia__
Top