86 comments

[ 5.0 ms ] story [ 97.7 ms ] thread
I like it! I have similar opinions on static vs. dynamic, Java vs Python or PLs in general - too many judgements are based on shallow first impressions or ease of getting started to the detriment of future maintenance.

Check out Scala :) Its a pretty complex language, but its the sweet spot between Python and Java i've been looking for.

Check out Kotlin. It's not a complex language with much faster compile time.
It's a complex language, just not a powerful one. If you want a language that actually simplifies on Scala, try Ceylon.
Kotlin has plenty of killer features, two of them is a very good OOB IDE support even in Community Edition of IDEA and machine translation of Java code to Kotlin.
The IntelliJ Scala plugin is pretty awesome too and it also offers machine translation of Java code to Scala. It's actually the most widely downloaded plugin for IntelliJ by nearly an order of magnitude. I think Kotlin is a much better option than Java, but the main selling point is simplicity for those who don't want to spend the time learning Scala (entirely valid if if that's a priority for you).
Or Xtend if you want a simpler Java with less verbosity
Turbo Pascal has much faster compile times than Kotlin. Compile time just isn't that big a deal as a feature.
It's not a feature, until it becomes a problem. It is a problem in Scala.
I use Scala every day. IntelliJ uses incremental compilation, so most compiles complete quicker than it takes for me to reach for the mug of coffee next to my keyboard.
If you're looking for a sweet spot you should try Go.
Go feels more like C with garbage collection and a nicer standard library, but lacks the abstractions necessary to be anywhere near as expressive as Python, Ruby, Scala or even Rust. At the language level some advantages of Go include the fact that it's easy to learn and mostly hard to write unreadable code.
I'm very comfortable in Go, Java and Python, and in my experience Java and Go fill the same niche in terms of use case, but I'm way more productive with Go, for various reasons. And in terms of language, it's waaaaay less verbose than Java and I end up writing far less code to achieve the same goals.

I actually just had the experience of starting a project in Go, and after a prototype the company decided to reboot it in Java (for business and not technical reasons, basically the project started as a server and ended up being a library, so language popularity matters). It took me a lot more code and time to get the Java implementation to where my Go prototype was.

It might just be me, but in terms of a sweet spot between being productive and having high performance, Go is the best of both worlds. It's on par with Java in terms of performance, and slower than python to write - but not as much as Java (and for big projects I suspect you end up more productive in Go than in Python).

Go is just functional enough for me to free up some boilerplate that I feel more productive there. Structs and funcs are 90% things, and I only use a receiver on a func if it helps to clarify an operation or mutate that value. That Java doesn't give this choice directly is sad, but verbs in the land of nouns will do that.

A lot of my time is spent writing and reviewing Java code, which I still enjoy a bit.

Go is a bitter spot in my book. All of the costs of a good type system like Scala's, but few of the benefits. (Go may well be better than Java, but why is that your point of comparison?)
this thread is about java vs python. go to me is a sweet sport between what I like about other strongly typed languages and what I like about python
The post you originally replied to was about Scala - if you're suggesting people use Go instead, we should compare Go to Scala.
We had very similar experiences with Scala. Java and the JVM are incredibly stable and mature but the language (even with JDK8+) is very restrictive. There's no pattern matching, no full closures, properties are based on a manual naming convention, and even the basic type inference is extremely primitive. The dynamically typed languages like Python and Ruby are fantastically expressive and flexible, but maintaining large bodies of code can be tricky and the performance can't compare to the JVM. Scala gives us the stability and performance of the JVM with great tooling (IntelliJ Scala plugin) and the language is very flexible and expressive. It takes some discipline to focus on writing highly readable Scala code but the result is totally worth the extra effort of learning the language. I'm not surprised that Scala was ranked as one of the most loved languages in the StackOverflow survey for at least the last two years, and Spark and Scala are the top paying tech skills in the US :

http://stackoverflow.com/research/developer-survey-2016#tech...

http://stackoverflow.com/research/developer-survey-2016#tech...

You hit the spot with your article. I could not have said it better. Let's now wait till the NodeJS/Mongo-webapp-in-2hours Kids ruling HN, start to "bash" you to hell... But be sure: There are more than enough people out there who exactly know what you are saying and why.
Nodejs is in decline here on HN, judging by post frequency.

    # Map from user ID to User object.
    userIdMap = {}
Or as I would write this:

    userIdsToUserObjects = {}
Ctrl + n in vim completes this easily, so I don't care how long the name is.

I agree about the general point of the article, being strong in one language, but poor naming will bite you in any language. Comments are apologies for bad code: only write comments when you can't write better code.

Algorithmically tricky code is going to need as much explanation as you can provide, no matter how good your variable names are.
I split my time between Java and less-typed languages, and what always annoys me is:

    messagesByUser = {}
Is the key a user id, username, a user object, some sort of stripped down user hash, what? What about the messages? If you try to cram all this information into the variable name then you've invented a perverse form of hungarian notation. And of course you lose all that precious type information every time you pass it off to a function.

Python is my go-to crutch for quickie projects that will never grow beyond a few hundred lines of code. Anything more complicated needs a typechecker. I only wish Java's was more robust.

What do you mean by more robust?
A suggestion, you should use the form valueTypeFromKeyType. The key is always on the right side and the value on the left side. This also applies to conversion functions - myFoo = fooFromBar(myBar); I find that makes the code easier to read than myFoo = barToFoo(myBar);
> The big argument against Java is that it’s verbose.

I have a few others I'd prioritize over verbosity:

  - Generics
  - Dependency conflicts
  - Libraries that simply "fix" the language, i.e. Apache Commons, Google Guava
Disclaimer: your mileage may vary. This is simply my personal pet-peeve list.
Keeps getting better though, the example in the post:

Map<String,User> userIdMap = new HashMap<String,User>();

is now just:

Map<String,User> userIdMap = new HashMap<>();

and Java Generics already saves a ton of type casting as well as checks and corrections IMO.

Or use Lombok and get it even more concise!

val userIdMap = new HashMap<String,User>();

I actually find I don't need Apache Commons or Guava now that I'm using Java 1.8. A lot of the functionality has been standardised.
After working on large Javascript projects and running into and cleaning up countless issues that static typing would solve, I've come around to being a huge fan of static typing. Now, every line in an untyped codebase looks like a potential typo or reference to an old function that was refactored ages ago just waiting to blow up at runtime. Tests help, but only after you've written them.

I really like Javascript, so I've been using Facebook's Flow type checker, and it's been great. I was already using Babel (with Browserify), so nothing about my build process even needed to change. It makes it easy to gradually add type-safety to a codebase. It doesn't get in the way of common Javascript patterns. Callbacks are still lightweight, but well-typed. I can still bypass the type-safety and monkey-patch a property onto an object while I'm testing something.

After coding for awhile now, I've also developed a penchant for statically typed languages. I've been forcing myself to use TypeScript whenever coding JavaScript for the static typing.
It happen the same to me, I ended up migrating the codebase to Typescript, and now I can have almost everything I want from a language, types and functions...
Code completion(API) has big impact on my productivity in larger systems. With dynamic typed languages I ended up with type annotations everywhere - so advantage of not having to declare variable types kinda disappears.
I'm not a fan of Java, but I am a fan ofJVM. You don't have to use Java to get the most of JVM, you know. Especially since Kotlin is out, but it was true for a long time with other languages.
> Sure you have to write: Map<String,User> userIdMap = new HashMap<String,User>(); instead of: userIdMap = {} but in the bigger scheme of things, is that so long?

More like user posts complex JSON object, which takes me seconds to parse into a Python data structures, and hours or days to figure out complex mappings into Java classes. It's often the mapping of objects to serialized forms is where a huge amount of time gets spent in statically compiled languages. And it's NOT just a once of investment - those mapping change in future and some poor soul is going to have a fun time modifying your Java app, no matter how well named your variables are.

If you are writing glue code or IO bound web servers without a high performance requirement, the difference in productivity between Python and Java is not at all trivial.

If you want type safety, you need to parse your JSON into a java class (although "days" is definitely an exaggeration with the right tools—I'm a fan of json-schemas and jsonschema2pojo [0]). But of course you don't get type safety in python, so it's bit of an apples and oranges comparison.

If you're willing to settle for no type safety, there are untyped Java APIs like Jackson's tree API [1] that are, while definitely more verbose than Python's, similarly productive in my experience—and much, much faster.

[0] http://www.jsonschema2pojo.org/ [1] http://wiki.fasterxml.com/JacksonTreeModel

Yeah, but when you have to change anything in that part of the code, you thank that everything is statically typed and you know what that json object contains...
The article seems to be about Java vs Python. But it really only talks about static vs dynamic typing. Not only has everything about that subject already been said 1000 times. It's also not Java-specific. Java sucks IMO not because of static typing, but because of the 'If you have a problem, add more OOP'-mentality which has given us Java EE. About any argument he makes pro-java is also valid for something like typescript. But with typescript you still have the freedom of a scripting language for the parts where it makes sense.
Really good point. Replace every mention of Java in the post with any statically typed language, and he definitely has a point. He doesn't argue that Java doesn't suck.
Why not do everything in C? The answer to that question is the answer to why not do everything in Java.
With the “small” caveat that C's design tradeoffs don't make it as good a general-purpose programming language as Java is, at least in 2016, no idea about 1995.

Not that I think Java should be used for everything.

In 1993 I was using Turbo Pascal 6.0 for systems programming in MS-DOS.

Short list of TP 6.0 features in 1993!

- Real type safe enumerations

- Proper strings and vectors

- modules (units)

- Fast compilation (seconds)

- OOP

- Type safe reference parameters

- inline assembler, naked functions, absolute addresses, pointer manipulation functions, customizable memory allocator, overlays, procedure/function variables for systems programming tasks

C++ was already picking up steam in Windows and Mac OSes and with CORBA and DCOM for enterprise systems, the precursors to J2EE.

If it wasn't for the widespread of FOSS software based on UNIX and C culture, C would have slowly faded out.

In 1993, I was just 5 years old, but, when I encountered Delphi, around 2000, it was a very pleasant improvement over Microsoft's offerings:

(0) Compiler: Super-fast compilation times, unlike Visual C++; and super-fast generated executables, unlike Visual Basic.

(1) Libraries: Borland's VCL was vastly more sophisticated than either Visual Basic's controls [underpowered toys] or Visual C++'s MFC [barely more usable than the Windows API itself].

(2) Core language: Of course, from Pascal, Delphi inherited a real module system [not C++'s `#ifndef` nonsense], real strings [not C++'s `std::string`, let alone MFC's `CString` nonsense] and real dynamically allocated arrays [not C's pointer nonsense, although C++'s templatized containers hadn't taken off yet]. And Delphi's object system was something a normal human being could actually hope to understand, unlike C++'s multiple virtual inheritance mess.

Yes, but then Borland had to screw it all up and now even the last compiler developers that go all back to Delphi early days have left the company.
Because every code line is a security exploit waiting to be taken advantage of.
So you happened to work on stuff that Java is good for, including subjectively good because you are familiar with Java and unfamiliar with Python (the web app) and randomly good because mistakes were made in the Python implementation but not in the Java implementation (the logcat tool), and you think this kind of work is "everything" and you spit judgements about "dynamic languages". Thank you for wasting my time.
Reading this is frustrating because I agree with a lot of what the author is saying (that using dynamic languages can speed up initial development but incur future technical debt), but I think that Java has a huge number of issues that prevent it from being a language I'd want to use for a lot of tasks. Here are some examples, although since I haven't written Java in a while I could be inaccurate on some of them:

- the use of the Object type (surprisingly common)

- No first-class functions or function types. New Java has lambdas but I'm not sure if it has function types or the ability to pass a class or instance method as a first-class value

- No higher-order types (e.g. The type of a map function, let alone an fmap function, can't be written)

- Need for frequent casting is both inelegant and a big source of errors

- Classes are giant, heavyweight and deeply stateful, and tend to have deeply nested hierarchies

- Class-scoped variable names (E.g. That don't require explicit 'this') are confusing, and for example don't make it clear whether a variable being referenced is a class variable, instance variable or local variable. Creating inner classes complicates things further, and inherited variables and methods are also opaque

- creation of new types is a pain which promotes overuse of primitives (ints/strings/bools) over more expressive and safe types

- polymorphism via interfaces isn't particularly expressive, for example AFAIK you can't make a function which takes two arguments of the same type unless you specify that type precisely

- null pointers are rampant, and even considered idiomatic, for example during initialization

- imperative style is forced on the user in a very strong way; for example no literals for array lists, maps etc, standard library overwhelmingly provides mutable data structures.

I could go on, but suffice it to say that the author's claim that the main complaint against Java is its verbosity is a red herring.

It's also a bit disappointing to see him dismiss languages like Scala (and presumably languages like Ocaml and Haskell, which he doesn't even mention) due to being "complex", which suggests to me that he hasn't fully grasped his own lesson that putting the time and effort into a safer, more expressive and more strongly typed language is worth the initial trade off in productivity. Although the author claims that once their code compiles it usually runs without errors, this has definitely not been my experience. Indeed my biggest argument against Java is that due to its imperative nature and inexpressive type system, it's not that much safer than many dynamic languages, which makes it really hard for me to justify using it.

We had a large project that depended on a library written in Haskell. One day the developer for that library quit his job. We sincerely couldn't find another Haskell developer, had to re-write the library in Java.

Heck, I've tried hard to understand Haskell. Simply don't understand why someone goes through the effort of using that exotic language. The old library was taking 2 minutes to process input, the re-written version in Java took 3 seconds.

Just keep it simple, use Java.

There are very good reasons for using Java: portability, libraries and the JVM's performance. But simplicity really isn't amongst them. Even Featherweight Java (a carefully selected subset of Java for the purpose of proving theorems about it) is full of tricky details.

That being said, yeah, Haskell's learning curve is quite steep, and writing high-performance code in it is kind of a black art.

> It's also a bit disappointing to see him dismiss languages like Scala (and presumably languages like Ocaml and Haskell, which he doesn't even mention) due to being "complex"

Hey, it's possible to dismiss Scala due to being “complex” (which is certainly is), and still like (or at least not dismiss) OCaml and/or Haskell. :-p

(comment deleted)
From my perspective, a lot of the problems listed above are either because 'you're doing it wrong' (and awful excuse that could apply to any language) or are hangovers from previous Java versions. That said, I've addressed a few of your points from my own personal experience working with Java for the last 6 years (3 years professionally):

> - the use of the Object type (surprisingly common)

Doesn't appear common to me at all - the code base I work on has no declaration of anything as 'Object' anywhere in well over 300k lines. None of the 3rd-party libraries we use have the Object type in any of their public APIs. So from my experience this is a non issue, and I'm quite surprised it was mentioned. Then again, I do work on a relatively new (<4 yrs old) code base, recently moved to Java v1.8.

In fact, probably the biggest offender of Object use is the Java built-in libraries, especially the Collections framework, parts of which are frustratingly not type-safe as a compatibility hangover from before generics were introduced. For a fun example, the map interface has put(K, V), but get(Object). Grrr!

> - Need for frequent casting is both inelegant and a big source of error

Again, the code base I work on has very little casting. I feel like this is more a symptom of how code has been designed rather than an inherent issue with the language. Once more possibly a hang-over from the pre-generics days.

> - Classes are giant, heavyweight and deeply stateful, and tend to have deeply nested hierarchies

This seems a bit subjective, so I'd say you might be writing/using classes badly. How does Java differ from any other OO language in this respect? And remember the words of The Great Joshua Bloch: always favour composition over inheritance!

> - Class-scoped variable names (E.g. That don't require explicit 'this') are confusing, and for example don't make it clear whether a variable being referenced is a class variable, instance variable or local variable. Creating inner classes complicates things further, and inherited variables and methods are also opaque

A moot point when using a modern IDE as far as I see it. But certainly a concern if syntax highlighting isn't available.

> - creation of new types is a pain which promotes overuse of primitives (ints/strings/bools) over more expressive and safe types

How/why exactly is this a pain? Related to the verboseness, perhaps? And certainly in the code I work on I wouldn't consider primitives over-used at all. Don't forget the Java enum, one of the best features of the language, can quickly be put together and contain as much extra information/functionality as you'd like. We certainly use them frequently.

> - null pointers are rampant, and even considered idiomatic, for example during initialization

If null pointers are this rampant, then again the code must be badly designed or doing something wrong. Null pointers are probably the least common issue we get in our code base. Of course I can only speak for myself. The Optional in Scala does sound like a brilliant feature, but doesn't demonstrate why Java is any worse than other non-Scala OO languages (here's looking at you C#).

> - imperative style is forced on the user in a very strong way; for example no literals for array lists, maps etc, standard library overwhelmingly provides mutable data structures

I can't argue with this. Mutibility in the standard libraries isn't great and parts of it certainly could do with a re-write (which worked out totally fine for Python, amiright?) and generally there are few few 'correct' ways to write anything (I'm ignoring the monstrosity that is Java EE here).

But this is an aspect of the language I actually really like. I like the verboseness, I like the lack of ambiguity, and I like that all well-written Java code looks remarkably similar. If dev teams enforce strict (and at least partially arbitrary) styl...

I've been using Java since 2009 for everything from small projects to large scale data handling (hundreds of terabytes).

Really, Java is just a tool. Language is familiar to anyone, performs good and libraries exist for just about everything.

The only reason we don't use C is because we'd require end-users to correctly pick different binaries and because the IDE for developing C is quite a pain (don't want to start a fight here, it is just pain when compared to Java).

So, let the cool kids play with Ruby and Go. Some of us just need to get things done.

Does there exist "the IDE for C"? I know Eclipse for Java, but even that has a number of competitors.
> I realized that as I accumulate knowledge about 3rd party Java libraries and grow my own utility library, it becomes increasingly expensive to use any other language. I have to figure those things out again and write them again, instead of copying and pasting the code from the previous project.

Author is a douchebag

Sounds like the author has never heard of or used Groovy before. There's very little you have to write in "pure" Java.
The author wrote:

> For these scripts I decided to use JavaScript, primarily because it’s included in Java 6 and secondarily because many people know it

Apache Groovy isn't included in Java, and there's many incompatibilities between it and Java (e.g. behavior of ==), so perhaps that's why it lost out to Javascript for scripting.

The big pain point I see with languages such as Java is the deployment cost. Since the runtime is separate, you have to deal with the cost of lugging that around and installing it. When you have a larger scale system with lots of different Java programs, you can run into cross dependency issues over time as different programs require different versions of Java. Then there's also the jar files and the rest of it. At the lower scale end, its a tough sell to have to lug the jvm and a pile of jars over to a system just to run a single program.

Python can have similar issues, even with virtualenv.

For this reason, I tend to use Go these days. It completely avoids this cost. Also, unlike Java, any tools start up instantly and don't need to 'warm up'.

About the startup delay, doesn't Java support having a long-lived VM that instantiates per-program class loaders and runs them?

Also, Go isn't JITted, so Java's HotSpot could potentially be faster for often-executed hot loops.

You can bundle a JRE with the application, no different than bundling libc.so or mscvrt.dll along a dynamically linked C application.

Or just buy one of the many AOT compilers available.

What an idiot!

Different tasks require different languages. It's not possible to pick just one. Most people gave this moron the right answer, and yet he failed to comprehend it.

And this pathetic cretin clearly never ever seen a truly expressive language. Likely, he never seen anything besides his pathetic Java and stupid Python.

  The author should start writing a game in java.

  The author should start writing a heavy matrix calculations in java.

  The author should start implementing a small command-line tool ine java (grep?)
All these use-cases is where Java fails miserably. Pick to right tool for the job. Is still the right answer.
> The author should start writing a game in java.

Minecraft did alright...

It did alright on PC. The problem I see there is that they had to reimplement it in C++/C# for other platforms, causing the updates to be way behind. Maybe I got that one wrong, but wasn't there some announcement that they'd switch to C++ in the PC version as well?

I'd like to add, though, that I don't generally see a problem with programming games in Java. I just prefer C++ for that, with portability being only one of the reasons.

In what ways cpp is portable and Java is not?
Usually, game consoles and handhelds don't have a JVM installed. I don't see the point in porting (parts of) a JVM to these platforms for your games, especially considering the little benefit (if any at all) that would offer.
Ironically to what you mention, Java was designed with embedded devices in mind and particularly popular as game deployment platform for old phones.

Virtually any cheap phone (non-smartphone) comes with Java ME available. Nowadays you find Android and the millions of Java-based games on the play store.

> The advantages of C and C++ ... don’t apply to my work. C# is nice but not cross-platform enough.

> Scala is too complex. And other languages like D and Go are too new to bet my work on.

So in the end you're talking about your work - the right language for the job.

Maybe Java is good for everything at your job, but not that good for most things at mine.

I prefer C++ over Java every single time.

Not because of the more power that it gives me, but because I'm experienced with it and I can get the job done.

I would use Javascript for a web application and Swift or Objective-C for an iOS app. And I can't imagine doing that with Java.

Even for iOS I still greatly prefer C++ as well over Objective-C or Swift.
Funny how the author missing the point.

Few things:

- you can write the example if, elif, etc. in any language that supports pattern matching (dynamic or static) safely, it has nothing to do with type systems at all

- spinning up the JVM for CLI is still largely unsolved problem, this is why Python or Go is used for CLIs more

- verbosity does not matter? Seriously, the most annoying part of Java is verbosity, that fosters a mindset that it does not matter how long is something. In that verbose code we can hide few things: bugs and more bugs.

- not knowing anything else than Java and Python, even in 2014 is silly

I think there are many better solutions for the problems he mentioned in the article.

> spinning up the JVM for CLI is still largely unsolved problem

Only by those that ignore that there are quite a few Java AOT compilers to native code available.

The OpenJDK isn't the only option out there.

Thanks for pointing out. I am going to check this option for my CLI projects.
It's apparent that a lot of developers have no idea of programming beyond OOP. Multi-paradigm ideas and CTM especially don't seem to be widespread.
Java is the reason i stayed away from programming when i was a teenager.

Later I noticed that Java teams did not get things done quick.

My android phone stutters while playing music. (No it's not packed with apps, there is at least 200mb RAM free)

Huge fan of Java, and at my company we actually do end up using Java for everything, but we are very cognizant of the fact that it is very specific to us, our deployment and runtime infrastructure. This article feels extremely opinionated and myopic to me. For instance,

> (python is) the wrong tool for code of any size written for pay, because you’re doing your employer a disservice

Honestly, Java 8 has a ton of new features that give it a very functional feel if one desires. Check out the new Stream api and map(), forEach() functions