
Better Java – Resources for Writing Modern Java - networked
https://github.com/cxxr/better-java
======
kodablah
"If you're using Java 8, you can use the excellent new Optional type. If a
value may or may not be present, wrap it in an Optional class like this"

While I agree with most things, overuse of Optional like this is an
antipattern IMO. Having done a lot of Java 8 development, I find Optional is
best for return types, but otherwise forcing callers to wrap values in
Optional is unnecessary as opposed to something like Scala. Those that work on
the JDK feel the same [1][2] and I think [2] is even overuse with the
prevalence of static analysis tools and @Nullable.

Although a tad dated, I find [3] to be a good guide to modern Java all around.

1 - [http://stackoverflow.com/questions/26327957/should-
java-8-ge...](http://stackoverflow.com/questions/26327957/should-
java-8-getters-return-optional-type/26328555#26328555) 2 -
[http://blog.joda.org/2015/08/java-se-8-optional-pragmatic-
ap...](http://blog.joda.org/2015/08/java-se-8-optional-pragmatic-
approach.html) 3 - [http://blog.paralleluniverse.co/2014/05/01/modern-
java/](http://blog.paralleluniverse.co/2014/05/01/modern-java/)

~~~
harryh
Keep in mind that Tony Hoare, the inventor of the null pointer, calls this
invention his billion dollar mistake. I generally think that he is right and
use of null should almost always be avoided.

~~~
asveikau
By all means, have more clumsy, less straightforward ways to represent the
lack of a value in your code, because Tony Hoare says so.

~~~
harryh
The problem with NULL is that it can be there for literally any reference in
your code. So, unless you are careful, you can get an NPE when calling any
single object method. In languages without NULL this can never happen making
them much easier to reason about.

~~~
asveikau
My initial reaction: programming ain't bean bag. Them's the breaks.

Then I think of it and I see the real problem is languages making all
nonprimitive types into pointers without being explicit. In a language like C
it's more obvious what can be null.

~~~
harryh
If null can be problematic then certainly making it more obvious when you
might have a null is a pretty good idea. I tend to think, however, that
getting rid of null completely as a concept is even better. One less thing to
worry about.

------
hiram112
I've seen numerous posts lamenting the use of typical Java Beans.

The problem with the struct approach is that numerous tooling / libraries
expects beans with typical getter/setters - Jackson Json, Spring binding, etc.
Yes it's possible with configurations and/or annotations to get around this,
but IMO, saving a few lines of code in exchange for non-default behavior isn't
a valid trade-off.

Adding a dependency on Lombock is even worse.

Honestly, I can spot a Bean class within 1 second of opening it up. Unlike
Scala or other languages, Java programmers typically use one class per file,
and beans rarely get in the way as they're typically contained in some 'model'
package anyway.

~~~
vbezhenar
Another problem with struct approach is inconsistency.

Sometimes you want a computed property and you use non-trivial getter.
Sometimes you want to do some work in setter. And then client's code will look
terrible: point.x * point.x + point.getY() * point.getY(). There are other
problems: binary incompatibility; non-trivial refactoring when I need to
introduce a getter or setter.

Java really need lightweight property syntax which would solve all those
problems. I don't understand why it isn't introduced yet.

~~~
zmmmmm
The lack of simple property syntax is probably the main reason I keep using
Groovy now that Java 8 has arrived. Yes, state is evil. But there are still
plenty of situations where you are just schlepping data around and generating
thousands of lines of boilerplate to achieve simple data transfer is such a
pointless and ugly hack.

~~~
cam-
For DTOs we don't user mutators. Just public member variables. It is the only
way to keep business logic out of them. That being said, I wish Java has some
object/struct syntactic sugar like Javascript Object Literals. They are so
powerful.

------
kilink
I'm surprised he didn't mention AutoValue [1] or Lombok (using @Data and
@Builder) in his section about data objects and builders. I prefer AutoValue,
but both approaches cut down on a lot of the boilerplate (and they also
generate sensible equals(), hashCode(), toString(), etc).

It's also kind of a nitpick, but I disagree with his preference for Guava's
Maps.newHashMap() vs new HashMap<>(). I'm pretty sure the only reason those
static methods exist is because pre-Java 7 didn't have the diamond operator.

[1]
[https://github.com/google/auto/tree/master/value](https://github.com/google/auto/tree/master/value)

~~~
adpreese
He mentions Lombok in the tools section.

And Guava's collection creation methods are part of an intense desire to not
use the new key word anywhere in application code.

~~~
kilink
Also, if you look at the Javadocs for some of the creation methods, they
explicitly state that they are for Java 6 and earlier, and that modern code
should just use the constructor with the diamond syntax.

[http://docs.guava-
libraries.googlecode.com/git/javadoc/com/g...](http://docs.guava-
libraries.googlecode.com/git/javadoc/com/google/common/collect/Lists.html#newArrayList\(\))

------
nobleach
After working at two companies filled with Java devs, I don't think any of
them will read this article. I can't speak for all Java devs obviously, but it
seems unless the dev is a polyglot, they are just fine living in their
Spring/SVN/J2EE/Java5 world. They have no idea what's going on in the software
development world. I get so excited whenever I hear any of them mention
Clojure or even Scala! They just live with this head in the sand mentality.
They hate the front end, they think, "these JavaScript developers will go away
someday and we can finally go back to writing JSPs". Currently we've updated
our JVMs to 8, and that's a big deal, but we've told our devs NOT to use any
features from 8 as we're worried about how GC will perform and since we're
about to get geared up into shopping season, now is not the time to use shiny
new features.

~~~
thejosh
This is also how I feel with PHP Developers who work in development agencies
or larger companies, either in a small team or by themselves (probably even
larger teams, but no first hand experience with that).

Basically they refuse to use version control (FTP their code to the live
server), use a terrible dev system, non-existent or terrible staging
environments or newer technologies such as composer or other tools which will
save them time and effort.

Don't even get me started on the lack of tests, and how buggy and broken their
code ends up being - "we don't have time to write tests", yet spend weeks
fixing critical issues that would have been found...

/rant

~~~
nobleach
I see the lack of unit tests constantly. I did a small stint with PHP and one
of the first things I did was learn PHPUnit. Having invested heavily in the
TDD Koolaid with Rails/Python, I made sure I learned how to apply the same
ideas in PHP. And yes, I've seen quite a bit of the "1999 was just fine"
culture among PHP developers too. If you can't deploy your code at the touch
of a button, you should be working your way to that goal.

------
carsongross
There is some good stuff in here, and a lot of bad.

SparkJava (mentioned) is the great hope for sane java web development:

[http://sparkjava.com/](http://sparkjava.com/)

Having to convert out to streams for data structure manipulation with lambdas
is insane. It would have been very healthy for the core java team to pull in
someone with a lot of ruby experience so they could get that API right.

Too bad: the JVM and associated tools are fantastic.

~~~
asdf1234
> Having to convert out to streams for data structure manipulation with
> lambdas is insane

I don't see why. It's explicit and allows you to chain higher order methods
without building up a ton of intermediate data structures and convert to any
data structure you like very efficiently.

It's still not efficient as imperative approaches but it's close enough and
far better than most collection libraries.

------
izzle49
Please don't use Java 8's default methods in interface's to do multiple
inheritance, and code reuse. Prefering this over 'Util' classes is bad as it
is inheritance over composition. The default methods were designed to
facilitate easier interface migration

~~~
lmm
Java was designed for TV set-top boxes, but that doesn't mean it's bad to use
it on a server. If using a default method in an unintended way leads to
clearer, more maintainable code, do it.

~~~
izzle49
how would it lead to more clearer code? You would have many interfaces
referencing an instance variable, each with different semantics for that
variable. Interfaces cant have variables so they should not be used as traits.

~~~
lmm
One good use case I can see is where you want to add convenience "helper"
methods to an interface that can reasonably have default implementations in
terms of some other method on the interface (E.g. overloads to emulate default
parameters). Or for methods that can be implemented in terms of another
method, but might have a more performant direct implementation (e.g.
Collection#get can be defined in terms of iteration).

I don't quite understand your point about instance variables. Instance
variables are and should be encapsulated. An object that implements multiple
interfaces must of course provide the correct semantics for all of them. But
that's true whether an interface contains method implementations or not.

------
zinxq
I'm in agreement with the first few comments already - at least some parts of
this advice is dubious.

For one - some performance examples (specifically, integer array iteration) is
15 times slower with streams.

Angelika Langer's analysis:

[https://jaxenter.com/java-performance-tutorial-how-fast-
are-...](https://jaxenter.com/java-performance-tutorial-how-fast-are-the-
java-8-streams-118830.html)

~~~
coldtea
> _For one - some performance examples (specifically, integer array iteration)
> is 15 times slower with streams._

That's a very misleading example, and even the linked post itself explains why
it is so (e.g. not much is done with the integers in the first place).

------
adarshr
My solution is to use Groovy wherever possible. It has a superb syntax, very
low learning curve and compiles into JVM bytecode. There is no issue with
getters and setters in Groovy - you just define the fields, which Groovy calls
properties and defines implicit getters and setters.

If not for the main application code, I would definitely use Groovy for unit
testing in combination with Spock Framework. You just have to try it once to
realise what you've been missing all these years with JUnit.

~~~
vorg
Groovy's always been OK for quick and dirty testing of Java classes, though
the statement label hack that Spock uses makes Groovy look trashy. The static
compilation that came with Groovy 2.0 is what no-one should touch if they
don't want to spend countless hours and days debugging and wondering why they
didn't use a language built from the ground up for static compilation, e.g.
Java, Scala, Kotlin, Ceylon, and others.

------
mindcrime
One thing I'd add, is that Java is very amenable to static code analysis, and
there are good tools like PMD and FindBugs for Java. I always encourage teams
using Java to use one or both. The biggest downside is that you usually have
to tweak the rule-sets to avoid getting lots of false positives. And if you
get too many false positives then people tend to stop paying attention to the
notifications from the tool.

On a related note, I really encourage Java teams to shoot for a goal of having
compiles that finish with no warnings. If there are generic warnings littering
your code (like, for example, all the warnings about unqualified references to
generic types that you get when using code written before generics existed),
bite the bullet and either fix them, or make it explicit that you don't care
and add the appropriate annotations to turn them off. At least that way, when
a new, interesting warning shows up, maybe people will pay attention to it.

And yes, this is something of a "do as I say, not as I do" thing, as I have
definitely written Java code that doesn't follow this rule. Especially on my
personal projects or code where I'm not working with a big team. On bigger
projects, I do try to push that as much as I can, depending on my role on the
project.

~~~
lomnakkus
> [...] Java is very amenable to static code analysis [...]. The biggest
> downside is that you usually have to tweak the rule-sets to avoid getting
> lots of false positives.

These two statements seem to be in opposition to each other.

(All your advice is spot on. If you let warnings remain in code, you'll just
end up accumulating more and more warnings until it's too much to fix. I guess
it's a sort of "broken windows" effect.)

~~~
mindcrime
I don't know if they're in opposition exactly. The Java language is definitely
amenable to static analysis to some extent, probably more so than a more
dynamic language. But a lot of the "false positives" are just about what rules
the developers of the tool ship by default, and what they define as a "bug"
(or "possible bug"). For better or for worse, static analysis tools sometimes
conflate simple stylistic issues ("don't use variable names less than two
characters") with things that are likely to be actual logic errors. And since
the tool will always be limited in how much it can understand about the
_intent_ of the code, it's pretty much always just applying heuristics and a
probabilistic analysis, even when processing Java.

So yeah, those tools aren't perfect, but my subjective experience has been
that they help, as long as you tweak the knobs so that they don't just
generate something equivalent to the "broken windows" compiler warnings, etc.

~~~
lomnakkus
My point was basically that, in general, imperative programming languages
(like Java) are insanely hard to do static analysis on, so I though it was
ironic that you mentioned that it (Java) was both a) amenable to static
analysis, and b) said that it resulted in a lot of false positives. I think
that point b) somewhat invalidates point a), don't you think?

EDIT: False positives tend to indicate that there's something wrong with your
analysis.

I suppose this is a general thing: If a warning system alerts you every five
minutes, what are you going to do? Are you going to react and go on full-
adrenaline-rush every five minutes, or are you just going to turn it off after
two or three false alarms?

EDIT: Sorry, OP = you. Edited correspondingly.

------
fizwhiz
>> Good alternatives to using Spring is Google and Square's Dagger library or
Google's Guice. They don't use Spring's XML configuration file format, and
instead they put the injection logic in annotations and in code

Spring has had code-based configurations since 2009[1]; seems a little
disingenuous to recommend Guice/Dagger due to this non-existent limitation.

[1] [http://spring.io/blog/2009/12/22/configuration-
simplificatio...](http://spring.io/blog/2009/12/22/configuration-
simplifications-in-spring-3-0/)

~~~
lmm
Spring has a million and one ways to do anything; that's the problem with it.

Spring with a very strict, carefully enforced style guide is probably as good
as Dagger or Guice. But there is a cost to maintaining and enforcing a style
guide. Better to just use something that doesn't have the bad options.

~~~
jacques_chester
That's what Spring Boot is for.

Everything is autoconfigured and set to sensible defaults. All the
dependencies in the starters are levelled and guaranteed to work together.

Spring Boot on Gradle is the closest thing Java has to adding lines to a
Gemfile in a Ruby system. Especially when you add other Spring automagical
libraries (Spring Data REST, Spring Cloud...).

------
eddiezane
This is a really great resource and I'll certainly be embracing some of it.

I attend quite a few university hackathons as a mentor/sponsor and one of my
goals has been to paint Java in a better light as it doesn't have the best
reputation in that circuit. I'm always telling people that their goal should
be to build something cool and learn something new.

It's much easier to teach someone how to build their first webapp in a weekend
when you can do it in a language that they are familiar with and Java seems to
be what's taught at most universities.

The Spark Framework mentioned here is very well done and beginner friendly. I
recently wrote an intro blog post [0] about it as an attempt to embrace
existing knowledge and showcase that it's easy to build something cool with
Java.

0: [https://www.twilio.com/blog/2015/09/getting-started-with-
gra...](https://www.twilio.com/blog/2015/09/getting-started-with-gradle-and-
the-spark-framework-3.html)

~~~
potatosareok
Looking at Spark framework I'm wondering about your thought of Spark vs Spring
Boot. I've not used Spark but I find Spring Boot lets you get an app of the
ground quickly, is part of massive Spring ecosystem which gives you a lot of
other advantages (for example, Mongo template might be very useful for
Hackathon project). Beyond that RestController automatic integration with
Jackson can quickly let you bring up a JSON based webservice.

Also I'm not a fan of how in your example the entire app routing/logic is
basically crammed into a single main method. I know it might be simple demo
app that you're trying to show off Twilo but I don't think you're doing favor
by structuring like that.

What do you feel are the benefits of Spark vs Spring Boot (or Dropwizard I
guess). In my mind the only reason I wouldn't use Spring-Boot for a new
project in Java is if I wanted to use something like Play! since supposedly
using Play!/Scala and futures integrate very nicely into that.

------
cletus
I mostly agree with this list but some things I have issues with.

The biggest is DI. Having witnessed what a tangled mess large Guice codebases
can become where you really have no idea what is providing what I have to say
that Spring here gets a bad rap from the all-XML days and (IMHO) it is
actually the cleanest and easiest to work with.

The author mischaracterizes Spring too:

> It has a either code-based wiring or XML configuration-based wiring.

Actually Spring can use a mix of XML code configuration and auto-wiring.

A modern Spring application will have precisely an application context XML
file with one line per "bean" eg:

    
    
        <bean class="com.foo.SomeClass" />
    

and that's it. Note: there's no classpath scanning. Auto-wiring takes care of
the rest. This has two big advantages (over Guice in particular):

1\. Everything is in one place. If it's not instantiated here it doesn't
exist. Guice can be many levels deep and tends to descend into ModuleBuilders
and conditional logic in modules (which the docs recommend against but tends
to be used extensively anyway); and

2\. Testing. Testing is incredibly easy. I'm talking functional testing here,
even integration testing. You simply include another XML file that overrides
any definitions from the first. Everything else remains the same.

Testing with Guice can be horrendous and once you start making extensive use
of Modules.override() you should abandon all hope.

I'm glad to see this post recommend Maven. It's fun to bash Maven but most
detractors ignore the huge benefit that applies to any shop with lots of devs:
Maven is opinionated. That's a plus not a minus. Seen one Maven Web
application and you've seen them all. There's no really weird directory layout
because someone decided they just had to be different.

Lastly Play. I really tried to like Play. I really did. But as of Play 2.0+ it
became a Scala not a Java framework. It may still work with Java but some
things just require you to know something about Scala. That's a huge negative
IMHO. I'm not interested in Scala. Nobody is.

Plus the auto-compile feature of Play tended to randomly break with
indecipherable error messages for no readily apparent reasons such that you
couldn't tell if it was a bug or not. I get enough of that with C++ template
programming thank you.

I also agree that the two books the author recommends are probably the two
most important Java books in existence.

~~~
Babylonian
> Scala. That's a huge negative IMHO. I'm not interested in Scala. Nobody is.

Their use of Scala was the only reason I gave the play framework a second
look. Just because you're not interested in Scala doesn't mean nobody else is.
Scala is the most popular plugin for intellij by a very wide margin, that's a
lot of 'nobody' downloads. Having used both java and Scala extensively I
honestly can't understand why anyone would still pick java by choice other
than if it's the only jvm language they know.

------
davnicwil
On the struct-like data objects part - this is so much nicer than the getter
(and setter for mutable objects) pattern, just because readability is so much
improved.

Getters/setters is a pattern that it took me a while to reject, having always
been told that public fields were really, really bad. But they're simply not.
Having logic in getters/setters is the only justification for this added
bloat. In my experience, in the overwhelming majority of cases (never say all)
having logic in getters and setters is a clear indication that your design is
flawed anyway, so most of the time you should never have them.

On this part:

> Further, this class is immutable unless you extend it, so we can reason
> about it easier as we know that it can't be changed.

Well, I'd go further. Make the class final if you really want to guard against
people extending it. Of course this is most applicable for writing reusable
libraries where communication with consumers may be limited.

If you rely on language features to enforce development practices in a team
who can freely communicate, in general you've got a much bigger problems than
the few rare bugs that extending an immutable class and making it mutable will
cause.

Obviously though, putting guard rails in can only ever be helpful, even when
absolutely everyone understands that there's a cliff edge there, and wouldn't
conciously try to walk over it anyway.

~~~
mark_l_watson
I don't like to use getters, setters either. I like default package access so
instance variables are just visible inside a package.

------
owlish
I used to be a fan of the Builder pattern (or Fluent Interface), but the ease
of use for developers comes at the cost of no compile-time checking. Before,
you just had to look up the constructor to see which parameters go where, with
the benefit of type-checking. Now, you have to look up the Builder's methods
to make sure you've filled in all required fields. The only case where I can
actually advocate using Builders is when you have a mess of telescoping
constructors.

~~~
habosa
If you have this problem, the library you're using is incorrectly using the
Builder pattern. All required parameters should be in the constructor of the
builder. Then the other methods on the builder should be optional
configuration. For instance on Android you often see a builder that takes a
`Context` in the constructor because that's almost always required.

~~~
owlish
This is contrary to the OP's example, where he passes data and num to the
constructor, which is how I've seen it used frequently. The Builder pattern is
often recommended to "make code easier to read" and wouldn't be useful if
many/most of those parameters were required.

------
Cthulhu_
Re the first bit about 'struct' style, even better (IMO) is to use Lombok;
throw an @Data annotation on your class and all you need to do is put your
properties in there (private final if need be). Nobody should be writing those
boilerplate constructors, getters and setters. If it's generated by your IDE,
use Lombok. The best code is no code.

~~~
Babylonian
Lombok is a crime. Have you seen what happens when someone does a minor
reformatting of your code and moves one field declaration above another? You
get a nasty little surprise because the two fields of the same type have now
reordered in your Lombok generated constructor. When the app runs nobody can
figure out why foo is set to bar and bar is set to foo. There's also the issue
of Lombok vals which don't conform to the language spec leading to other fun.
And it's almost always incompatible with new jdks without code changes to the
lombok libs due to the whacky way it relies on implementation specific
compiler details.

~~~
dguaraglia
Wow, I didn't know this could happen. I've only recently started using Lombok
for some side-project related stuff and this heads up comes at a really good
time. Thanks!

------
jonhohle
As a fan of immutable objects, I bemoan the builder pattern. The nice thing
about constructors (or factory methods) is that you have a compile time
guarantee that you have all required components to construct an object and
validate its invariants. With a field oriented builder, only the documentation
informs you whether you've met all of the conditions to construct an object.
Also, a builder which mutates its own internal state breaks the idea of
partial application where several variants can be constructed from a parent.

Unrelated to builders, the stream example could be simplified further with
method references

    
    
        final List<String> filtered = list.stream()
            .filter(s -> s.startsWith("s"))
            .map(String::toUpperCase)
            .collect(Collectors.toList());
    

It would be nice if Oracle back filled some predicates to make them more
useful in streams (e.g. "s"::isPrefixOf, etc.).

~~~
benjiweber
You can create immutable "builder" with lambda chains. This also gives you the
compiletime guarantee that you have specified the required fields (At the cost
of flexibility and ease of adding new fields)

[http://benjiweber.co.uk/blog/2014/11/02/builder-pattern-
with...](http://benjiweber.co.uk/blog/2014/11/02/builder-pattern-with-
java-8-lambdas/)

Regarding your isPrefixOf - is there a significant benefit to that being in
the standard library? You could define a isPrefixedWith("s") that returns a
Predicate<String> yourself.

~~~
hepta
This is great, thanks. I've also used something like this:
[https://gist.github.com/dwijnand/3741951](https://gist.github.com/dwijnand/3741951)

------
zatkin
Streams are questionable in performance vs non-stream approaches. I haven't
found an article that details performance differences, but I will say that I
personally tried doing things using streams and doing the same things using
non-streams and have had mixed results, one being faster than the other in
some cases.

~~~
mabbo
The benefits of streams isn't performance improvements for the CPU, but
performance improvements for the developer.

~~~
chii
i have colleges that claim streams don't necesserily make the code more
readable. Imagine a triple nested for-loop - making it a triple nested streams
(e.g., where your map method is yet another stream), doesn't seem to really
make it any more readable.

The only reason to use streams, i think is the possibility to automatically
parrelize, and secondarily to make it more readable.

~~~
mabbo
I would take any triply-nested for loops, and reduce each loop to its own
method. Inside that method would be nice, easy-to-understand stream logic
rather than for-loops.

The Java compiler will unroll the methods anyways, so you get easy readability
without any loss of performance.

------
mabbo
95% agree with these opinions, but have a few disagreements, or perhaps the
author had missed some great stuff.

Two main ones: Mockito is, IMHO, much nicer than jMock. And Immutability is
good, but 'final' is... complicated. I find it's often over used by people who
don't know why they're using it.

~~~
lmm
jMock isn't great, but Mockito makes it too hard to understand which method
you haven't stubbed; I find EasyMock with its explicit replay() step much
easier.

~~~
cam-
JMock at least blows up if you don't mock something. Powermock and Mockito
will let it pass. It is a shame JMock's API is so wordy.

~~~
mabbo
That's what I _hate_ about JMock, lol.

You had better mock _everything_ , and better put them in the exact order they
will occur in, or your test fails.

Most JMock unit tests I see are essentially the exact same code as is being
tested, written a second time in the unit test. So if I want to refactor or
modify this code in any way, my unit tests break- even if functionally, my
tests are doing exactly what their spec says.

With Mockito, I can say 'Hey, if anyone calls this method with parameters sort
of like this, give them this response', and then focus on my unit tests
actually testing the output for a given input.

------
trbvm2
Dependency Injection (frameworks) -1

Use constructors. This makes perfectly testable classes and is vastly simpler
than encouraging more XML as code. Any proper dependency injection framework
should work quite well with regular constructors.

~~~
vbezhenar
Constructors have their problems. First: constructor calling is not readable
because Java misses named parameters. It's fine when there are 2-3
dependencies, but not more. Second: circular dependency is not possible. So I
prefer to use setter dependencies, as they don't have those problems.

~~~
trbvm2
I agree on the first. I'm only advocating for keeping the constructor as the
DI entry point. A DI framework can then be used for the convenience they
provide in wiring things up at main.

Regarding the second: I think circular dependencies should be avoided whenever
possible so I view the difficulty constructors create there as advantage
rather than a problem.

[https://en.wikipedia.org/wiki/Circular_dependency#Problems_o...](https://en.wikipedia.org/wiki/Circular_dependency#Problems_of_circular_dependencies)

~~~
benjiweber
By using a DI framework to wire up constructors you tend to use the compile-
time checking that your app is wired correctly. Which is unfortunate. You only
find out when you try to run it.

Perhaps things being too big to wire together manually is a smell that the
application is getting rather large.

There are also other patterns that can be used to make manual dependency
injection less of a pain. I wrote about some of them here

[http://benjiweber.co.uk/blog/2014/09/13/frameworkless-
depend...](http://benjiweber.co.uk/blog/2014/09/13/frameworkless-dependency-
injection/)

------
tigeba
I agreed with most of these suggestions. I'm not sure the suggestion to use a
struct pattern is worth the lack of JavaBeans support in argle support
libraries. You can always use final properties and only provide getters.

I think asserting that Fluent interfaces are 'more readable' or better is
largely a matter of opinion.

------
meddlepal
Some good suggestions in here and some very very bad ones. For example, using
Optional as a member type, tuples etc.

~~~
chii
this details a good amount of the problems with optional, but yet why it will
still be used despite it:
[https://developer.atlassian.com/blog/2015/08/optional-
broken...](https://developer.atlassian.com/blog/2015/08/optional-broken/)

------
tsotha
>Java 8 has a nice stream and lambda syntax. You could write code like this:

    
    
      final List<String> filtered = list.stream()
        .filter(s -> s.startsWith("s"))
        .map(s -> s.toUpperCase())
        .collect(Collectors.toList());
    

>Instead of this:

    
    
      final List<String> filtered = new ArrayList<>();
      for (String str : list) {
        if (str.startsWith("s") {
          filtered.add(str.toUpperCase());
        }
      }
    

>This allows you to write more fluent code, which is more readable.

I don't agree. The second snipped is far more readable. This seems like an
effort to use lambdas just to be using lambdas.

Not only that, but the non-lambda version is far easier to maintain. When you
get exceptions in code that has the form

    
    
      this().that().theOther()
    

it's generally not obvious where the problem is.

~~~
ap22213
A matter of personal taste, but I greatly prefer the lambda style (though I
wish the example had the .stream() on the following line).

I have been coding Java (and C-style) languages for a really long time. And, I
still have some cognitive delay when traversing multiple indented scopes. Not
a long delay, but long enough to be slightly annoying.

With the lambda style, I can quickly glance down the text column to see what's
going on. Stream -> Map -> Filter -> Collect.

After using lambdas enough, one starts to subconsciously cull the stream() and
collect() calls. So, when I look at it, I really see Map -> Filter.

But what really, really annoys me is that exception handling can't be applied
to the whole stream processing statement. This leads to code that looks like:

    
    
        collection
                .stream()
                .map(o -> {
                    try {
                        return o.oToC();
                    } catch(Exception e) {
                        // handle
                    }
                    return new C();
                 })
                .reduce((c1, c2) -> {
                    try {
                        return c1.combine(c2);
                    } catch(Exception e) {
                        // handle
                    }
                    return c1;
                 });
    

For that, I have had to write a bunch of helper functions that wrap and throw
the exceptions.

------
namelezz
I note that it's not safe to pass Java 8 streams around as streams can be
closed when invoking terminal operations. If you pass a stream to a method and
do not know whether the method is going to close the stream, it's dangerous to
reuse it after the method return.

~~~
EdwardDiego
Well, once a Stream has been consumed, you can't use it again. We have a rule
of thumb in my team that our APIs should not consume or return Stream or
Optional.

------
anotherevan
I find lauding use of Optional over null for return values, but eschewing
checked exceptions somewhat inconsistent. The problem with null is it can be
returned anywhere, from any function. It is difficult to generate compile time
errors for if they go unhandled. But unchecked exceptions are great because
you don’t have to then think about them. hmmm.

Addendum: I’m also of the opinion that trying to write java code without an
IDE is highly inefficient. With an IDE, you can locate all the throws you’re
not taking care of quickly, and usually quickly deal with them to get things
to compile. Yeah, it’s a bit of housekeeping overhead, but once they are dealt
with, they are dealt with, even if it is just passing them upstream.

------
jacques_chester
I've worked on two Spring Boot projects so far and written somewhere between
zero and no XML.

------
sigzero
Guava is on github now. Might want to change the link.

------
tootie
I've been using spring loaded instead of jrebel and it works pretty well and
is free.

One thing I'm surprised he didn't mention is exception handling. Namely the
growing acceptance that checked exceptions are dumb. I make a point that
except for a few rare circumstanes, my code should never have a throws clause.
I always created subclasses of RuntimeException (or Spring's
NestedRuntimeException) and use them exclusively. Any libs that throw checked
exceptions get either handled or rethrown with a custom RuntimeException.

------
bluejekyll
As a Java Dev of 15 years, through my own experience, almost all of these
points I have discovered through hard fought bugs and trying to find a way to
reduce the causes of them in the future.

Final by default is the biggest, bc it removes some of the most basic
concurrency errors implicitly. Awesome post. It also is pointing out things
that in some other languages (e.g. Python) are implicitly impossible to
achieve, and others which some new languages (e.g. Rust) have built in from
the beginning, like never use null.

Well done.

------
sandGorgon
What web frameworks are you guys using in the Java 8 world that lets you
leverage newer language features?

Is it still Spring ? Are you guys doing things like Socket.io , etc.

And is Hibernate the preferred orm ? Confession: I'm an ex Java programmer,
who have been working in rails and python for past several years...so am
fairly out of date. I have kept up with things like Dropwizard...but have not
seen many other startups do Java development.

~~~
jacques_chester
Spring is on Java 7 for the 4.x series.

Spring 5 will take Java 8 as the baseline.

------
saveliyb
Nice! Seeing "enterprise" java code anyways makes my blood boil, and I keep
reminding myself that it doesn't have to be that ugly.

------
ryanseys
The only way it seems you can be effective with Java is with an IDE to do most
of the heavy lifting. What would be better is if Java shipped with more
focused command-line tools and better defaults that allow me to productive
immediately without the need to learn something as hefty as IntelliJ /
Eclipse. This could lessen the barrier of entry to Java and widen community
adoption.

~~~
yogthos
Or you could just use modern JVM languages like Clojure.

~~~
EdwardDiego
I like Clojure, but anyway to make it start faster in a scripting context? I
wrote the same script in Clojure and Kotlin, and the Kotlin one loads so much
faster.

~~~
yogthos
There's Planck for OS X
[https://github.com/mfikes/planck](https://github.com/mfikes/planck)

It uses JavaScriptCore and starts practically instantly. There's some work
being done to port it to Linux/Windows as well.

Here's an example:

cat foo.cljs

#!/usr/local/bin/planck

(println "hello world: clojurescript -> planck -> as shell script")

./foo.cljs

hello world: clojurescript -> planck -> as shell script

Planck can be installed using homebrew now as well.

Another promising option is Pixie [https://github.com/pixie-
lang/pixie](https://github.com/pixie-lang/pixie)

~~~
EdwardDiego
Cheers mate :)

------
Randgalt
Nice compendium. I don't agree with everything, but I doubt you can get an
Java devs to agree on everything.

------
whitenoice
For web framework I would also suggest Dropwizard. Its simple easy to use and
robust.

------
incepted
If you really want to describe modern Java, you should probably mention RxJava
and TestNG.

~~~
fizwhiz
TestNG may have been considered a "modern" alternative years ago, but today
jUnit4 has caught up with most (if not all) of testNG's features.

------
based2
Nothing on findbugs, checkstyle, EOL and CVEs?

log4j: now log4j2

jOOQ => $, JPA, MyBatis

------
joesmo
'Formatting is so much less important than most programmers make it out to be.
Does consistency show that you care about your craft and does it help others
read? Absolutely. But let's not waste a day adding spaces to if blocks so that
it "matches".'

I do agree that it's less important, but it's so easy to do that there is no
excuse for not doing it or giving out such rubbish advice. Anyone that wastes
a day on formatting is doing it wrong. The problem with advice like this is
that people take it to the extreme and ignore formatting altogether. That
leads to someone being frustrated and formatting all the files automatically
(as should be done anyway) which then leads to possible conflict and crappy
diffs. Instead, you could have had professional programmers work on these. In
an industry that's touting how code readability is so important (and it is),
this advice is toxic. We're finally getting people to realize that readability
is the most important part for most code because it is. Honestly, formatting
is important in this inconsequential reply, in essays, in everything we write
except short chat messages. Imsurenoonewouldliketoreadsentenceslikethis just
like no one wants to read obfuscated, unformatted, crappy code. So yeah, I
disagree strongly because formatting is important, get one style, get proper
tools to automate it, and then you don't have to spend a day putting in spaces
(which is ridiculous).

