

John McClean x Java Daily
In our special Java Daily edition, we would like to introduce you to John McClean. John is an Architect at Verizon Media. With his incredible dedication to give back to the Java community, we are more than excited to present some of his know-how to you.
Java Daily: How do you choose a framework for a project?
John: For larger frameworks with a learning curve the availability the existing knowledge of our engineers is critical, so most of the time I would look at evolving our current tech stacks rather than selecting something entirely new. The exception to this is where an important need is met by a new framework that is not covered in our existing tech stacks.
Java Daily: What is more important: an optimal algorithm or code that is easier to read?
John: 99 times out of 100 – code that is easier to read. If it is easy to read and understand, it is less likely to contain bugs and should be easier for other engineers to extend and evolve later. But very occasionally speed (or some other optimization) is critical and trumps the long term maintainability of the code.
Java Daily: What are the most important functional programming principles that can be transferred easily into imperative programming as well? I could start with: “Always use pure functions”. What would you add?
John: Write unit tests for those pure functions, they are so much easier to test than most enterprise Java code 🙂 Make sure to follow SOLID principles and keep I/O operations encapsulated so that you can write as much of your code base as possible in terms of simple, testable pure functions.
Prefer Immutable Data structures where possible. From typed FP – help the next developer by making illegal states unrepresentable in your code (practically to start – don’t use null, don’t throw exceptions). To expand on that later point, make use of the type system to ensure only valid inputs can be provided. If you must accept an input you can’t handle (because. for example you must accept an Integer and only 0-10000 are valid values), then use the Return type to return the error.
Java Daily: Have you encountered a project that was done in functional way but was more suitable to be done in other way? Can you elaborate?
John: Code needs to be maintained – often for a long time. There are large numbers of Java developers who are comfortable coding imperatively and much lower numbers of (for example) Scala developers who code functionality. We’ve certainly had projects, implemented in functional languages. that we have had to migrate because hiring people to maintain them became difficult. In the Java world, I think it is possible to adopt functional principles and techniques – because at minimum new developers are familiar with the syntax – but it is important to remember code will have to be maintained by someone else at some stage.
Java Daily: Switching from imperative to functional is very difficult. Can you suggest some of your favourite books, courses, or just outline some steps to learn functional programming?
John: Don’t try and switch all at once. In Java (where you may be comfortable with the SDK, the libraries and the syntax) adopt and practice functional principles one by one. Try making some of your existing classes immutable and spend a little time figuring out how to create and then ‘change’ those objects efficiently. Play with an existing API, and remove null values as valid return types, or Exceptions as something that can be thrown. This will make your API more reliable and may still feel like standard OO coding to you, but it is a good exercise on the path to understanding FP.
Java has already adopted many functional ideas (Generics, Monads – Streams, Optionals and CompletableFuture, Lambda’s), so I would start there. I really enjoyed the Java 8 in Action book by Raoul-Gabriel Urma, Alan Mycroft and Mario Fusco as an introduction to some of the functional features of Java. Outside of Java, the ‘red’ Functional Programming in Scala book by Paul Chiusano and Runar Bjarnason is really good (but it helps to understand the syntax of Scala first).
Don’t over complicate things as you adopt and experiment with functional ideas. It can be an interesting challenge to experiment with some advanced functional concept – but if your code is cleaner with something simpler, make sure that what you actually merge to the production code base is the simple version – not the interesting experiment!
Java Daily: Writing in functional style with Java feels very cumbersome. Do you think that Java will ever become a valid and reasonable alternative of purely functional/hybrid languages out there?
John: I would guess that it is cumbersome to emulate monadic Scala or Haskell in Java – but maybe less so to write simple, testable, pure functions that accept as input the result of an I/O operation.
Will Java ever become a reasonable alternative for languages like Idris, Haskell or Scala? Not likely.
If you want to write purely functional production code – Java is not the language to do this in. If you want to learn some of the principles and you are a Java developer – by all means experiment in Java, but I recommend making sure any functional Java code you commit to your production code base makes it better not worse (is simple and clean).
You absolutely can make Java code better by sensibly adopting functional principles however.
Java Daily: What properties should a project have in order to go for a functional approach in java based application?
I think projects with all but the most extreme low latency / GC requirements can adopt at least some functional principles in Java.
Java Daily: Let’s say we’re going in production with Java 11 and we don’t have the budget for Oracle JDK. Which OpenJDK build would you recommend?
John: Honestly, no idea.
Java Daily: What is your favourite functional library for Java?
John: Cyclops, of course 🙂
Java Daily: Which one do you prefer?
1 2 3 4 5 |
final List<PageContainer> containers = Optional.ofNullable (page.getContainers()).orElse(List.of()) .map.(this.containerMapper: :convertToPageContainerDTO) .collect(Collectors.toList()); pageDTO.setContainers(containers); |
or
1 2 3 4 5 6 7 8 9 |
If (page.getContainers() != null) { List<PageContainerDTO> containers = New LinkedList<>() ; For (PageContainer pageContainer : page.getContainers()) { containers.add(container.Mapper.convertToPageContainerDTO(pageContainer)); } pageDTO.setContainers(containers); } |
I prefer the imperative version.
But with cyclops (and Lombok) you could write something like this instead:-
1 2 3 4 5 |
Vector<PageContainerDTO> containers =page.getContainers() .map(this.containerMapper::convertToPageContainerDTO) return pageDTO.withContainers(containers); |
Where the method signatures are :-
1 2 3 |
Vector<PageContainer> getContainers(); PageDTO withContainers(Vector<PageContainerDTO> containers); |
Vector is an efficient ImmutableList in Cyclops. Rather than returning a null Vector, getContainers would return an empty Vector.
Is there anything else you would like to ask John McClean? What is your opinion on the questions asked? Who would you like to see featured next? Let’s give back to the Java community together!