Usability - Productivity - Business - The web - Singapore & Twins

By Date: October 2022

Beyond Java 8: The Cool Stuff

Java is evolving rapidly. Henri Tremblay is walking through the cool stuff. Henri is, besides other activities a contributor to EasyMock

From Java 7 (2011) to Java 19 (2022)

Unless stated otherwise Java 17 (2021) LTS will work for the examples. Henri used a trading app to walk through upgrading steps.

Impressive: just moving from Java 8 to Java 19 shows double digit performance improvements

Some of the tips:

  • use the java.time.Clock object for anything date/time, Don't use Date. Inject the clock object.
  • use Comparators
  • use Files.lines to read by line
  • use the Maven deamon to speed compilation
  • Be careful with stream().findAny() - in most cases a Map performs way better
  • Use """ text blocks (why o why did Java not pick the tripple backtick)
  • Use Files.writeString if it is a String you write
  • Use jlink and jpackage for distribution
  • Use switch expressions which returns values (not convinced about that yet)
  • Use Records for immutable data
  • Use the new instanceof syntax
  • Use the new RandomGenerator for better performance
  • Sealed types allow tighter controls

A quite enjoyable session

Posted by on 20 October 2022 | Comments (0) | categories: Java

Test-Driven Development Is a Paradox

TDD is favored by very succesfull engineers as a means of accellerating software development by preserving quality.

Objections are plenty. The talk by Burk Hufnagel tries to address those.

The TDD Paradox

TDD requires you to write more code, so you can be done sooner. It's like learning to drive a car. Your first mile takes, give or take, 40-50h to complete: Driving lessons, driving tests, get the license issued before you drive. You can walk a lot more in 50 hours, you get the drift...

Looking deeper at "development" we see, it has multiple components:

  • understanding and clarifying the business requirements (business rather loosely defined)
  • write code
  • manual testing
  • debugging

TDD helps with the first and third component. A well defined test communicates the desired outcome and serves as a living specification. Having the machine running tests reduces the need for manual testing and frees up time to work on functionality

Test early, test often

TDD proposes to write tests first, not as an afterthought. The strongest new argument Burk proposed was: nobody wants to write a test for code freshly debugged and proven working (at that time). There's no immediate value in it. A test, initially failing, written upfront is a reassurance to be on the right track when going green.

Using the "test first" approach, tests turn into a design process, increasing the confidence in not only doing things right, but also doing the right thing. In other words: Tests are Specifications

Best results are to be had when working in small increments and resist the urge to "code for things you think are coming next" instead of "(just) make the test pass".

It's not a cure-it-all

TDD might not be a good fit:

  • no clear business requirements - you can't test when you don't know what you want
  • exploratory coding - trying stuff out

A common objection is "we have an existing non-TDD code base, we can't switch to TDD". Burk suggest to use "Defect Driven Development". Write a test that test for defect free behavior and then fix the defect. Your test harness will grow while defects shrink

Test long and prosper

The usual subjects for testing in Java are JUnit and Mockito. Burk introduced another, very promising tool: Spock. Spock is written in Groovy and allows to specify a test's purpose more expressive and concise than Junit's @DisplayName property. Luckily it isn't an exclusive-or question, Spock interacts with JUnit and Mockito quite nicely.

In conclusion

Burk made a good case for TDD, backed by experience and tooling, if in doubt visit his arguments.

Posted by on 19 October 2022 | Comments (0) | categories: Java

CI/CD, Github Actions, and GraalVM Native Image

GraalVM is a promising polyglot runtime for Java, JavaScript, Python, Ruby and WASM.
It can produce native images. Unsurprisingly with great powers come ... lots of things to learn.

GraalVM Native Image Benefits

A native image has a number of benefits over an JVM based application, mainly owed to the extensive analysis done at build time.
Some of advantages mentioned:

  • Runtime speed ~ 25% above the same code running on an JVM
  • Ahead of Time compilation can lead to up to 9 times less memory consumption than running on an JVM
  • Code executes faster with a smaller memory footprint than comparable Go applications ( but still is bigger/slower than C by a whisk)
  • Warmup time got moved to build time, improving startup time

Building the image

Build has been greatly improved with tooling available:

  • a Maven plugin (also available for Gradle), eliminating the need of extensive commandline foo.
  • a GitHub action to install the GraalVM tooing in a pipeline
  • reduced memory consumption, so most apps will fit into the GitHub build container limit of 7GB memory
  • option for a non-optimized fast build, useful for testing correctness

Thoughts and conclusions

A big step in the right direction making native images more accessible. There's still room for improvements, like caching the build images and more samples. What Oracle solved nicely: If you are a GraalVM Enterprise customer, accessing GraalVM Enterprise edition is done using an access token, fully compatible to any build system. No messing around with downloads and manual installations required.

Posted by on 18 October 2022 | Comments (0) | categories: Java

Streamlining Lage-scale Java Development using Error Prone

It has been a while since I attended an in-person conference. Finally this October I managed to attend JavaOne in Las Vegas. I shall report on interesting sessions.

The first one is by Sander Mak on a topic near and dear to me: Code Quality

Another tool in the box

Error Prone, courtesy of Google, supplements tools like Sonar, Spotbugs or Checkstyle. Other than these tools it is a compiler plugin with > 500 checks.

It can be configured to fix a set of identified errors automatically in code, inline or as patch file. Sander used a few simple demos to drive home what is possible using the tooling. Besides the ckecks that are available out-of-the-box one can implement extensions. One interesting contribution comes from the popular mocking framework Mockito, extending the checks to your use of mocking.

Extending error-prone is possible using two complementary approaches:

  • writing your own extensions (extending BugChecker), dealing with Java's AST and all its power
  • using the included ReFaster templates that allow for powerfull pattern based code upgrades

Use cases

Just a few samples from the session:

  • implement consistency in coding style (not to confuse with code style)
  • reduce visible clutter like final before variables by using @var to denote mutable variables and consider immutable the default
  • ease the transition to higher JVM versions, e.g replace !Optional.isPresent() with Optional.isEmpty() (JDK11)
  • verify logging uses {} instead of %s
  • fail builds that violate rules and conventions

My impression

Error-prone seems to be an important tool in toolbox to produce a well groomed Java code base. I loved Sander's progression from a simple introduction example to the more complex use cases that help his company deliver (pun intended). Error-prone isn't for the faint of heart, but a component that belongs into any code base of size. The session inspired me to improve our Java tooling, well done!

The Steve pun, one last thing, was the icing on the cake

More content by Sander

Posted by on 18 October 2022 | Comments (0) | categories: Java