piątek, 17 listopada 2017

JEP 286 - a case of language flexibility

Introduction


As a part of the future Java 10 specification, Oracle has proposed JEP 286 - Local Variable Type Inference. Full specification can be found here: http://openjdk.java.net/jeps/286 Since publication, it has raised a great deal of controversy among Java devs around the world. What is this all about then?

Local variable type - VAR


The proposal currently boils down to introduction of a new 'reserved type name' - var - that could be used instead of a variable type. Actual type would be then inferred by the compiler. Therefore you would be able to write:
var list = new ArrayList();
instead of:
List list = new ArrayList(); 

It should remind you of a Java 7 feature called diamond operator which was designed to eliminate verbosity of a RHS (right side assignment). Since then, Java compiler is able to infer generic construction type by looking at the variable type, for example:
List list = new ArrayList<>();
Var on the other hand aims to eliminate verbosity on the LHS (left hand assignment). Also, due to the fact that var would not be a keyword, the change is totally backward compatible, making following compilable:
var var = "var"; // ;-) 

The good, the bad (and the ugly)


So, is this good or bad? The answer is the usual one - it depends :-D

There are obvious advantages on var. The biggest one is already mentioned decrease of (unnecessary) verbosity. Does is make sense to write: 
int counter = 10 or MyOwnService service = new MyOwnService() ? 
Of course it does not, as type is apparent for writer and will be for consecutive readers of the code. However, it is easy to realize that the same feature is an obvious disadvantage in some contexts, like: 
var service = MyServiceFactory.forUserData(data)
 or even worse (as nothing is implied by context):
var result = service.calculate();
The fact that with var a result of an operation will not have an apparent type (for devloper that is) can cause even more trouble, especially in a context when result is later used in a generic way (like string conversion). Just take a look at the following, compilable code:
var ids = users.stream().map(user -> user.getId()); log.info("User ids: {}", ids);
The result in runtime will be completely unexpected, as instead of user ID list, stream's object reference will be logged. Why? Because the developer forgot (or didn't know) that the stream needs to be collected to list first. If the code had explicit typing like:
List ids = users.stream().map(user -> user.getId());
the code would simply not compile (as the compiler would know that the type expected by the developer was different than RHS). I often refactor, often work with legacy code and believe that the example is not an artificial one.

Also, taking into account the diamond operator, with var the developer will need to decide which "sugar" should be used in a particular context, either:
var list = new ArrayList();
or
List = new ArrayList<>(); 

Make peace, not VAR ?


To sum up, var has some benefits but also brings some dangers. From my perspective it's a typical case of added language flexibility, that can make life a bit easier but on the other hand can cause harm if used improperly or without caution (aka a monkey with a razor). Similar concept has been introduced into C# and developers can live with that. On the other hand, Microsoft in the official code convention guide (https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/inside-a-program/coding-conventions) explicitely warns developers not to use var in a number of contexts. 

Taking into account a typical life of a regular developer, that is often chased by deadlines, get distracted while writing the code or simply has not enough coffee ;-) I believe that var should be limited to cases when a type is apparent (local variable and constructor call for example). As the code is read more than written, it's better to have a code that is easier to understand than shorter to write. 

piątek, 3 listopada 2017

Spring framework 5 - new & noteworthy

Spring platform


Seems that nowadays everybody at least know (and most use) Spring framework. Well, no wonder. Years ago Spring pioneered lightweight DI container for masses. Later on provided nice (and also lightweight) MVC implementation that could easily play along multiple View (UI) technologies (JSP, vanilla JS, Portlets? you name it). With each and every modern (sometimes only trendy) solution / approach they were ready (REST, polyglot persistence etc.). Apart from the main Spring Framework, there are also additional Spring projects - for example fantastic microservice-enabling Spring Boot.

Spring framework 5


Current newest and shiniest version (actually 5.0.1, reference available here) has been the first major release since December 2013. This means 2,5 years of development, quite a lot I'd say in modern fast-changing software development world. So, what are the most interesting parts of the release?

Reactive Programming


Biggest star of the show - Spring-native reactive programming (go ahead and read Reactive Manifesto if you're not familiar with whole "reactive" hype). Based upon industry-agreed specification which is called Reactive Streams (specification here). Current Java 9 implements Reactive Streams natively, but as Spring 5 is coupled with Java 8, it uses an external implementation of the API - Project Reactor (click here for more info).
The reactive module is called WebFlux. Nevertheless, Spring MVC (REST-style) is still of course supported. Nice comparison in 5 use cases of "new fancy" versus "old proven" can be found here: https://www.infoq.com/presentations/servlet-reactive-stack
In order to make an application fully reactive, it has to use non-blocking model thru all layers, down to persistence. This means that currently it will work only with Mongo, Redis etc. Unfortunately, JPA / JBDC are still inherently blocking :( This can be worked around by separating persistence layer with a queue / working thread, reading / publishing persistence events (Event Sourcing anyone? :-P ).

Core and container changes


Apart from WebFlux, 5.x brings some core enhancements. Among most notable ones is utilisation of Java 8 features. For example, core Spring interfaces have now default method implementations. It means that in many cases you won't need to extends "adapters" implementing the interfaces but simply use them directly. There are also multiple lambdas and streams all around. For example, one can now register beans using a lambda (aka "supplier").  Last but not least, reflection enhancements (for details see here: https://docs.oracle.com/javase/8/docs/technotes/guides/reflection/enhancements.html) are now used for better/faster parameters access.
There is also a nice enhancement for large application start-up. Instead of a time-consuming classpath scanning, applications can now provide an index of candidates in the form of META-INF/spring.components file. Of course the file should be created by a plugin during build (not manually for God sake! :-) ). This should bring noticeable benefits for applications with more than 200 classes. According to the source (JIRA: https://jira.spring.io/browse/SPR-11890), 200 components / 5000 irrelevant classes starts 10% faster. Not that bad at all.

Others

  • Junit 5 fully supported, also on the "integration" side of testing
  • guava (among others) support discontinued :-( 
  • Java 8  / Java EE 7 as a minimum requirement

Further reading

Summary


To sum up, Reactive programming seems to be the main theme of the release. Rest of the updates are rather "sugar" like. It's not bad though, as we should remember to always "leave well alone" :-)

piątek, 13 października 2017

Notes on Java (hash) maps

Maps

Maps are one the most common data structures, used everyday by many programmers. In Java, the most popular implementation is HashMap, which uses open hashing (chaining) over an array to achieve constant-time (o(1)) performance of get/put operations (barring degenerated situation - for example when hashCode() call returns constant number).

Java HashMap

There are few things concerning this topic that should be interesting even if you're not that into algorithms / data structures ;-)

First of all, the underlying implementation and possible performance benefits. As said, Java HashMap is an open hashing one, which means that entries with the same bucket (array index calculated from hash) are put on a list. Therefore, in order to find a value for a particular key, the list needs to be iterated. This is of course o(n) operation (where n means number of entries in the list).

Java 8, however, implements a nice solution for this problem. According to this blog: http://www.nurkiewicz.com/2014/04/hashmap-performance-improvements-in.html Java switches bucket implementation from list to a balanced tree after a specific threshold is met (TREEIFY_THRESHOLD = 8 entries as of current). Thus, worst case performance improves from o(n) to o(log n). What is particularly interesting is balancing of the tree. For entries with different hashes, the hash value is used to compare entries. What if hash values are equal? Well, in this case the implementation hopes that keys implement Comparable interface. If this doesn't hold true - well, tree will be linearised, so in case of heavy collisions no performance benefits should be expected.

Robin Hood (RH) hashing 

As already mentioned, Java stdlib implementation uses open hashing approach. There is however a competing closed hashing (open addressing) approach. Closed hashing algorithm in case of collision calculate new hash (and array index) till free spot is found. This obviously means a performance penalty in high-collision scenarios as compared to open hashing in which the entry would be simply put at the end of the list. For get it's similar as the algorithm needs to go one-by-one comparing keys. Performance gets of course worse with higher loads of the underlying table.

I'd like to show here a neat idea how to improve over typical linear search, called Robin Hood hashing. The idea is quite old - published for the first time in 1986 (paper here: https://cs.uwaterloo.ca/research/tr/1986/CS-86-14.pdf). Why such name? Well, the idea is basically that some entries will get a free (insertion) slot sooner (with lower number of tries) than others, due to their "better" hash code value. Therefore, the algoritthm can put entries with "worse" hash codes closer (and move "better" to further spots). Thus, it's like taking from "richer" and giving to "poorer" :-)

Implementation itself is really straightforward - for each entry probe length (distance from originally calculated and current position) is kept. In case of collision, if probe length of the new entry is bigger than probe length of the current one, the new one is inserted (as poorer) and insert continues with the previously inserted one. If probe length of the new one is smaller, new index is calculated (and probe length for that entry increases). Therefore prob lengths will gradually even out.
According to this article https://www.sebastiansylvan.com/post/robin-hood-hashing-should-be-your-default-hash-table-implementation/ Robin Hood is faster as for current architectures it will has less cache misses (due to lower probe count variance). There were some attempts to measure the performance benefits of such approach. One of the best can be found here - http://codecapsule.com/2013/11/17/robin-hood-hashing-backward-shift-deletion. Up to date, only Rust language implements Robin Hood as the standard hash map.

Key takeaways


  • Java hash map implementation is very fast, in Java 8 even faster (balanced tree)
  • it's worthwhile to implement Comparable for keys used in hash map 
  • Robin Hood hashing is an interesting idea that's worth trying, especially in case of memory constraints (high load factors - 0,9 or even 0,95 without big performance hit) or other non-functional requirements (seems reasonable for disc storage due to linear access pattern) 

Further reading


piątek, 15 września 2017

Java 8 continued - cheat sheet ;)

Continuing the topic of Java 8. Folks at Zeroturnaround (authors of JRebel) wrote a nice article regarding:

  • default methods in interfaces
  • best practices with lambdas usage
  • proper Optional usage
or
download/print the cheat sheet in PDF: 
 http://files.zeroturnaround.com/pdf/zt_java8_best_practices.pdf

Enjoy! :-) 

czwartek, 14 września 2017

Java 8 for late-adopters - Venkat's 5 cents

Some time ago I wrote a short post regarding some Java 8 features that may be interesting for current pre-8 developers and may motivate them to switch to the latest version. It was really basic, more like teaser than tutorial.

As one of the projects I'm in is currently moving to Java 8, I recently did a presentation on the topic. During research I found out a number of great tutorials - ranging from simple introductions to deep-in-details encyclopedias. One, however, caught my eye.

Venkat's "Java 8 programming idioms" series, published here: http://blog.agiledeveloper.com/2017/09/java-8-programming-idioms-series-at-ibm.html Touches mainly functional side of the Java 8. It can particularly handy, as I see that some developers that up to date lived in an object-oriented programming world have a hard time switching to functional style of thinking. Enjoy!