Lazy construction of parameters

W

Wibble

Piotr said:
So what about line like this:

logger.logWarningIf(entry == null
&& logger.setMessage("No entry found in storeEntries for
arcfilename: " + arcfileName));


Thanks to use of Java '&&' operator second operand will be computed only
when the first one is true. As the result no message build is performed
unless really needed.


In this case Logger must buffer your message before commitment of the
printout, like in the following example:


public class Logger {

private String message;

public void logWarningIf(boolean needToLogIt) {
if (needToLogIt) {
System.out.println("warning: "+ message);
}
}

public boolean setMessage(String msg) {
message = msg;
return true;
}

}

P.S.

I've never used it, my preference is classic if (...) { log... }
scenario, and honesty saying I can't see any reason to switch to
something else.


Regards,
piotr

And of course don't make that Logger a singleton since its not
thread safe.
 
W

Wibble

Eric said:
The pre-existing syntax looks pretty simple to me ...

One way to repackage so while avoiding the potentially
expensive message construction would be

LogWarning.ifNull(entry,
new Object() {
public String toString() {
return "No entry found ... "
+ arcfileName
+ expensiveStuff();
}
}
);

Note that arcfileName would need to be final in this
scenario. Note also that it always constructs an Object,
even if it then does nothing but throw it away -- one
supposes that the Object construction is cheaper than the
database queries and such that go into building the message
itself.

I really don't think this would be an improvement over
the original -- all this foofaraw just to relocate an `if'?
But there's no point arguing with Gus, as the old saying
has it. ;-)
Thats alot of hair to avoid saying 'if (blah) print'.
Also, if blah is a final boolean, java can
just compile out the whole print form.

Perhaps this is best left a problem not solved.
 
D

dduck

Well, I don't know...

As a relative newcomer to Java-in-the-wild (as opposed to
Java-in-the-academia or C++-up-the-wazoo), I don't find the
(apparently) common Java ideom of:

Logger logger = Logger.getLogger(<some magic here>);
<...>
if (condition) {
logger.warning(<message>);
}

....particular transparent. It's a lot of typing that locks
functionality locally with no obvious way to interject run-time
filtering of logging (besides hacking something into the logger chain).
Why not make a helper method as a shorthand?

I know... I am in the "relentless refactoring for brevity" camp here,
and there are other valid points of view. Still, this happens a lot in
our 40 K line code base, so every saving of 3 lines + improvement of
clarity can probably be multiplied with a factor of at least 100 when
evaluating the effect. Of course it should be balanced by an
appreciation of the effort involved in refactoring the old ideom and
the potential impact on performance and/or stability.

This discussion parallels the one currently taking place in our
collaborative work, and so I value comments, experiences and insights -
please feel free to contribute.

Anders
 
P

Piotr Kobzda

Wibble said:
And of course don't make that Logger a singleton since its not
thread safe.

I didn't presume it. Logging is done using Logger instance and there is
no limitation in creation as many Logger instances as needed.

Anyway, if someone wish to use a singleton instance, the simple solution
to make it thread safe is to use ThreadLocal for message buffer like this:

ThreadLocal<String> message = new ThreadLocal<String>();


Regards,
piotr
 
J

Jean-Marie Gaillourdet

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Hi,
@Bart:

Neat solution. In effect, you are building a higher-order function, and
then defer invocation. Thought about doing something like that, but
didn't have the Java skills yet - I am still in transition from C++,
where I'd just use the preprocessor for this...

I had a similar problem to yours in our theorem prover with an unparser.
I preferred to extend my unparser with lazy unparse methods and
combine it with message format logging methods.

class MyLogger extends Logger {
public void infof(String messageFormat, Object... args) {
return String.format(messageFormat, args)
}
}

class MyUnparser {
String unparse(Formula f) {
...
}

Object unparseLazy(Formula f) {
return new Object {
public String toString() {
return unparse(f);
}
}
}
}

So applications have the following form:

....
logger.infof("Bla bla %s\n", unparser.unparserLazy(f));
....

instead of

logger.info("Bla bla %s" + unparser.unparser(f) + "\n");

Note: The condition is hidden in info and depends on the global logging
configuration in my case.

Regards,
Jean-Marie
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.1 (GNU/Linux)
Comment: Using GnuPG with Thunderbird - http://enigmail.mozdev.org

iD8DBQFEF+P5NIUNP/I5YOgRAmDlAKDQio3owoCI6JdYZLFli56Lmnfe5QCfWcdo
2nX0I8G4FP1lbKsCqGejZUM=
=VI1S
-----END PGP SIGNATURE-----
 
C

Chris Uppal

dduck said:
Elapsed ms 750
Elapsed ms 32

..for false condition (no logging) and: [...]
Comments?

This sort of benchmarking should really take account of the behaviour of the
JIT, but still, taking the above as best case figures, it's questionable
whether a saving of less than a second for a million logging calls is really
worthwhile.

Of course, the saving is unbounded if you consider more complex code to supply
the parameters to the call, but I don't think that expressing arbitrary
computation really fits into this framework (or into any other framework
expressible conveniently in Java).

-- chris
 
C

Chris Uppal

dduck said:
...particular transparent. It's a lot of typing that locks
functionality locally with no obvious way to interject run-time
filtering of logging

Agreed.

Ultimately, though, I think you are going to hit the problem that Java just is
not expressive enough to do this properly. In which case it might be better to
settle for a pattern where /every/ log statement is expressed as a conditional:

if (Logger.shouldLog(... something...))
Logger.log(...something else....)

That at least gives you somewhere to introject system-wide filtering without
having to find and change every line of logging in the entire code-base.

Yes, it's less that ideal . It's poor structuring. It's verbose. It violates
the "don't ask, tell" slogan of OO programming. And, maybe it's less
efficient than it might be. But that's what you get when the language is
underpowered....

-- chris
 
J

Jens Auer

dduck said:
...particular transparent. It's a lot of typing that locks
functionality locally with no obvious way to interject run-time
filtering of logging (besides hacking something into the logger chain).
Why not make a helper method as a shorthand?

I know... I am in the "relentless refactoring for brevity" camp here,
and there are other valid points of view. Still, this happens a lot in
our 40 K line code base, so every saving of 3 lines + improvement of
clarity can probably be multiplied with a factor of at least 100 when
evaluating the effect. Of course it should be balanced by an
appreciation of the effort involved in refactoring the old ideom and
the potential impact on performance and/or stability.
Logging is the standard example of aspect-oriented programming, which
handles cross-cutting concerns like this and puts them into their own
entity. You might want to have a quick look at AspectJ, a Java
implementation of aspect-oriented programming.
 

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

No members online now.

Forum statistics

Threads
474,436
Messages
2,571,696
Members
48,796
Latest member
Greg L.
Top