
Java Doesn’t Suck - craigkerstiens
http://www.jamesward.com/2014/12/03/java-doesnt-suck-youre-just-using-it-wrong
======
philsnow
> It would have been much better to utilize environment variables so the only
> thing that changed between environments was those variables.

I strongly prefer commandline arguments to environment variables: They're more
transparent, easier to reason about ("what's running on this server? `ps`...
oh, that process there is running in the staging configuration instead of
production"), and it saves useless sudos (/proc/<pid>/environ has mod bits
0400, so if the processes you're investigating are running as separate users
(and they probably should be), you can't inspect the actual environment that
the process has, so you end up sudo'ing to check the environment out when you
should have all the information you need in the process list).

If the environment variables are just interpolated into the run script by the
deploy and then all passed to the process as arguments, that works too.

~~~
curun1r
On the other hand, environment variables are useful for things you
specifically don't want showing up in ps. If you've got to supply credentials
(passwords, tokens, certificates, etc) or anything else that requires a
modicum of security, it's much better to pass those in as environment
variables rather than command line arguments.

~~~
philsnow
Please keep in mind this point called out by wereHamster elsewhere (
[https://news.ycombinator.com/item?id=8695887](https://news.ycombinator.com/item?id=8695887)
):

> env variables are inherited by children, which may be relevant if the app
> forks

If your app forks (or any of the multitude of libraries that it may depend on,
check and _pin_ your sources (so they don't add un-audited behaviors)),
whatever process it execs probably will get a copy of the environment of your
process.

Yes, it's possible to clean the environment between the fork and the
exec/execve. Do all / most frameworks do so or make it easy to do so? I'm not
sure, but would check before making any assumptions about it.

I was about to suggest that sensitive information like credentials would
better be kept in files that are referred to by name in command line
arguments, but... unprivileged users cannot fork/exec a process as a different
user, so children could read all the same files as the parent.

I can hardly believe it, but a plug for my masters work [0] is actually
relevant here. I was interested at the time in the intersection of HCI and
security, so I made up this thing called sub-identities that let unprivileged
unix users create sub-users. It's a really watered-down version of some actual
research that's been around for a while, but the point was, it was easy(ish)
for the average unix user to use. I don't pretend that it was anything but a
toy, though.

All that said, it seems that passing sensitive information in environment
variables, squirreling them away in the process space somewhere, then cleaning
the environment (all right away, during initialization) would be a smart thing
to do.

 _edit: see `man 3 unsetenv` for how to do this_

[0] [http://ccl.cse.nd.edu/research/pubs/snowberger-
thesis.pdf](http://ccl.cse.nd.edu/research/pubs/snowberger-thesis.pdf)

~~~
Crito
> _" Yes, it's possible to clean the environment between the fork and the
> exec/execve. Do all / most frameworks do so or make it easy to do so? I'm
> not sure, but would check before making any assumptions about it."_

It might be better to wipe the contents of the environmental variable
immediately after reading the value in it (presumably done at startup, or
close to it).

------
api
TL;DR: Java as a language is not bad. The problem with Java is its bloatware
ecosystem. Endemic to the Java world are uninstallability, Rube Goldberg
machine code, and such heights of over-engineering that they're easily
parodied:

[https://github.com/EnterpriseQualityCoding/FizzBuzzEnterpris...](https://github.com/EnterpriseQualityCoding/FizzBuzzEnterpriseEdition)

I think the over-engineering is an unintended side effect of Java's most
attractive features: incredibly stable standard ABIs, portable byte code,
fantastic tooling, and a language that makes byzantine abstractions relatively
easy to implement without the instability you get in C++ or the
unmaintainability you get in dynamic languages. Sometimes you actually do need
very high level complex abstractions, so this makes Java a fantastic language
for those cases. But those cases are rare. Java makes it easy to build towers
of babel that stand up, so they happen.

Java can be fine if you exercise discipline around complexity. Java coders
need YAGNI and KISS tattooed on their inner eyelids more than coders in other
languages.

~~~
Iftheshoefits
Anything can be parodied by exaggeration. One could provide a github parodying
any language:

C: pointers-to-pointers-to-functions, type puns, and quasi-opaque "types" with
really_long_identifiers_t everywhere (among many other possibilities, and
bonus points for numerous reimplementations of basic data structures tailored
specifically for different types without significant performance gains)

C++: see Java, but in C++ form; or alternatively larded with metatemplate
programming

perl: write any valid perl, because it parodies itself

python: mishmash classes, functions-as-stateful-objects, and n-levels of
decorators everywhere, and toss in some metaclass programming for giggles

And so on.

(Note: my favorite language to program in is currently C++, and I'm well aware
of the less desirable traits of the language and codebases that exist.)

~~~
userbinator
The difference is that with Java, the tools available allow creating immense
complexity very easily - and due to how that complexity manifests itself as
the complexity of the entire application, each individual piece still looks
simple. A parody Java application resembles a real one more than the others
you mention, which are more in the "clearly obfuscated" category.

~~~
CountHackulus
So what you're saying is that the tooling for Java is more advanced than the
tooling for other languages. I'm not sure I see this as a negative. I did node
dev for a while, it was horrible, no tools that were any good, got a memory
leak? Have fun!

Had a memory leak happen in Java once, had the proper tools already, didn't
have to interrupt a live server or anything, plus the tools were easy to use
and well documented.

Really the problem is that when you program in Java, you need to restrain
yourself. You could create another level of abstraction, or you could just
solve the problem at hand and abstract it later when you find a concrete case
for it. And guess what, when you get there, you've got excellent tools for it.

------
barrkel
My company is doing most of these things (except it's more complex because
we're polylingual, and don't use Java for web apps), but Java still sucks.

The reason it sucks has more to do with the language and the culture that has
grown up around it, than the mechanics of building and deploying that this
article talks about. These mechanics have to be solved for most languages.
They're table stakes; mostly just a basic level of usability from which you
can start to measure against other things.

If I had to name the single worst thing about Java, it would be the tendency
for business code to degenerate into a 1:1:1 ratio of interface:class:public-
method. For any significant piece of logic, it ends up living in a class on
its own, with its dependencies injected either via constructor parameters or
method parameters. Whether the constructor or method is used doesn't really
matter, unless the method is to be called many times, in which case the
constructor acts as a kind of partial application. And of course the class it
lives in needs to be the only implementation of a corresponding interface,
which only has a single method, the method in question. All other interesting
methods this method calls must in turn be called via single-method interfaces,
with these interfaces injected via parameters, one way or another.

The cause of this is a religion around a particular style of testing. The
development driven by the need to create tests for everything leads to code
that has very little cohesion, very little structure, and most closely
resembles 80s procedural code, but with vastly more ceremony. Code is hard to
browse and read because the link between method call and implementation is
hidden in a runtime indirection via an interface reference. This lack of
legibility in turn encourages doing more work in these methods (albeit broken
out into private methods), and instead of an OO decomposition of the problem,
you end up with a poorly factored procedural decomposition.

The biggest symptom is classes with names that are close anagrams of their
primary method. For example: StaleJobsCleaner.cleanStaleJobs,
StaleJobsFinder.findStaleJobs, JobDeleter.deleteJob,
JobDepedencyFinder.findJobDependencies, etc.

~~~
michaelochurch
_If I had to name the single worst thing about Java, it would be the tendency
for business code to degenerate into a 1:1:1 ratio of interface:class:public-
method._

I agree. It's ugly and hard to maintain. Most enterprise Java usages of
"design patterns" are unnecessary cruft. This is where I step back and say,
"what you really want is a function".

The argument I tend to make for functional programming is that it only has two
design patterns: noun (immutable data) and verb (referentially transparent
function). And even though it's very rare that pure functional programming is
used, mutable references (e.g. TVars for STM, reference cells like IORefs) are
just "noun-plus" and _actions_ (e.g. m a for some monad m) are just "verb-
plus". It's easier (read: possible) to reason about the complex stuff if the
simple stuff is done on a sound foundation.

~~~
ThrustVectoring
Even object-oriented programming is made better by importing functional
concepts. Python's take with "classes are simply functions that return
objects" is much cleaner conceptually than the "everything is an object and
objects do everything" pattern.

------
lostcolony
I'm confused about the title of this. I've never heard an argument that went
"Java sucks because you are forced to (thing on this list)".

It's always been "Java sucks because it lacks (thing it certainly lacks)" or
"Java sucks because it forces you to (thing it certainly forces you to do)",
or, closest to this article, "Java sucks because it encourages you to (bad
practice, such as those mentioned in this article)". None of these does the
article refute.

I've seen places that used Java, and had most of these, and places that used
Java and had little of it. I've seen places that used other languages that had
all of these, and other places that used those same other languages that had
none of it. This seems kind of orthogonal, and as such a bit of a strawman; is
it in response to some specific arguments I've just not heard?

------
michaelvkpdx
Java doesn't suck, not at all. I still find it to be the most productive
language for developing systems big and small, mostly because it's well-
understood, the pitfalls and traps are well-known, and the community is
extensive and supportive, for the most part.

Java got a bad rep because in the late 90's, enterprises hired anyone who had
the word "Java" on their resume, with no real assessment of their actual
proficiency in the language or programming skills. As a result, there was
probably more bad code written in Java than any other language in history
(including VB- you just can't write as much bad code in VB as you can in Java
if you really (don't) know what you're doing).

Much of this bad code ended up running flaky enterprise systems. So much bad
code ended up in closed-source products (like Websphere, and like many JDBC
drivers) that were sold to people who didn't really understand technology (but
knew Java was sexy!) that Java itself got a bad name.

No, the language isn't perfect. But with all the lessons learned, and with the
great developments in Java since Oracle took over (I cannot believe I wrote
and believe that now), I contend it's perhaps the single best language for
general purpose software in 2014.

The things James talks about in this article are all big problems that have
less to do with the language than with the poor development practices that
became so endemic to the community as a result of the rush to hire anyone with
a pulse to be a Java programmer 15 years ago.

~~~
hawleyal
List<String> list = new ArrayList<String>()

Please make me type more redundant words.

~~~
esfandia
It's a bit better since JDK1.7 introduced a modicum of type inference:

    
    
      List<String> list = new ArrayList<>()

------
tacos
It's hard to imagine someone who wouldn't be turned off by the tone of this
article. Kicker is the quote at the end: "If you are in a typical enterprise
then maybe you are lucky and already doing most of this." I went looking for
sarcasm twice and still couldn't find it.

Java enterprise shops are not using git and JRebel and Play Framework and
continuous deployments and 2 week sprints and reactive development refactoring
boilerplate into lambdas.

Nor are they "mocking" amazon web services for ease of local developer
testing. And a request to your boss to write the next services layer in
"Kotlin" is likely to be met with the slap it deserves.

~~~
pron
The following companies are Java shops (i.e. they use it for all/most/huge or
very large part of their coding effort): Google, Amazon, IBM, Oracle, Twitter,
Netflix, NASA, LinkedIn, Boeing, Raytheon, Twilio, Box and the list goes on
and on and on. In fact, you'll be hard pressed to find companies working on
large scale projects that _don 't_ use Java in any way (Microsoft, GitHub and
Stack Exchange are notable examples -- there aren't too many more). Even
Facebook, which isn't a Java shop, uses Java quite a lot for their analytics.

Pretty much all air-traffic control and defense systems in the Western world
are written in Java (those of them written in recent years). In fact, every
piece of software you really rely on (probably without even knowing it),
there's a very good chance it's written in Java. Hell, there's even embedded
avionics software written in Java nowadays[1]. So you'll be surprised what
many different kinds of tooling -- both modern, super-modern and less so -- is
being used in Java shops. Some use hard realtime GCs, some use really advanced
model checking (NASA has built an awesome Java model checker), and yeah, many
use Git. And even if many of them don't -- the work they do is so important,
that I could really care less whether their SCM is hip or not.

[1]: [http://www.atego.com/products/atego-
perc/](http://www.atego.com/products/atego-perc/)

~~~
pkinsky
Twitter and LinkedIn are Scala shops, not Java shops.

~~~
cgh
I worked on a large Java application at LinkedIn so in my experience, LinkedIn
is certainly not Scala-only.

------
bkeroack
The problem is not necessarily with Java or the JVM as a technology, but
rather the "Java shop culture"[1] that often goes along with it. Although I
would call it "Enterprise shop culture" instead, since it seems to stem from
people who (sometimes unknowingly) perpetuate big company politics and a
consultant attitude, even in startups.

I've found "Java shop culture" in non-Java places as well--C#/.NET for
example.

1\. [http://michaelochurch.wordpress.com/2012/04/13/java-shop-
pol...](http://michaelochurch.wordpress.com/2012/04/13/java-shop-politics/)

~~~
georgemcbay
Yup.

Java as a runtime is a really nice piece of technology, Java as a language is
pretty good, if a bit dry.

It is the heavy-weight anti-YAGNI ecosystems that grow around it (the
AbstractFactoryFactoryManager APIs that these Java shop cultures tend to
produce) that makes working with Java suck, in my experience.

And yes, that stuff can be avoided if you aren't stuck working on a
maintenance project and you are really careful to smash down any signs of that
sort of culture growing when you see it.

------
kllrnohj
> The blocking model limits parallelism, horizontal scalability, and the
> number of concurrent push connections.

[citation needed]

Seriously, where are the benchmarks? I see lots of claims of threads being
slow and heavy (see also every time green threads comes up), yet... they are
not. And every benchmark I've seen shows that, _gasp_ , kernals are really
fucking good. And library-of-the-week's greenthread kernel is not.

The author then says you should use NIO. But, well, NIO is slower than
blocking IO. A _lot_ slower:
[http://www.mailinator.com/tymaPaulMultithreaded.pdf](http://www.mailinator.com/tymaPaulMultithreaded.pdf)

So if you're using NIO instead of blocking IO threads, well, say goodbye to
25-30% of your throughput. But at least you got to feel all clever using
unnecessarily complex async programming, so that's worth it, right?

~~~
sehugg
Each thread has a minimum stack size which can grow memory quickly if you're
using 10k's of threads. Using an async framework like Netty gets you into 100k
connections and beyond. (Not that it's always the right thing to do unless you
have lots of long-lived requests)

~~~
kllrnohj
Like all virtual memory the stack isn't actually allocated until it's used.

So, no, that doesn't grow memory quickly. And while it's great Netty will get
you to 100k connections, you can totally have 100k real threads on Linux. In
fact, as far back as 2.5 in 2003 starting & stopping 100,000 concurrent
threads took just 2 seconds with the introduction of NPTL. CPUs & memory have
gotten a smidge faster since the Pentium 4 days so that time has almost
certainly dropped significantly.

~~~
sehugg
But the stack _will_ be used for each request, especially in Java app servers
where stacks are often dozens of frames deep. The lowest stack size I could
get away with for Tomcat 6/JDK 1.6 was 128 KB.

Sure, you could do better with a lightweight C/C++ solution.

------
dschiptsov
Why not, you have started it.)

Before down-voting and replying, please, copy and paste examples from the
Rosetta Code website, which would prove my statements to be incorrect.

1\. Syntactic noise. 2\. Verbosity. These gives us lots of cryptic lines of
code, full of design patterns and other kluges. This is also related to the
two below: 3\. Over-abstraction. 4\. Everything must be a member of a class.
These two are simple and straightforward. These few pages long stack traces is
a result of these unnecessary method calls. 5\. Static typing makes our code
safe. This nonsense results in even more lines of cryptic code ("generics")
and even longer stack traces.

I am not talking about XML configs, over-"engineered" components (beans,
servlets, etc.)

Here is a lemma: Any algorithm (at least those represented on the Rosetta Code
website) could be coded with less lines of code, _less words per line_ , less
"special symbols" (with much better readability) and executed with less memory
waste (this one excluding scripting languages for obvious reasons) _in any
other mainstream language_. Period.

Sure, Java does not suck. It is stupid us, who are unable to "get it".

~~~
Crito
Not that I typically defend Java, but I think that (going by your Rosetta Code
algorithm comparison test) Java fairs well against a few mainstream languages:

Rosetta Code's Java Quicksort:
[http://rosettacode.org/wiki/Sorting_algorithms/Quicksort#Jav...](http://rosettacode.org/wiki/Sorting_algorithms/Quicksort#Java)

Not great, that first line is a wreck in particular, but not terrible either.

Compare that to this though:
[http://rosettacode.org/wiki/Sorting_algorithms/Quicksort#C.2...](http://rosettacode.org/wiki/Sorting_algorithms/Quicksort#C.2B.2B)

Really quite ugly looking code.

Now, this isn't entirely fair; one of C++'s faults/benefits is that depending
on your shop and/or framework/libraries, "idiomatic" C++ can vary greatly.
Template heavy C++ tends to look like vomit. C++ that uses Boost will
typically be more unpleasant to look at than C++ that uses Qt (imho anyway).

Java really comes into it's own horrible self when you get beyond mere
algorithm implementation. A quicksort method in Java will tend to be
relatively fine, but for projects larger than that it becomes idiomatic to
make your java code a real mess.

~~~
cheepin
Quicksort looks significantly better in a functional style. Here's some
Haskell, but it certainly doesn't use any Haskell-exclusive features:

    
    
        quicksort :: Ord a => [a] -> [a]
        quicksort []     = []
        quicksort (p:xs) = (quicksort lesser) ++ [p] ++ (quicksort greater)
            where
                lesser  = filter (< p) xs
                greater = filter (>= p) xs

~~~
loqi
When is quicksort not quicksort? When it's not in-place:
[http://augustss.blogspot.com/2007/08/quicksort-in-haskell-
qu...](http://augustss.blogspot.com/2007/08/quicksort-in-haskell-quicksort-
is.html)

I love me some Haskell, but this particular example is kind of a bait-and-
switch.

------
Sphax
I maintain 2 semi-big Play 2 web services (written in Java, not Scala) at
work, and I just hate it.

    
    
      - SBT is super slow compared to maven
      - Compiling a play 2 app is slow
      - IDE integration is quite bad
    

After a year, I would definitely not recommend Play 2, or SBT on a Java
project.

My choice when using Java today would be Dropwizard, although I haven't
deployed anything in production using it, I tested it for a couple hours, and
I think it's the best combination of libraries.

One thing I definitely agree on, is to use Docker if possible. We use it for
almost everything at work, and it improves our deployment speed, it gives us
more flexibility and local/CI testing is now super easy. In case you deploy
with Docker, using only environment variables for configuration is great, that
way you can control the configuration directly via the docker command line.
With Java a good library for this use case is Typesafe's config, which can
automatically use environment variables.

~~~
jbooth
SBT is probably the best example of the total immaturity of the Scala
community in terms of real-world engineering. Hey, we're building for the JVM,
we've got Maven, it's arguably the best solution in any language for a very
difficult problem that has stopped entire language ecosystems in their tracks.
Let's rewrite it, from scratch, using unproven concepts! And put 'simple' in
the title!

Afterwards, we'll call XML ugly and claim to be more 'functional', without
even noticing that Maven's pom format is actually a nested s-expression
structure that happens to use angle brackets.

~~~
frowaway001
> we've got Maven, it's arguably the best solution in any language for a very
> difficult problem that has stopped entire language ecosystems in their
> tracks

Wait wut? Are you drunk? :-)

My experience is that SBT works great, while Maven tries to fight you at every
step. SBT developers try to help you get you work done, while questions in the
Maven community are usually answered with bullshit responses.

Maven (like Eclipse) are a great example of what's wrong in the Java
community.

~~~
jbooth
Not yet. You wanna show me the better solution than Maven? Something that
manages multi-module projects, with various versions of dependencies, and
packaging as war/jar/tgz/whatever?

I've probably spent way more time cursing Maven than praising it, but that's
the nature of a build/packaging/dependency tool, it's like a sysadmin, you're
either not noticing it's there or cursing its parental lineage.

What's SBT offer over maven? Lack of XML, with more trendy markup and new
bugs? Like I said, immature.

~~~
frowaway001
> What's SBT offer over maven? Lack of XML, with more trendy markup and new
> bugs? Like I said, immature.

Maybe you should do some research and figure out the answer for yourself, then
you wouldn't jump to weird conclusions.

~~~
jbooth
If you're motivated to wade this far down the thread, but can't be bothered to
explain one concrete benefit in one sentence, I've gotta assume it's pretty
difficult to come up with one.

~~~
frowaway001
It's pretty easy to come up with multiple ones.

Just one, to not prevent you from doing your own research:

Type-checked build definitions.

I lost days to debugging broken Maven setups were some tags were misspelled or
placed at the wrong position, and Maven just gave a shit about it.

SBT immediately tells you what's the issue.

Another one: It's completely painless to introduce new
settings/keys/commands/tasks. Want to have a deployment step which moves some
files to the right place after compilation? 3 lines of code. 3 lines, not a
god damn Maven plugin.

~~~
jbooth
Well, we seem to disagree on the usefulness of those items and the quality of
SBT's solutions vs the pain of rebuilding an entire new build/deployment stack
and fighting through all the bugs you've created.

We'll just have to see how history unfolds. IMO sbt already hit the high-water
mark and is receding, lots of shops using scala today advocate using mvn.

EDIT: You inspired me to do some research. Apparently, senior engineers from
typesafe do hour-long presentations named "Effective SBT" at Scala Dayz
conferences. Truly the simplest of build tools.

~~~
frowaway001
> IMO sbt already hit the high-water mark and is receding, lots of shops using
> scala today advocate using mvn.

I haven't seen that at all in practice. I think that's just a bit of noise on
the internet.

SBT keeps getting better, and many shops which originally opted to stay with
Maven are now moving to SBT, because it's just so much better than Maven.

Not sure what your problem is. Even back in the 0.7 days, SBT was better than
Maven. I'll change profession before I ever move back to Maven.

Oh, let's have a look what that "senior Typesafe" guy has to say about SBT vs.
Maven:

    
    
      Well, coming from first contributing to the maven-scala-
      plugin, then eclipse, then sbt itself, I can tell you that
      some of the things we do in sbt just fundamentally won't 
      work in Maven, otherwise I'd have tried them.
      If you'd like my branch list of broken experiments, I can 
      share them, but be assured that I personally was an sbt 
      hater before learning the tool.
    
      All of the complaints of syntax and documentation DO 
      represent a younger project vs. a more mature one.  
      However, architecturally, I'm placing my money on sbt over 
      maven.  THat's not to say sbt is perfect, but I think most 
      of these complaints are adressible.

------
shadeless
Someone could argue that Java and PHP suck because there are a lot of people
who use them wrongly. Linus Torvalds made a similar argument for not using
C++: [http://article.gmane.org/gmane.comp.version-
control.git/5791...](http://article.gmane.org/gmane.comp.version-
control.git/57918/)

~~~
serve_yay
I would agree with that, though perhaps more about PHP than Java. We like to
say "use the right tool for the job" and "you can write bad code in any
language", but that's just a way of seeming egalitarian and not really dealing
with the issue. It feels bad to talk about shitty programmers but they're kind
of a problem.

------
serve_yay
It is only tangentially related, but I recommend this video from Brian Geotz,
a Java language architect. He breaks down the challenges of adding features to
the language, in a room full of Clojure devs no less. Worth a watch:
[https://www.youtube.com/watch?v=2y5Pv4yN0b0](https://www.youtube.com/watch?v=2y5Pv4yN0b0)

------
aligajani
Who said Java sucks? The Java "language" is just too verbose for my liking,
but the Java as a toolset is very powerful. Been using it for Big Data.

~~~
julienchastang
Agreed about the verbosity and Java 8 is only making the situation worse. I've
been a Clojure enthusiast for a number of years now, but I was hoping there
would be less of a need to use other JVM languages with Java 8 and Streams. I
find working with Streams to be 3 steps forward and 2 back. The syntax (as
usual) is cumbersome, and add a layer of generics on top of that and you have
somewhat of a mess. I also find interop with traditional Java Collections to
be annoying though maybe I am not following (yet to be discovered) best
practices for dealing with Streams.

Edit: Ohh and BTW, if you ever have the opportunity to see James Ward speak in
person, do so. He is a great presenter, and a regular cast member at the
Boulder Java User Group.

------
sehrope
> If your app needs a relational database then use an in-memory db like hsql
> or cloud services like Heroku Postgres, RDS, Redis Labs, etc. However one
> risk with most in-memory databases is that they differ from what is used in
> production. JPA / Hibernate try to hide this but sometimes bugs crop up due
> to subtle differences. So it is best to mimic the production services for
> developers even down to the version of the database.

The idea that you can develop locally or test against a different type of
database then what you are (or will be) using in production is silly. I don't
just think it "sometimes" is a bad idea, I reject it outright. You should
always be using the exact same database (type and version).

For cloud deployments most XaaS providers have cheap or free dev tiers. For
local development it's easy to use VMs. For any project that requires external
resources (Postgres, Redis, RabbitMQ, etc) I have a VM that gets spun up via
Vagrant[1]. Just "vagrant up" and all external resources required by the app
should be available.

> So first… Use a build tool. It doesn’t matter if you choose Ant + Ivy,
> Maven, Gradle, or sbt. Just pick one and use it to automatically pull your
> dependencies from Maven Central or your own Artifactory / Nexus server. With
> WebJars you can even manage your JavaScript and CSS library dependencies.
> Then get fancy by automatically denying SCM check-ins that include Jar
> files.

Though I agree that it's a good idea to have dependencies externalized, it's
not always possible. Some libraries (ex: third party JARs) are not available
in public Maven repos and not everyone has a private one setup. In those
situations it's fine to check in the JAR into the project itself.

I like the approach outlined by Heroku for dealing with unmanaged
dependencies[2]. You declare them normally in your pom.xml but also include
the path to a local directory (checked into SCM) with the JAR files. Anybody
that clones your repo should be able to build the project with no manual
steps. Works great!

[1]: [https://www.vagrantup.com/](https://www.vagrantup.com/)

[2]: [https://devcenter.heroku.com/articles/local-maven-
dependenci...](https://devcenter.heroku.com/articles/local-maven-dependencies)

------
applecore
I think an important lesson for web application development—mentioned in the
article—is keeping the server stateless, moving state into the client, and
using a real middleware like Redis for the session cache.

------
ohitsdom
I'm a .NET developer and I love C# & Visual Studio but have worked some with
Java. Most of his arguments sounded to me like- "Just do _complex-sounding
long list of steps_ , it's easy!" Java development seems like a massive pain,
and too much time not actually spent on development.

~~~
breischl
Maybe it's my similar background, but that's how I read it as well.

My TL;DR summary of that article is "Java doesn't suck, as long as you use
enough tools, libraries and workarounds to avoid actually using Java."

------
nickik
>Clojure: The lack of some OO constructs makes managing a large code base
challenging

I would be intrested in what his problem is. The only thing that I can think
of is subtyping and Im not sure how subtyping helps managing organisation.

Clojures namespacing is pretty nice, it might be a bit to complicated but it
does everything you need.

~~~
escherize
And if you're just learning, sticking to the

    
    
        (ns hn.comment
           (:require [clojure.string :as str]))
    

syntax is a good bet.

------
ibebrett
all of his points except for one are related to the jvm in general, which most
people agree doesn't suck, and then when it is time to address java he just
says "scala, clojure.. are great" Yes, thats the point. The JVM is well liked,
but Java as a language is not, and I don't think he did much to change anyones
opinion.

~~~
sklogic
I do not agree that JVM does not suck. It sucks badly. No tail calls support,
no (optional and confined) unsafe pointer arithmetics, no value types and a
pathetic limit on a method size makes it an extremely shitty target for any
language other than Java. All the existing languages running on top of JVM are
very, very inefficient, or have to pay a horrible price for being able to run
reasonably fast (crap like `recur` in Clojure, for example).

edit: I suspect that none of the downvoters ever implemented a single compiler
targeting JVM.

~~~
dlubarov
> No tail calls support

Is there a good reason for VMs to support TCO rather than having compilers
perform it?

> no (optional and confined) unsafe pointer arithmetics

When do you want this? There's sun.misc.Unsafe#setMemory if you really need
it.

> no value types

Might be added in JVMS 10 or some version thereafter.

> a pathetic limit on a method size makes it an extremely shitty target for
> any language other than Java.

True.

> All the existing languages running on top of JVM are very, very inefficient,
> or have to pay a horrible price for being able to run reasonably fast (crap
> like `recur` in Clojure, for example).

Fair enough, but it wasn't designed as a general purpose compilation target
like llvm.

~~~
sklogic
> Is there a good reason for VMs to support TCO rather than having compilers
> perform it?

Again this word! Proper tail calls handling is not an "optimisation".
Optimisations are supposed to be optional, while tail calls handling makes a
_semantic_ difference.

And, no, compilers cannot do it statically. You cannot statically resolve
virtual calls, for example. Consider the following trivial case:

`(define (f g x) (g x))`

> When do you want this? There's sun.misc.Unsafe#setMemory if you really need
> it.

Try implementing, say, an STG efficiently. Or even a WAM.

> Might be added in JVMS 10 or some version thereafter.

JVM may start to suck less at some point. But now it sucks.

> but it wasn't designed as a general purpose compilation target like llvm.

Exactly. And that's why it's inferior to the other VMs, which were designed
with multiple source language semantics in mind. Including even CLR.

------
dlwj
Java itself was once so popular that a completely unrelated programming
language, javascript, had java in its name to ride the coat-tails of its
popularity.

The culture and behaviors that have grown up around it though make it easy for
people to fall into holes. (Both technical and non-technical, e.g. hiring
culture)

It's like if a minefield existed via the path of Java and people said "There's
no way through this minefield." And another retorts "Of course there is a
path! Just go through it carefully, learn the topology, and it's just as fast
as sprinting across an open meadow."

~~~
eridal
Are you talking of java? It reads like PHP to me

------
jimmaswell
One of the few big problems I have with Java is that you can't use anonymous
classes as real closures like it intuitively looks like you should be able to.

------
koffiezet
I haven't used Java for a long time myself - and am not up to date with it's
current featureset. I know I used to like coding in Java back in 2000/2001,
but my professional career demanded switching to C/C++ - which I did and also
said goodbye to a few years ago.

Anyway - something I posted yesterday in the "Java for everything" thread
here:

> My view of Java may be a bit biased, since I also tend to look at things
> from the sysadmin pov nowadays. I can only tell that I never disliked Java
> until I had to take care of the monstrosities the Java developers bring to
> life, and mind you - I started out as a Java dev back in 2000. > > The main
> issue I have with Java is the JVM and memory usage and leaks. No matter what
> people claim - no memory leaks in Java is a fairy-tale. We run both custom
> C++ and Java services (about 50/50) on a few hundred servers - and I cannot
> find a single issue in our ticketing system related to memory problems with
> any of our C++ services. Java services? Every. Single. Week. When I get an
> alert some JBoss unexpectedly died or became unresponsive -
> "java.lang.OutOfMemoryError" is most likely going to be the problem. A lot
> of those are permgen space errors, and yes you can try all the "fixes" like
> increasing the permgenspace, permgensweeping, enabling class unloading, ...
> but these don't always fix the problem and slow down your services. Every
> time this happened in our own services, this had to be fixed by our
> developers. It takes weeks to locate the problem, and you end up deploying
> new versions, upgrading JBoss, JSF, Bouncycastle, ... whatever.

After a while dealing with crap like this - you start avoiding projects using
the JVM (although elasticsearch is pretty nice)

------
hysan
If I'm reading this correctly, it just boils down to "use the right tools and
Java won't suck" which is something that can be argued for most programming
languages. This is fine and all, but one of the problems for new programmers
(the majority of languages comparers) is that learning what Java toolset to
use is a huge hurdle. Java's diverse ecosystem and long history hurt its image
by making it seem like a hulking monstrosity that is reserved for enterprises.
Combine this with the verbose syntax and any cursory glance at Java will drive
most new programmers away. Compare this with other languages that do not
suffer from such a poor image and it becomes easy to see why people often say,
"Java sucks."

What I wonder is if the following exists:

* A simple/clean tutorial that introduces a developer to the most common tool chain (perhaps various tutorials for different use cases - web, desktop apps, gamedev, etc.).

* Instructions that don't just name drop, as this article does, but instead gives concrete examples that lead to a fully functional work environment. Perhaps one that works as this author describes - scripts to setup dev environments, deployment, CI, etc.

* Advanced instructions that point you to documentation in the case that you need to go beyond a simple work environment.

* A comparison of various tools in the Java ecosystem that compares the use cases and, more importantly, gives examples of how various tools would be effectively used together.

One of the reasons why I personally find Java to "suck" is because the
friction involved in getting up and running in an efficient manner is far
greater than that of other programming languages. I think that rather than
write such an article defending Java, it would be much better to create a
beginner resource that can onboard developers easily.

------
kazinator
> _Servers That Take More Than 30 Seconds to Start Suck_

> _For developer productivity and so that scaling up can happen instantly,
> servers should startup quickly._

Of course, a Java programmer takes it for granted that you restart things
every time you change code. But that sucks.

Servers _should_ start up quickly. Well, what if they don't? What if they
don't for some good reason?

~~~
Fishkins
> Of course, a Java programmer takes it for granted that you restart things
> every time you change code. But that sucks.

Did you not read to the section about jRebel/Play and not needing to restart?

But I do agree with you that server startup time isn't as big a deal if you
don't have to restart after each change.

~~~
aries1980
These makes some debugging tricky because of the indirections the frameworks
introduce and also comes with performance hit.

A long start up time makes more difficult your integration/functional tests
that it should.

~~~
neeme
JRebel IDE plugins integrate with your IDE debugger to hide the indirection
from you. Works for me. If it does not work for you (or the performance hit is
non-negligible) then I suggest you contact their support, they usually fix
stuff in couple of days (from my personal experience).

And, AFAIK, Play! is also fully debuggable. What's bothering you?

~~~
aries1980
Yes, the IDE hides the indirections, but not in the bytecode. I mean when I
need to profile or debug the binary and optimise e.g. the GC or the heap
usage, I am stucked, right?

------
mcguire
" _Decoupled Schema & Code Changes: When schema changes and code changes
depend on each other rollbacks are really hard. Decoupling the two isolates
risk and makes it possible to go back to a previous version of an app without
having to also figure out what schema changes need to be made at the same
time._"

I'd really like to know how you do that.

~~~
the_fury
Generally you would use an expand/contract migration pattern.

You deploy a schema expansion so that both the new and old code will run,
deploy the new code, and once the new code has been validated you deploy a
schema contraction.

[http://exortech.com/blog/2009/02/01/weekly-release-
blog-11-z...](http://exortech.com/blog/2009/02/01/weekly-release-blog-11-zero-
downtime-database-deployment/)

~~~
mcguire
That's what I came up with, too. But it's still coupled: you can't "go back to
a previous version of an app without having to also figure out what schema
changes need to be made", post-validation, anyway.

------
habosa
I love Java. When used correctly it's a very powerful language that is easy to
run in many environments. I choose it for any personal project that I can see
growing beyond a few small scripts.

I hate Java culture. Too much Enterprise Java is filled with SomeThingImpl,
MyModelDAO, SomeShittyBean, and magical XML configurations. I don't know how
things got this way (I haven't been around long enough) but there is no reason
Java the language has to be attached to this nonsense. I totally understand
why people take one look at a modern Java codebase and swear off the language
forever.

For me though, Java is the mainstream language that I find makes me most
likely to be correct the first time I write a program. Yes that comes with
verbosity. Yes that means I have to use a RAM-hungry IDE. But I write code
that runs fast and correctly the first time. I love that.

TL;DR - Java (The Language) != Java (The Culture)

~~~
kyllo
Exactly. Java is fine if you just write plain-old classes. It's when you
overuse patterns and try to make everything hyper pluggable/configurable with
XML-based dependency injection that it becomes a disgusting slog.

I write Java that is 100% "Plain Old Java Objects" and it is just fine. Keep
it simple.

------
AhtiK
"#1 Install the JDK"

No developer should install JDK, it's a mess, madness and risk for crapware.
Just use the JDK zip/tar.gz for that one specific project.

Even for distributing java apps I find it much easier to bundle JRE with the
app and never ask for the devop or end user install it separately. The license
for bundling is quite permissive [1] and bundling can be also used for os x
apps [2].

[1]
[http://www.oracle.com/technetwork/java/javase/jre-8-readme-2...](http://www.oracle.com/technetwork/java/javase/jre-8-readme-2095710.html)
[2]
[https://docs.oracle.com/javase/jp/8/technotes/guides/jweb/pa...](https://docs.oracle.com/javase/jp/8/technotes/guides/jweb/packagingAppsForMac.html)

------
vorg
> Groovy > * Great > * * Simple language with a few very useful features

Simple? Have you seen Codehaus Groovy's grammar?...

[http://svn.codehaus.org/groovy/trunk/groovy/groovy-
core/src/...](http://svn.codehaus.org/groovy/trunk/groovy/groovy-
core/src/main/org/codehaus/groovy/antlr/groovy.g)

That's from 2007 and more's been added since. What hasn't changed is it's
still in Antlr 2 whereas the latest version of Antlr is version 4. Groovy's
not simple, it's an obsolete dinosaur.

------
untog
_So first… Use a build tool. It doesn’t matter if you choose Ant + Ivy, Maven,
Gradle, or sbt_

To me, that's part of the problem. The Java ecosystem seems diverse to a
fault.

~~~
jlward4th
Most platforms have pretty fragmented build tooling. I think an exception
might be Go because it has the build tool built into the platform.

------
ausjke
Suddenly I'm reading Java-come-back articles, which is nice. That convinced me
to some extent I should learn Java more for serious coding, instead of
spending the same time on php/python/javascript. Not saying the rest languages
are bad, but life is too short to get good on all of them.

Also Java is important for android.

~~~
calebm
Satire?

------
jontro
I'm not sure about the "Useless Blocking Sucks" paragraph, it's very
opinionated and using the play framework in production is nothing I would
recommend for enterprise deployments. The technology is still very immature
and I do not see that the overhead of an extra thread per request would
matter.

~~~
tormeh
How is it immature? It is used in enterprises already, and they seem to like
it.

------
strangename
His last note should have been his first; it's the Java environment that
doesn't suck in any magnitude more than other environments, and has oodles of
benefits for getting Serious Business done. You now have your choice of
language with which you can enjoy the rock-steady JVM/JDK-library environment.

------
th3iedkid
>>Spend a couple evenings or weekends working on implementing one of these
items. Then show your manager what you did in your own time (that will convey
how much you care) and then let them take the credit for the amazing new thing
they thought of.

Why would someone want to do that , unless its someone's personal project?

~~~
jimbokun
If the expected cost of interviewing for and finding a new job where these
things are already in place is greater than the cost of a couple evenings or
weekends to add those features to the current work environment.

------
debacle
Java has some problems. I would contend that using the wrong tool for the job
== using the tool wrong. Java has its place, but overall there is a better,
more specialized solution in most instances that doesn't have some of Java's
(pretty hideous) warts.

------
hit8run
This article reads like an advertisement for play2. I created apps with play 1
and when play 2 was released I was quite excited hoping for things to get even
better. Unfortunately the authors like Guillaume Bort and some others found
love for Scala. Now the core framework is written in scala and play feels like
a scala framework even though they added some Java Apis. The last time I
checked play2 out there were conceptual inconsistencies between scala and java
flavors of play2. For example Java comes with a hipster ORM (ebean) and Scala
has a completely different almost non ORM flavor called anorm. Also IDE
Support for play2 java flavor sucks. The biggest advantage of playframework
was to have an agile framework like rails in the java world. This advantage
has gone.

------
halis
SharePoint doesn't suck you're just using it wrong..

------
WalterSear
From the article:

    
    
        The Java Language Kinda Sucks

------
talles
Listed without no further _text_ on the Clojure's _bad parts_ : "Dynamic
typing".

That's very very debatable, don't you think mr. Ward?

~~~
jlward4th
Definitely. Which is why I labelled that section as my opinions. :)

~~~
talles
_Touche_ :)

I guess I just felt bad to see all those great bulleted itens with some nice
phrasing around and then to see my dear _Dynamic Typing_ there, alone, without
any adjective. No love, no hate, simply emotionless "Bad" :(

~~~
jlward4th
Good point. I should have put more details in there. I prefer static typing
with good type inference because it allows me to have a compiler validate a
lot of my code pre-runtime. Otherwise I'm left with tests and actually running
all of the code to do that validation. The value of this for large code bases
has been worth the tradeoffs in my experience. But since this is one of the
most debated things in programming I don't expect to sway anyone. I'm happy to
leave this as an item of "it depends" / personal preference.

------
davesque
As a side note, I can still remember how nice it felt to use Java in the mid-
nineties coming from C++.

------
edpichler
People, we are in 2014 and still discussing what programming language is
better.

~~~
Retra
2014 is not the future. It's not even a big number.

The world we live in is actually quite primitive. That's why people who _care_
about things keep bringing them up.

~~~
edpichler
I believe languages war is not a good problem to spend energy.

~~~
Retra
Every worthwhile achievement in human history has been as a result of our
mastery of language.

------
devniel
totally agree. What about testing EJBs?, it was painful for me, it took me
many hours.

~~~
mooreds
People still use EJBs? What, are we still listening to Gorillaz?

~~~
Havvy
I still listen to Gorillaz, but I don't use EJBs.

------
kendallpark
Because we needed an article to clear this up.

:P

------
javaistheworst
No really, Java the language is bad. Terrible in fact.

The fact I need an IDE to make it workable (just) highlights this point. J2EE
was terrible too, because it showed where things can go, if you let the Java
astronaut architects lead.

Some of my most profitable projects were helping to rescue systems by
migrating to to an alternative language on the JVM, or off it completely.

The worst part is the damage Java inflicted upon a generation of developers.

I have a problem, I think I will use Java, and Eclipse, and Maven, and all the
rest. Now I have twenty thousand problems!

Edit - if you disagree, then say so. Bit spineless to downvote without a valid
point to back it up!

~~~
nostromo
Speaking of spineless, did you really need a throwaway just to say Java sucks?

~~~
Scramblejams
As HN has grown it has attracted a more vocal contingent of Java developers.
It's getting progressively harder to criticize the language without somebody
shouting you down.

~~~
ww520
It seems the anti-Java ones are the more vocal ones most of the time. You see
the anti-Java posts all the times.

~~~
Scramblejams
Those of us who are recovering Java programmers might say there's a good
reason for that. :-)

~~~
ww520
Are you insecure about your new found favorite language that you have to bash
the old one that you didn't have much success with to justify your new choice?
If you are really happy with your new favorite language, great. Do good work
with it and move on. No need to keep smearing the old one.

~~~
Scramblejams
Heh, no. Your comment didn't seem rhetorical so I was just providing an
explanation for the phenomenon you've observed. However, we do engage in much
spirited discussion throughout the software world about the relative merits of
various languages and their features. There's no getting away from it, and
Java's gonna get beat on until the end of time. Hope you don't take it
personally.

~~~
ww520
None taken. If those frequent "spirited discussion" soothed your ego, by all
means increase the weekly Java bashing. Meanwhile we just keep making software
with it.

~~~
Scramblejams
It's not about ego, it's about taste. Specifically the tastes of the majority
of HN.

Sure, lots of software gets written in Java. And (less so) Cobol and Fortran.
Every sensitive Java (and PHP, etc) user who is on HN and feels compelled to
respond to every slight has to understand, though:

HN was founded by the guy who wrote Beating the Averages[0].

We're in PG's house. And he never liked Java.

So if Java fans come here with a chip on their shoulder about it and
constantly take the bait and get into flamewars about how solid and adequate
their language is, they should remember what forum they're in. Not that
opinions in the forum can't be changed, but why bother when there's plenty of
Java love out there elsewhere?

[0] [http://www.paulgraham.com/avg.html](http://www.paulgraham.com/avg.html)

~~~
ww520
So it's basically herd mentality with reinforced in-group cliche. Just because
PG started HN, we all have to toe the party line to bash Java? If you think PG
cared about everyone here has to agree and follow his opinion, you paint him a
very shallow man.

And I think he's naive in that blog in using single language as a criteria to
evaluate developers, but there's another story.

~~~
Scramblejams
No, I'm just saying that like attracts like. If PG starts anything involving
programmers, a lot of them are going to share a number of his opinions on the
topic, because they self-select that way. So HN is naturally going to be
dominated by those who dislike Java.

You can keep responding to that dislike, but on HN, given its natural
audience, staking out much of a pro-Java position is doomed to futility.

------
thehelix112
Yes, it does.

------
Dewie
> If you need some ammunition to prove to your management that your startup
> times are killing your team’s productivity then use the stopwatch on your
> phone to count the total minutes per day wasted by waiting for the app to
> start.

But... what about my sword-fighting

------
lcfcjs
Wow makes me dislike Java even more lol @jamesward

------
serve_yay
I agree with the article -- as it says, "The Java Language Kinda Sucks" :)

