191 comments

[ 17.6 ms ] story [ 4371 ms ] thread
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.
The benefits of streams isn't performance improvements for the CPU, but performance improvements for the developer.
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.

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.

"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... 2 - http://blog.joda.org/2015/08/java-se-8-optional-pragmatic-ap... 3 - http://blog.paralleluniverse.co/2014/05/01/modern-java/

I'm curious, which aspects of An Opinionated Guide to Modern Java have dated?
I'm also not a fan of passing Optionals into methods. Most of the time it's easier and cleaner just to write an additional method without that optional parameter.
It can grow cartesian though.

I think the best compromise is to declare a new data type for the argument, such as:

  data ExecutionDirectory = ExecuteInCWD | ExecuteInDir FilePath
And take an ExecutionDirectory instead of a `Maybe FilePath`.

Of course, you need light-weight data declarations for that.

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.
In other paradigms (Lisps) null is a lot less than a billion dollar mistake, it seems it goes better with map/filter/fmap patterns. In imperative languages, data is tied to control, and null means segfault.
When some ELisp code crashes in my emacs with an error like:

  error: (stringp nil): not a string
I think it indicates Lisps suffer from this problem too...
It does, I said 'a lot less' not 'zero dollar mistake'. Recursively defined lists take care about nil, and since it's one of the most used ways to program in lisp it makes a lot of logic nullproof.
Despite what he says, I don't think Hoare actually invented the "null pointer", as address 0 for "not exists" or "end of list" was probably a common convention ever since linked structures existed and independently discovered by many others. (The other convention would be the all-bits-1 value, but I'd assume that testing for 0 was easier and thus more widely adopted. Also, "0 = nothing" makes great sense.)

IMHO Optional just feels like another typical Java dogmatic overabstractionism. "Null pointer exception? So what? Just catch it." Then again, I mostly use C/Asm.

Given that the Option type has existed in programming languages other than Java for decades I don't think it makes sense to call it a "typical Java" thing.

I can see how a C/Asm programmer wouldn't like it though. Very different mindsets. :)

The difference is that other languages which originally had the Option type don't have null, so it's the only option. I meant it's typical of Java to take features from other languages, resulting multiple slightly-different-but-incompatible ways to achieve the same thing.
I certainly agree that Java would be a much better language if NULL could be eliminated completely. Backwards compatibility though...

sigh

Yeah, Optionals came from other languages, not originally Java.

IMO the problem with Optionals is that they'll never suffice unless they are part of the language itself, like in Swift. As this article pointed out, Optionals aren't supported in any existing APIs, so you still have to do a ton of null-checking everywhere. And there is nothing that guarantees an Optional reference itself can't be null, which is why you really want language-level support.

I'm probably being a bit too pedantic here, but strictly speaking they don't need to be part of the language at all. You just need basic support for (generic/parametric) algebraic data types.

For example, Haskell has Maybe which is not part of the language nor treated specially by the compiler in any way. It is part of the Prelude (think "standard library"), so that (basically) all libraries can agree on what "Maybe a" means.

By all means, have more clumsy, less straightforward ways to represent the lack of a value in your code, because Tony Hoare says so.
An Optional type is more clumsy than null checks and null returns sprinkled everywhere??
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.
A NullPointerException is unchecked as well. I would say about 40% of our code is checking for null to avoid NPEs especially with APIs. You have to protect yourself and cannot take nothing for granted.
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.

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.
(comment deleted)
Watching the evolution of languages / APIs makes me believe that Optional over-use is a necessary step between "our language has no formal Optional therefore crash" and "our language uses null in a sane manner".

C#'s prior behavior gives me hope for languages I'm currently paid to care about like Java and Swift on this issue.

When I get some time I'll update the OGMJ. I think the choice of tools mentioned is still very much up-to-date, it's just that some of the APIs used in the examples have been upgraded.
I really like OGMJ, it's definitely a great resource and I recommend it to many new Java developers; however, I disagree re: tools mentioned.

After trying dropwizard for a few projects, the superiority of the spring-boot and its various ecosystems just blew me away.

Also, while I appreciated Gradle, Maven is just much more supported through the entire eco-system. As a new comer to Java from C++/Python, it made a big difference.

You're probably right about Spring Boot. I've never been a web developer, and TBH, I've had no direct experience with either Boot or DW other than a simple Hello, World. At the time DW seemed the safer choice simply because it used the JAX-RS standards, and using standards in the Java world (especially good ones like JAX-RS) is a very good idea. But in the meantime Spring Boot has also done the right thing and adopted JAX-RS (at least as an alternate API), so I should add it to the post.

As to Maven vs. Gradle, that turned out to be the most controversial point of the entire guide -- which surprised me. Let me put it this way: both are good and I prefer Gradle. Also, Gradle, while still far behind Maven in terms of adoption, has good momentum. Either is a good choice at this moment, but I would guess that Gradle will take the lead in five years (although it's far from a safe bet).

5 years is a long time in IT. Gradle has a millstone called "Groovy" around its neck because of an early poor choice to ship with only one configuration language. Maybe they'll enable more languages to be plugged in later on, but there's an ex-Pivotal programmer who used to work on Groovy now working at Gradleware on Gradle who might sabotage such an effort because of his lingering association with Groovy.
> Maven is just much more supported through the entire eco-system

Could you give some examples? I haven't had much problem with Gradle support, and Gradle's essential advantages over Maven fat outweigh what little I have had.

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
That reminds me of "constant interface" anti-pattern - abusing a feature because it brings a small technical benefit.

If you are unhappy with candy-shop utils class and are ready to split them into smaller entities, go the whole way there. Create proper small classes, and inject them using your chose DI technology.

Anyway, kudos to the author, that was a risky article to put together and there was no way to write it without controversial recommendations. That's a good start for what a new java developer need to look for.

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.
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.
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.

Inheritance over composition. I know what these words mean, but I don't see your meaning.

Also, I don't think that's what default methods are for. The new StreamUtil libraries uses default interfaces. It's not migrating anyone, but the default methods describe intrinsic properties about the classes that inherit the interface. A predicate can be in sequence of another predicate, for example.

Guava is on github now. Might want to change the link.
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-...

>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).

I would question these results. I ran the same code on a more modern processor (i7-3930K) for 1000000000 iterations and got these averages over 10 loops after a warm-up:

Array: 453 ms Stream: 887 ms Parallel stream: 120 ms

The array loop code is about twice as fast as the sequential stream (parallel stream blows both of them away). The array loop advantage will start to go away once you increase the complexities of what you're doing in the loop and, of course, the stream code is much more readable.

(Edit: I also tested IntStream().of() instead Array().stream() for the sequential stream test, the results were identical in both cases.)

Nice compendium. I don't agree with everything, but I doubt you can get an Java devs to agree on everything.
>> 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...

Not sure how you get that reading... the author makes no claim that Spring is limited to XML configuration. In fact, in the paragraph just before the one you quote:

> It [the Spring framework] has a either code-based wiring or XML configuration-based wiring.

I read the paragraphs a little like "Spring has code-based config and xml-based config (careful with the xml-based config!) Guice and Dagger don't have xml-based config, so use Guice or Dagger". My gripe is with the hand-wavy treatment of why Guice/Dagger are better alternatives just because they don't have xml-based configs even though the author knows that people can use Spring exclusively without xml-based configs (this is why i said it was disingenuous)
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.

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...).

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.
Or you could just use modern JVM languages like Clojure.
Lisp? Lisp syntax makes less sense than lambda and stream which have ruined Java.
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.
There's Planck for OS X 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

What would you use instead of an IDE? Learning Intellij is a lot easier than learning Vim or Emacs.
The command-line tools are fine. And Java is the most adopted language in existence.

The problem with writing Java without an IDE isn't one of tooling, it's that the language is so very verbose. They're working on that with lambdas and generics inference, but there's a limit to what you can do and remain backwards compatible.

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.

Nice! Seeing "enterprise" java code anyways makes my blood boil, and I keep reminding myself that it doesn't have to be that ugly.
If you really want to describe modern Java, you should probably mention RxJava and TestNG.
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.
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.
then you suddenly force anyone who uses your code to depend on lombok. I tried to find a compile time only mechanism for lombok - not sure i found it, but it ought to exist!
Lombok does rewrite bytecode at compile time only. Your dependencies will not have to depend on Lombok.
Thats one of the things that'll happen to you if you start writting groovy code. The whole setter/getter boilerplate thing gets really annoying.

Another groovy-ism.. the whole deal with having to copy properties. (In a groovy class they're threated like a map)

> properties. (In a groovy class they're threated like a map

Except in hard to remember special cases like .class which gives the class "LinkedHapMap" of the map object instead of the value at key "class". After working with Groovy for a short while you'll realize you're really working around it.

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.
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!
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.

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.

> Sometimes you want a computed property and you use non-trivial getter

Then pre-compute it, make it immutable, and expose the variable. And if that ends up being too hard it's probably because you need a builder and/or to group your properties into smaller classes.

Precomputing properties on a hundred million object instances is not cheap.
Going from C# to Java, one of the biggest things I miss is the Property syntax.
C# property shares its own set of issues , especially when there are exceptions involved.
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.
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.
I'm surprised I haven't seen anybody mention the "public final fields" approach yet. I use this myself for immutable objects and I quite like it. Granted, you still need to implement equals and hashcode, but these can be generated easily and verified with tools like EqualsVerifier [2].

[1]

  public class MyImmutable {
    public final String field1;
    public final int field2;

    public MyImmutable(String field1, int field2) {
        // assign
    }

     // equals, hashcode, toString
  }
[2] https://github.com/jqno/equalsverifier
Also, whatever stylistic issues are raised by JavaBeans are largely obviated by modern IDEs.
> Spring binding

Not sure what in particular you're referring to, but Spring supports constructor based dependency injection, and I tend to insist upon it vehemently - getter/setter injection means that you can instantiate your object in an invalid state.

The problem comes when you spot a Bean class and then it isn't. 99.9% of "getX" methods simply read the field. But if you assume that every "getX" method just reads the field, you'll be caught out by the rare one that doesn't - I've seen a production bug happen this way.
Lombock is one of the most valuable enhancements to Java. Without it, it would make Java development not as fun.
Lombok is also a non-standard dependency and there are costs with having to rely on it.
If the cost overweights the benefit you can delombok everything will works as before.
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.

Your comment is unclear. Are you encouraging people to NOT use DI frameworks, or using them only with constructor-based injection?
The latter. DI frameworks are a convenience item, they should probably not have a big effect on the way the code is written. You get most of the benefits of DI just from not new'ing up things within your classes.

The main advantage of keeping the constructors around is that you retain more flexibility in interacting with that bit of code.

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.
> First: constructor calling is not readable because Java misses named parameters. It's fine when there are 2-3 dependencies, but not more.

If you have more than 2-3 dependencies, it might be time to refactor things, as your class may be doing too many things.

> Second: circular dependency is not possible.

Circular dependencies are possible with constructor injection when using a DI framework (e.g., using a Provider in Guice [1], or the equivalent in Dagger).

[1] https://github.com/google/guice/wiki/CyclicDependencies

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...

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...

Constructor calling is readable either with an IDE, or using distinctive types. If the constructor is unclear, it's a smell.

I'd also say that making circular dependencies not possible is a feature, not a bug. They go against everything we've learned about computing in the last 20 years. Entire languages do not have variables, or at least heavily discourage them, and the gains outweigh the costs.

Setter dependencies have other major disadvantages, like how easy they make creating partially initialized objects: Refactor something in one place, adding a parameter, and good luck making sure that the change is made everywhere else. A constructor guarantees fully initialized objects, and that's a great things.

Java pays for the mistakes of the early 2000s: The Java Bean pattern, and all the infrastructure around it, makes Java code be full of default constructors that force us into mutable objects and nullable fields.

If there is a defense for your argument for setter dependencies, is that we cannot count on any of the nice things that come with, say a Scala case class, because so much Java code out there is built with standards from a less enlightened era that using what would be better standards in any more modern language leads to inconsistencies, due to all the ancient code using Spring, Hibernate, Guava and EJB code that is hanging out there, and that would lead to inconsistencies for those trying to make Java actually use some of its new functional programming inspired features.

I'd rather inject some lazy somethingsomething-provider reference wrapper to break the occasional circular dependency than work with a bunch of nonfinal references that supposedly never change, because DI, but are otherwise indistinguishable from true working state.
I think people use DI just because Java constructor syntax is so incredibly verbose:

    public class MyClass {
      @Inject private String foo;
    }
versus

    public class MyClass {
      private String foo;

      @Inject public MyClass(String foo) {
        this.foo = foo;
      }
    }
Dependency injection is brilliant for testing. Prior to DI you often has to have two constructors, one for prod, one for testing. DI took that away.
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

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.

I realize he mentions Lombok, but he specifically bemoans the extra boilerplate with writing builders and data classes, but does not mention the @Data or @Builder annotations...
The other replies kind of hit on this, but I'll expand on it by saying:

The collection creation methods existed because Java could perform type inference on methods but could not on constructors:

  // Java 1.5
  Map<String,Integer> map = new HashMap<String,Integer>();
  // Guava
  Map<String,Integer> map = Maps.newHashMap();
  // Java 1.8 diamond notation
  Map<String,Integer> map = new HashMap<>();
Immutables (http://immutables.org/) is another option which creates nice, immutable value classes. It's a bit more succinct than AutoValue, but it does still require annotation processing in your IDE.
Lombok's a bit sketchy as parts of it rely on some undocumented, non-standard parts of the Sun Java compiler - you have to be really into code generation to want to use it.

Other libraries like Immutables are safer for this purpose.

Wouldn't the best way to create an empty map be to use `Collections.emptyMap()`?
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/

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.

> 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.

Have you seen Goldman Sachs collection library? I've been using it for my Java work for last year and found it to work well. Put's a lot of useful methods onto the Collection objects themselves.
'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).

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.
Mentioning Scala, or clojure or even Haskell to a HR interview leads to raised eyebrows at best. But that was expected. I'm surprised actual devs are still wearing eye blinders.
I'm hiring front end JavaScript developers right now. If I see other language experience on their resume, they're getting a call. My last hire had worked through "Learn You A Haskell" and that was enough for my interest to be piqued. Seeing Python, Ruby, C, ObjectiveC, heck even PHP is enough for me to see they're not just a "I did some Angular tutorials" type of candidate. I'm on this site, so I get a nice smattering of different technologies. I don't write Rust, but I know it exists. I've read about it. Same goes for a ton of other technologies/languages/methodologies that I don't deal with. It just floors me that anyone in the development/engineering world doesn't do the same! They must believe their language/tech will exist forever.
I've always been surprised when I run into developers who really don't have an interest in multiple languages, platforms, whatever. But, I think it's something you come to understand, that every profession has people that are just phoning it in every day. Some of the best people I've hired have had no experience in the one technology that I'm hiring for, but their enthusiasm and level of interest has been more than enough for me to want to take a chance on them. It usually works out well.
I should have added that it was IT consulting shops HR I was referring to, not final clients. The further away from the actual jobs, the more buzzwordy it gets. Some might appreciate curiosity and diversity, but in the end they want simple and bankable. They told me, some missions will enjoy jack of all trades type, but the majority of their clients wants framework-specific forces.
What a curious comment. The first portion of your diatribe disparages all java developers, but the latter part of it suggests that you're still working in java shop (perhaps in an ops capacity?) I'm wondering what you meant by JVM 8 because no such thing exists (unless you were talking about the JDK or the JRE.)

You must have worked at some sweatshops to spout such biased vitriol.

Well, I was an English major, so I'm glad you were engaged by the "diatribe". And if you were unable to piece it together... and I kinda feel bad if you couldn't. I'm referring to Java 8 language features and OpenJDK 1.8. I get the feeling you knew that though and are being pedantic. You've succeeded though, because I responded.

Sadly you missed the part where I said, "Not all Java devs obviously". I have read great blogs by Twitter engineering and many others.

But, since you seem to have some experience in sweatshops, please explain how your current situation is different. Add something to this conversation instead of correcting my stupid generalizations.

Your comment about the "JVM update" was a non sequitur trailing from your rant, but I'm glad to know that you were indeed referring to JDK 1.8. The fact that you get excited in the event these nebulous java devs have "heard" of Clojure/Scala only comes across as patronizing (but I suspect you weaved that in masterfully and deliberately, given your degree in English.) Your anecdotal fallacy hasn't added anything valuable to this conversation (your parent comment admittedly claims the original having "stupid generalizations"). Most of the other comments here on HN are discussing specifics outlined in the article, but it's evident that you don't have anything meaningful to contribute in that area, which is a shame because it appears that you value polyglotism so one would think you could offer your "enlightened" perspective around best-practices which could help the community in a more meaningful way.
You have won at the internet. I'm sure you're a joy to be around. I haven't seen the meaningful response that you've added. You really do seem like a troll. If that's not your intention, that's cool. If it is, well, hey, happy trolling dude!

Edit* Yep, just checked your comment history, you're a troll. God why do people like you exist.....

Personal attacks are not allowed on Hacker News. Regardless of whether you think someone is trolling, a comment like this makes the thread obviously worse. Please don't do this here.
Agreed, may I edit or delete this response?
While you're reviewing these, you should probably take a look at your original post which got you in this thread of poo-flinging to begin with. It doesn't address the article at all. It just says 'grumble grumble, those Java people!'. It's content-free flame bait that produced predictable responses such as 'And those PHP people!' and 'I'm a Java person and you, Sir, are an ass'.
But this is the point. Now you've felt the need to teach a lesson... which also has nothing valuable to add. I feel like any conversation on Java or newer Java does lend itself to my point. If we can't add any personal experiences to these stories, then why do we have a comments section? I know it's not just so we can post links to other facts. And no, I'm not stuck in this thread. I'm trying to do the fair thing and remove a response to a personal attack and name-calling (which was mine). I stand by my initial statement. I work in an environment where a ton of Java devs don't understand why the pesky front end people keep asking for these RESTful JSON APIs. "Why can't we just do some JSPs and give you an XML/XHR when you need a hint of dynamic-ness?"

This is what brings on personal attacks. The attitude in which you post. If you fail to see my original point, ask for clarification. It would have caused me to edit my original and change my tone.

The point was 'if you don't want to feel embarrassed by things you post in flamethreads and have moderators berate you, don't start flamethreads', that is all.

Take a look at the top comment in the thread for a) an actual substantive criticism of the article b) a link to a much, much better survey article on the same topic.

We're always happy to help with that, but can you please email hn@ycombinator.com about it? And thank you for the polite response—I really appreciate it.
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

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.
On the flip side, the best practice for both Java and PHP is trending towards the same thing. Routes + DI + immutable types + fluent api's. Give it another decade and the only way to tell the difference will be the presence of $ characters.
Even worse, the Java 1.4 world. I've seen people avoid generics and other Java 5+ features for "compatibility reasons".
Wow, you didn't even get forEach with 1.4, right???
People get in the habit of writing loops with indices.
I still people doing that shit in Java 8 and Groovy... I can probably count on one hand the situations when a counter-based loop is necessary.
> I can probably count on one hand the situations when a counter-based loop is necessary

Such counting is analagous to counter-based looping. If you'd said "I can probably filter down to the fingers of one hand..." I might have believed you.

That's a shame. Java is my favorite language because it has the right balance of strictness (although Go is starting to take over for me). When written correctly, Java can be amazingly productive because you learn so much at compile time but the tools (IDEs) make it so that you can autocomplete away most of the verbosity.
Java as a language is totally fine! It has everything one might need. The culture totally sucks. Oracle leads the march toward what is the "standard". Jersey is a great leap out of this.
Java lacks higher-kinded parametric polymorphism.

Java also lacks the ability to say something like:

  class Foo<T> implements ISerializable iff T implements ISerializable
So you end up having to work only with T's that are serializable, or not having the instance for Foo.

Also, Java lacks type-classes.

Java also lacks lazy bindings, and many other useful features one might need.

In short, Java is still very far from having everything one might need...

I consider Jersey to be a good example of what is wrong with Java. Annotation driven APIs don't really lend themselves to composability - sparkframework, vertx or ratpack are much better ways of building REST apis with Java 8.
Using the annotations could probably be done a different way, but it follows many of the popular micro-frameworks like Sinatra for Ruby, or Express for Node.js.
What do you mean by: "you learn so much at compile time"?

I'm a C and C++ guy, but I've done a tiny bit of Java a while ago.

A lot of mistakes are picked up before the devs can even compile their project. (Note that I did not say "you". I guess pro C and C++ coders are a lot more thoughful about their code and therefore don't that level of static checking.)
I have a hard time believing that a company stuck on Java 1.5 or SVN is like that because the developers want it that way.
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.

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

Spring 5 will take Java 8 as the baseline.

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.
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.
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.

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...

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.

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.

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.

Can you expand on the later point about final please?
tl;dr: final parameters != immutable and safety, and they look like they ought to.

A lot of people write "final" in front of every. single. declaration. And they do that because someone once told them that was good. But then you remember that Java is a language which all non-primitive types are passed by reference, so your 'final' is actually a final reference and not a const immutable object, like you might get in C.

If someone passes in a final FooBar to a method, and you mutate the FooBar during the method for any reason, then after the method is done the object remains mutated.

Just this week, that exact problem caused my team an entire day of headaches. Two methods were being called concurrently using Futures, passing the same object to each method. One method mutated the object slightly, the other relied on it having not been mutated. Hello race condition. I was so proud to have solved it, until I realized I'm the dolt who wrote the bug in the first place.

Silly, I know. But the point is that final makes you feel safe when you might not be.

> If someone passes in a final FooBar to a method, and you mutate the FooBar during the method for any reason, then after the method is done the object remains mutated.

Fair enough, but if FooBar is your class there's an easy fix for this - make FooBar immutable. If it's not, make an immutable wrapper object for it.

Very true that relying on untrue assumptions about the immutability of your data will cause hard-to-spot bugs, but the solution is then just to guarantee everything is immutable, and define that as an assumption that cannot be false if everyone on the team follows the pattern.

If somebody does break the pattern, then that, rather than the race condition down the line, is the real bug. The dev who wrote the mutable data class can just have that (re-)explained to them, so it doesn't happen again.

i wish java had designed final to be semantically const just like C++ (but without the type level breakages that seems to happen in C++).
C const doesn't mean immutable either, and I suspect most Java programmers have no exposure to it in any case.

Honestly I don't think final ever makes things worse. I struggle to imagine someone who would misunderstand in the way you describe having any success in Java - references are a pretty fundamental part of the language.

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.
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.
Like I said, Easymock. Powermock has an Easymock API too if you need the mocking statics/object creation.
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.

Eesh, let's agree to disagree. EasyMock has some advantages, but I find the readability of Mockito outweighs them.
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.
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.
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.
If you have required parameters in a Builder, you're doing it wrong.
> Now, you have to look up the Builder's methods to make sure you've filled in all required fields.

the builder should fail with a good error message if there are required fields you didn't supply to the builder.

This doesn't solve the problem where the parameters aren't checked at compile-time. Now, hopefully all your codepaths are tested so your builder doesn't throw exceptions in production.
You can have a type-safe fluent Builder, but it requires having one or more static nested classes with private constructors. The outer class will not have a build() method, but rather that method will live in one of the nested classes. You use the type system to control what parameters have already been set, and what parameters need to be set.

Obviously, this can apply to many sorts of fluent API. This is at least part of what Tony Morris is alluding to in his essay on API design [1].

[1] http://blog.tmorris.net/posts/understanding-practical-api-de...