
The last time I did any serious (or semi-serious) work in Java was in 2006. I used J2EE 5.0, which was the current version at the time, to demonstrate how we could migrate our enterprise web app package from spaghetti C++ to a more soundly architected framework in which most of the low-level work was done for us. I used Jetty as a servlet container for the demo because it was lightweight and easy to get going in a dev environment, although there were other options (most notably Tomcat). That was a long time ago and many versions away. I went into full-time LAMP work with Modern Perl and became a full-stack web developer.
My current circumstances have encouraged me to revisit Java. Firstly, I have some experience with it. I started by going through the Java practice challenges on HackerRank. I’m pleased with how easily it all comes back to me. I guess programming is like riding a bike. I’m using Java for all the online coding assessments as I look for work (except for the Perl positions). And I’m putting together a Java version of a TicTacToe app.
This has inspired some thoughts on the current Java ecosystem… and how it compares to the Modern Perl ecosystem.
There’s more than one way to do it
One of the aspects of the Java ecosystem that I appreciated in 2006, as compared to the .NET ecosystem, was that there were always multiple options, and the source code was usually available to see. The JDK included library source, which bailed me out on multiple occasions. You could choose TomCat, JBoss, or Jetty (or a host of other options) as a Servlet container, depending on your specific needs. Even back then, there was a thriving Java ecosystem with numerous included and third-party libraries and packages: JSP, Struts, JSF, EJBs, Hibernate, Spring… I’m listing these from memory, and the list now is many times the size.
Maybe Java doesn’t take the TMTOWTDI principle to the same insane extreme that Perl does. Java doesn’t try to “Do what I mean!” (And as a result, it’s much harder to write ambiguous-but-clever Java code.) But it does have the expressiveness to say it how you want to (much of the time).
At the time, this struck me as distinct from the .NET approach, in which everything was designed by Microsoft, and every solution had event handlers.
Java feels a lot more like Perl now
…or sometimes it does.
As I mentioned above, there are parts of Java that have always felt like Perl. Or maybe it’s actually the reverse. The fact that the One True Way™ was not shoved down your throat. And I seem to recall that JavaDoc predated POD, but that might’ve just been the order I learned them in. Perl 5 predates JDK 1. But what really stands out to me about Java now is its power and expressiveness.
Autoboxing and generics were part of Java in 2006, although I don’t remember using them much. Lambdas were added in Java 8. Meanwhile, Java’s type inference has also steadily improved over the years. The Java Stream library was also added in JDK 8. The result is code much closer in style to idiomatic Perl.
Now we can do things like:
List<String> words =
Stream.of("Hello Java World".split(" "))
.map(s -> s + '!')
.collect(Collectors.toList());
System.out.println(String.join("...", words));
…which of course prints…
Hello!...Java!...World!
But sometimes what you want to do is still just not as clean or concise as you wanted it to be. As part of my TicTacToe project, I needed to port to Java the functionality implemented in this Perl code:
sub _piece_counts {
my $board = shift;
my %counts = (X => 0, O => 0, ' ' => 0);
$counts{$_}++ for @$board;
return \%counts;
}
Here’s the best I could come up with:
public static final Boolean PIECE_X = false;
public static final Boolean PIECE_O = true;
private Map<Boolean, Integer> pieceCounts(Boolean[] board) {
Map<Boolean, Integer> counts = new HashMap<>();
counts.put(null, 0);
counts.put(PIECE_X, 0);
counts.put(PIECE_O, 0);
for (Boolean piece: board) {
int oldCount = counts.get(piece);
counts.replace(piece, oldCount+1);
}
return counts;
}
I should note, however, that the Java version is 100% type-checked. The board is an array in which each element can contain any of exactly three values: PIECE_X
, PIECE_O
, and null
. And as a result, there were whole sets of run-time validity checks that were needed in the Perl version that were simply meaningless in the Java version.
JUnit versus Test2
Like many old-timers, I first learned to unit-test on JUnit. Or more precisely, by reading about JUnit.
I first encountered the concept of test-driven development in Uncle Bob’s “The Craftsman” column in Dr. Dobb’s magazine in the early oughts. At the time, I was developing embedded software for a 6502-based product, and I needed to parse input data using nothing but 6502 assembly code. I think it was the promise of being able to break a complex parsing task into a series of simpler tests that lured me onto the TDD bandwagon. I used a script on my desktop as the test platform, running the tests on the embedded processor via its serial debug port. It worked like magic.
JUnit has also come a long way. I don’t know what version I was using in 2006—the Maven artifact history doesn’t go back that far. It was before we had annotations, I’m pretty sure of that. And all your tests still had to be subclasses of TestCase
. The current spec, JUnit Jupiter, includes features that make me drool as a Perl developer.
In particular, I’m taken in by parameterized tests, the ability to declare a table of test parameters with which a test method is iteratively invoked. This is something I’ve long wanted. When I was using Test::Class
, I promised myself I would someday put together some sort of implementation of this idea. Now that I’ve been primarily using Test2::Tools::Spec
… different plot, same story.
Gradle
I don’t remember what build system I used in 2006. Might’ve been make
. Or maybe whatever was built into Eclipse. Ant was available, but I don’t ever remember actually maintaining an Ant configuration—and that’s probably for the best. In the intervening years, Ant has been superseded by Maven, and Maven by Gradle. And Gradle is based on Groovy, and as someone coming back from the Perl world, that feels familiar and comfortable and also exciting.
In the 1990s, I designed a tool to build binary images for embedded systems. The tool was written in object-oriented Perl and supported a flexible configuration file format, which was also Perl.
Of course, MakeMaker
and Module::Build
are also configured (in part) in Perl. But it’s not quite the same thing.
I think it’s incredibly cool that I can do anything in a Gradle configuration that I can do in a Groovy script because Gradle configurations are literally Groovy. Firstly, it’s one fewer language for me to learn. And secondly, it means much more power at my disposal if I ever need to implement a complex custom build procedure.
So I put together a build.gradle
for my TicTacToe project. And the reason for this was, primarily, part of a Travis-CI setup. Now all my pushes are automatically build-tested.
Spring Boot
Before closing this piece, I wanted to mention a technology that fascinates and excites me: Spring Boot.
Back in 2006, Spring was coming into its own. I saw the power of IoC for some applications, even though I never had an opportunity to work with it. But I never forgot. To this day, I continue to dwell on the opportunities therein, even while developing in Perl.
Perl has a number of low-overhead “micro” web frameworks, like Dancer and Mojolicious. The idea that there is an analog in the Java world that does not require me to configure a servlet container…
This intrigues me because I haven’t yet decided what the interface to my TicTacToe application will be. I’m starting with the business logic, which is where any app development properly starts. The simplest idea would be to implement a simple REPL of sorts, a command-line interface. And that’s probably where I’ll start.
But ideally, I would love to create a microservice with a JavaScript front-end. I haven’t yet delved into Spring Boot. But it might be the ticket.
Still typing…
And may all your bars turn from red to green.
Tim
By John April 11, 2020 - 5:25 am
Sounds very encouraging. When you can, check out using Groovy in Grails and a hybernate framework. It’s all java. Groorvy is really perl-like. (some use Spring as a framework). There is a good living in this stuff and a demand right now. I keep getting requests to return to work because they don’t know I got old. 🙂
By Tim King April 14, 2020 - 11:52 am
Yes, Groovy is definitely on my radar, as is Spring. Right now, I’m taking an excursion and updating my JavaScript. Not as big a job as with Java, as I’ve been using JavaScript on and off while working with full-stack Perl. But I’d like to be able to say that I know a little Node.JS.
I’m really impressed with IntelliJ IDEA. I’ve been working without an IDE for so long, this is going to ruin me for “real” programming. LOL.