Last week DZone had the opportunity to interview Daniel Fernández, the lead developer of the op4j library. Also called the "developer happiness tool," op4j is a powerful implementation of the Fluent Interface concept. It helps you polish the quality and readability of Java code with specific emphasis on auxiliary code such as structure iteration, filtering, mapping, data conversion, and more. op4j is also a large repository for hundreds of functions with over one thousand different parameterizations. Version 1.0
of op4j was released two weeks ago. Fernández had some really interesting things to say about op4j's origin, performance, and usage.DZone: What motivations led to your authoring of op4j?Daniel Fernández
: Quick answer: accident.
I started developing what now is op4j back in 2007 and under a different project name. At first I just wanted to write an extensible library for type conversions, for which I even wrote a runtime representation of the Java type system (which is now the javaRuntype [http://www.javaruntype.org ] project).
But when I came to write converters for arrays-of-x, lists-of-x, etc. it really turned nasty, and I started to think that I needed something that allowed me to write conversion code in a more readable way, something maybe a little bit similar to functional languages. And so the op4j "fluent" core was born.
Dozens of thousands of lines of code after that, when I saw the results I thought "Wow, this is something else. This makes code look great!". And so I went much further than just type conversions and created a lot of other useful features, which is the concept you know today for op4j.
So, as you can see, there were no exact "motivations" for authoring op4j as it is today. It just happened.DZone: What other tools inspired the technology behind op4j?Daniel
: First: Java itself. Java is a WONDERFUL development platform, but the language is so rigid, so "straitjacketed", that sometimes it just spoils all the fun that we should find in coding. So Java was my first inspiration... for change.
Also jQuery, Ruby and functional languages in general. I love jQuery, and I really like the flexibility of Ruby enumerables. Many ideas came from there. Some of my best friends are brilliant Ruby and ex-Java programmers and they helped me identify things that could be improved in the way we code in Java. Of course I also looked at some other technologies like lambdaj and linq, which I found really interesting.DZone: Could you briefly describe the Fluent Interface style, and how it relates to op4j?Daniel
: "Fluent interfaces" is a concept that has been around some time (some would say since the times of Smalltalk) which tries to produce more
readable code by making it look, in some ways, similar to phrases in written English.
How? Mainly, by means of method chaining. For example, in op4j you could write a line like:
"Op.on(myList).forEach().exec(myFunction).get()", which you could almost read like "Operate on myList and, for each element, execute myFunction and get the results". That is what "code fluency" is about.DZone: What types of Java applications will benefit the most from op4j?Daniel
: Any applications with an important amount of "auxiliary" code: type conversions, collection/map/array management, etc. To be honest, I think a very big percent of applications being developed nowadays have a lot of this stuff and could benefit from using op4j. Unreadable auxiliary code is just everywhere.DZone: This question comes from a DZone community member: "Do you have any performance figures? I recall when I looked at lambdaj, they suffered a 400-1200% performance penalty compared to regular Java code. In the end that was the main reason we decided not to use it. Does op4j have similar issues?"Daniel
: From what I know about lambdaj, lambdaj and op4j cores are very different in concept. For example, op4j does not use any kind of dynamic proxy creation, which gives lambdaj a very interesting typesafe way of calling object methods... but maybe could be affecting performance in the scenario this member explains (just maybe).
The code you "plan" with an op4j chained expression is translated quite straighforwardly to equivalent Java code by the op4j core, which has been heavily -and I really mean heavily- optimized to make it as quick as possible. The problem is, the only way of executing the same bytecode instructions as with "plain" Java code (and consequently, be as fast) is effectively writing plain Java code instead of using any libraries (be it op4j or any other library in your stack).
Some figures: we have a small "benchmark test" I used during development in order to be sure I optimized the op4j core to the maximum. It is not any kind of scientifically-correct benchmark, but it can give an approximate idea: The test takes a List with 1000 Strings and iterates it, converting each element to upper case before finally converting the whole list into an array. And it does this 1000 times, both using op4j and equivalent non-op4j Java code.
Timing in my poor old laptop: Without op4j: 828ms. With op4j: 1125ms.
Anyway, I always say that if you aren't a bad programmer and have confidence in your code, unless you are generating random numbers or parsing patterns or large Strings (which are time-consuming operations) you should only care so much about the performance of your in-memory code. Just go optimize your input/output, that is the key. And if you are apocalyptically worried about performance, don't use any libraries. And write native code ;-)DZone: How do I get started with op4j? How is it used?Daniel
: op4j is just a Java library. It is used in the same way you would use Apache Commons Collections or similar: just add it to your classpath, either manually or by using maven or whichever build tool you fancy. Once in your classpath, you are ready to code. No configuration needed.
As for how to use it, op4j was designed with the "content assist" feature of IDEs in mind, as it will only offer you the methods that make sense at each step of your expressions. For example, if you have a String, op4j won't let you write "forEach().forEach()"; the API will never offer that second "forEach()" method to you. So there is no point in trying to learn the entire API from the start. Just let op4j show you your options step by step by pressing Ctrl+Space.
And finally, a good place to start for examples is the recipes blog, "Bending the Java spoon". http://www.bendingthejavaspoon.comDZone: What new features are you planning for the next version of op4j and beyond?Daniel
: I think after releasing a 1.0 version of an open source project like op4j, one should be mainly oriented to listening to the user experience for a while. After the intense months of effort the team has gone through in order to publish 1.0, we will spend some weeks reading reviews and listening to comments and critics. In my experience, feedback received after releasing something new is certainly the most important -and desirable- influence for future work.
And then of course there will be more functions, more fine-tuning, more examples... all the usual stuff in project evolution.DZone: Is there anything else you'd like to mention?Daniel
: Let's make Java coding a little better --and more enjoyable!