Tuesday, February 1, 2011

Against any dogmatic approach

I am just against any dogmatic approach to anything.

Because dogmatic approaches do not work. If they did even AI might eventually succeed (I no longer believe in it).

Because it is arrogant and maybe ignorant to even suggest or advice a dogmatic approach to others.

This is a dogmatic approach? Then this is the only viable exception :)

Monday, January 24, 2011

Parsing very simple expressions in Java

You might say parsing such a simple expression

function(param1, param2)
(and the like) is easy even if you want escaping of special characters and quoted parts. At least that's what I said.

Obvious approaches include using standard Java classes
  1. StringTokenizer
  2. Scanner
  3. Regular Expressions (sometimes coming in disguise as direct String methods like String.split)
  4. Use a lexer generator like http://www.cs.princeton.edu/~appel/modern/java/JLex/ or http://jflex.de/
  5. Using a full parer generator like http://www.antlr.org/
  6. doing this by hand using low level String functions, e.g. indexOf and substring
  7. remember your C days and still do this by hand, but rather by iterating through the input character by character
What did I do?
  • Options (1) and (2) do not work as they are not powerful enough, especially when it comes to escaping. Besides they are slow
  • Option (3) might acutally work, but besides being slow, dealing with complex regular expressions and the Java API for it is something I can not recommend. Even after reading and groking this tutorial would you want to write and maintain regular expressions? Try it. I don't.
  • (4) and (5): Having the full burden of a generated lexer plus runtime libraries or even a full generated parser is hardly worth the effort considering the simplicity of the expressions, even though both approaches would solve the problem.
Which leaves me doing it by hand - which I wound up doing. First I persued option (6) which did the job, but resulted in code very hard to read and very hard to maintain.

I then turned to option (7) and things became both easy and fast. I even came up with a very simple utility class that not only handles the above case, but other similar inputs. This is a test case for that utility class

@Test
public void scanAndSplit() throws Exception {
String input = "function(param1, param2)";
List segments = MiniParser.defaultInstance().scan(input, "(", ")");
assertEquals(2, segments.size());

String functionName = segments.get(0);
String parameterString = segments.get(1);
assertEquals("function", functionName);
assertEquals("param1, param2", parameterString);
List parameters = MiniParser.trimmedInstance().split(parameterString, ',');
assertEquals(2, parameters.size());
assertEquals("param1", parameters.get(0));
assertEquals("param2", parameters.get(1));
}

Java byte code generation

To speed up template processing for our template engine I recently decided to optionally compile each template into byte code.

Looking for a library to help me I chose ASM, because it
  1. is small with no dependencies
  2. has been released lately
  3. has decent documentation
  4. has a tool (Eclipse plugin) that generates ASM API calls from existing byte code
Especially no 4 inspired me to do the following:
  1. Create a fistful of hand crafted Java classes that do the same as some selected templates
  2. Create ASM code that generates the same byte code as those Java classes by the tool described in no 4
  3. Create a recursive descent compiler that calls the generalized ASM code derived from step 2 that generates the desired byte code
  4. Load and cache the classes at runtime
It turned out to be a pretty viable approach and allowed me to finish my task without too much knowledge of Java byte code. And what I had to learn anyway was quite enlightening :)

Even though a lot of code remains to be dynamic, because I do not know what will be in the model at run time, the caliper micro benchmarks comparing uncompiled reference code against the compiled version shows a 2.5x - 10x speedup:


benchmark ns logarithmic runtime
SimpleExpressionReference 3367 ================
SimpleExpressionCompiled 963 ==
ComplexExpressionReference 6721 =======================
ComplexExpressionCompiled 1331 ======
If 7067 =======================
IfCompiled 805 =
Foreach 12796 =============================
ForeachCompiled 5275 ====================

Monday, November 10, 2008

Typedef in Java or Map<String, List<Map<String, Object>>>

Folks!

Have you ever had generic types like these Map<String, List<Map<String, Object>>>? If so this post might be interesting for you.

I had to pass either

Map<String,  Map<String, Object>>

or

Map<String,  List<Map<String, Object>>>

through a single method.

As you may know, polymorphism does not work with generics as the generic type is erased at compile time and is thus not available at run time.

So, I tried to have a decent signature for my method:

public void doSomething(Map<String, Object> data);
 
Which obviously works for both above types. Unfortunately, this signature works for many other types as well. Even worse, checking which type has been passed in, is really hard as the generic type has been erased. What you would have to do to really find out is to check the actual type of the map values. Really ugly. 

What can you do then? Before doing Java programming I was a C++ programmer, so I remembered the typedef keyword. Giving a lengthy type descriptor a short name - that's what I would have used in the C++ world. However, in the C++ world generics - templates in C++ speak - where different in nature. Each generic parameter would actually create a new type - which is not the case for Java. Apart from the fact that there is no typedef in Java! 

I finally did as Matthias advised me: Adding a thin wrapper around my two generic types that serves both as a short name as well as a type valid for run time:

A wrapper for Map<String, Object> would look like this:
public class DataProvider {

public final Map<String, Object> data;

public DataProvider(Map <String, Object> data) {
this.data = data;
}

public DataProvider() {
this(new HashMap<String, Object>());
}
}
Such a wrapper even saves you from typing constructors having weird syntax all the time as the default constructor already does this for you.

Concerning public fields, I know some people do not like them - for whatever reason. Simply make that field private or protected and add a getter method.   


Monday, September 29, 2008

Your Daily Dog Picture (Google App Engine)

My latest piece of work allows users to upload and display self-made dog pictures.

Right now only the latest 10 pictures will be displayed, but a tagging system to access older pictures is already on its way.

Technically, the site has been developed with the Google App Enginge and Python. On upload pictures are automatically rescaled to thumbnail size and are stored in Google Bigtable database along with the original.

All in all the whole site require less than 200 lines of code and about the same amount of HTML. It took me less than two days - including learning Python - to have the site ready and online. This is not because I am a genius, but because the technique is so simple and straight forward. Just great!

Why did I do it? Because I like dog pictures and I - of course - wanted to try out the Google stuff. You get free development and free hosting and there is much more available than I have shown on the dog site.

Monday, November 19, 2007

Google Android

If this http://code.google.com/android/ isn't cool, I have got no clue.

Friday, November 9, 2007

Is Spring Batch Vaporware?

I tried to figure out what Spring Batch can do for a customer. To my surprise I have not found a single source of practical use. No examples that made sense to me. Just a bounch of weird interfaces and some illustrations at the very high level. Could it be that Spring Batch is just Vaporware? That no one really has an idea what it should finally become? Announcements that went out a bit too early? Something like that?