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" :-)