Hacker News new | comments | show | ask | jobs | submit login
Java for Everything (teamten.com)
387 points by cousin_it on Nov 30, 2014 | hide | past | web | favorite | 338 comments



There's the language and there's the ecosystem. A lot of negative feelings that still linger are, IMHO, directed more at some of the painful historical aspects of the ecosystem: J2EE XML configuration hell, EJBs, bloated application servers, XML for everything, JAX-WS, SOAP, ant, classloader problems, maven dependency hell, 10 different logging libraries, etc... A lot of this stuff truly sucked.

But I feel things have improved over time. Dropwizard, gradle, embedded jetty, jersey, guava, Spring boot, etc... The trend is towards minimizing configuration and overall, the ecosystem has become somewhat more manageable. I wouldn't necessarily call it pleasant, but it's better.

An as for the language itself, Java8's lambdas + streams provide significant improvements.

Compare this (Java 7):

  public static List<Integer> sortDescending(List<Integer> ints) {

      ints.sort(new Comparator<Integer>() {
          @Override
          public int compare(Integer o1, Integer o2) {
              return o1.equals(o2) ? 0 : o1 < o2 ? 1 : -1;
          }
      });

      return ints;
  }
to this (Java 8):

  public static List<Integer> sortDescending2(List<Integer> ints) {

      ints.sort((o1, o2) ->  o1.equals(o2) ? 0 : o1 < o2 ? 1 : -1);

      return ints;
  }
(Example is contrived, since you could use the built in Collections.reverse() to achieve the same result. My main point is that we have eliminated ~4 lines (counting braces) of ceremony.)

All that said, I'd rather be using Clojure.


Keep in mind that JAX-WS with JAX-B beats other rival libraries in other languages. If your requirement is to be a client that consumes SOAP web service given wsdl, I'd take Java any given day. The wsimport and wsdl tool that JDK provides beat any libraries.

Also, JAX-B annotation can serialize and deserialize to JSON given the right provider. That's JSON, XML with POJO with the price of one. Good example of Java ecosystem: build on top of existing one / backward compatible / play nice with others.


False. If you use a language that's homoiconic (any Lisp), you don't need to serialize anything. The source code of the language is already in its serialzed form. You can't beat the speed of not having to do something in the first place. As an aside, no sane person would write a SOAP webservice today.


I wrote a SOAP webservice -- not because I'm insane, but because our business relies on data sent to us.

We could certainly tell everyone that they'll need to write code to send us the data we need to be of use to them. Or we could look at the installed systems that hold their data, and see what built-in support those systems have for external integrations. And so: we quickly added a simple SOAP endpoint.

About serializing -- I'm potentially missing your point, but "The source code of the language is already in its serialzed form" doesn't seem to make sense. Who serializes source code? Values in data structures need to be transmitted, normally (sometimes in the form of source code -- e.g., JSON) -- homoiconic languages are interesting for other reasons, but not serialization.


So you're consuming data of an existing (legacy) SOAP service? Or complying with exisiting clients of a (legacy) SOAP service? That's not the same as writing a new SOAP service.

If the language you're using is already expressed in a form that does not need serialization, then you don't have to serialize it. This is the very essence of languages that are homoiconic. Perhaps you should familiarize yourself with that before down-voting what I have to say about it.


> So you're consuming data of an existing (legacy) SOAP service? Or complying with existing clients of a (legacy) SOAP service? That's not the same as writing a new SOAP service.

Neither; we're accommodating large, complex systems that only have a few options for "send selected data elsewhere". "Web services" (meaning SOAP) tends to be on that list, plus often other options that are completely unacceptable like "FTP".

> If the language you're using is already expressed in a form that does not need serialization, then you don't have to serialize it. This is the very essence of languages that are homoiconic. Perhaps you should familiarize yourself with that before down-voting what I have to say about it.

I'm someone who responded to you; I didn't downvote anything. I can try again: I use serialization all the time, to convert in-memory data structures into something I can send over a connection (or to disk, etc.), then to reconstitute them back into in-memory data structures on the other end. So I don't yet see how homoiconic languages play into serialization.


>If the language you're using is already expressed in a form that does not need serialization, then you don't have to serialize it.

Yeah. If only that language and "not needing serialization" code format didn't have 200 other problems, like NONE of the major services accepting it, lack of tooling, a sorry state of an ecosystem, difficulty of finding programmers and/or jobs, etc...


And the simple fact that taking code provided by a remote service and just using it as is just handing the keys of your server over.

LISP homoicity is nice but its a bad, bad idea to accept LISP code over the network from any client. Documented dataformats that are not executable are enough of a security risk that sending an executable around is not a great idea.

(Should have been attached to grandparent, as I agree with parent)


You really don't get it do you. An s-expression doesn't have to be evaled to be read. I just keep getting downvoted here. It's like offering a machine gun to a caveman and getting clubbed to death with it.


>An s-expression doesn't have to be evaled to be read.

Yeah, so you get a serialization format that's the same as your code. Big deal. And you have to live with your code having the same look as a serialization format. Even McCarthy wanted to give Lisp a proper syntax.

>It's like offering a machine gun to a caveman and getting clubbed to death with it.

More like it's coming to Paul Graham's house to tell him all about this new wonderful Lisp thing thing you've discovered. I mean, this is HN, what makes you think those that answered you don't already know and/or use Lisp and its homoiconicity properties?

Being used as a serialization format is perhaps the least interesting and useful property of Lisp code.


Okay, this suggests I'm not confused; there's just no argument given.

> Yeah, so you get a serialization format that's the same as your code. Big deal.

There's no reason this would be automatically a "good thing" -- a serialization format that is also valid source code -- it's just a thing. It's good to have a clean path from data structure to serialized data and back again; but if the obvious way to re-create the data structure (exec the code) has a huge security flaw built into it, that's no longer a clean path.

Human-readable serialized formats are nice; but guidelines on "readable" for a data structure vs. "readable" for full-power source code are not the same -- and "compact" is also strongly good for serialization formats, but not nearly so important for source code.


> Yeah, so you get a serialization format that's the same as your code. Big deal.

Oh, but it is! Making a massive compute grid can be done with just a few lines of code if your language is homoiconic. If you have to come up with a protocol and a data transfer format, well you have some work to do then.


This may be true but there are many existing SOAP webservices out there still, and the parent mentioned consuming a SOAP API.


SOAP certainly sucks, but regarding your comment on using lisp as the transfer protocol is a bad idea. Data transfer protocols must be verifiable - you should basically be able to write a piece of code that parses the data input and verifies that it will not do something bad if deserialized. Given that as far as I know, Lisp is turing-complete, this task is impossible. Therefore, Lisp, while being a nice programming language, is a very bad wire protocol.


Reading an sexp isn't the same as evaling it. Just read it and manipulate the resulting tree. Lisps have templating, marshalling, and unmarshalling built-in.


You've clearly never tried to implement a REST API using any flavor of Lisp before. Guess what: most clients of web services understand JSON and XML, not S-expressions.


Or in Clojure, it's

(sort #(compare %1 %2) coll)

To reverse it

(sort #(compare %2 %1) coll)

Where coll is the collection you want to sort. Same caveat applies with:

(reverse coll)

Try as I might I can't get Clojure to bench slower than its comparative Java. I see no reason to program in Java anymore wherever possible.


Java 8 counterpart to you Clojure variant is actually:

coll.sort(comparing(identity(), Integer::compareTo));

Or:

coll.sort(reverseOrder())


Better! Still much more complex, though.


I think we need something that could be called "The good parts of the Java/Ruby/C#/Javascript/... ecosystem".

Showing what tools and libraries are recommended at the moment and how some of them work together. In Javascript the ecosystem is growing almost exponentially which makes it impossible to keep up with everything. In Java and C# there is many old classes still in the libraries and around that most experienced developers avoid. And some trimmings of the ecosystem would probably be useful every 3-5 years or so.


I suspect readability isn't a big priority for you.

Here's how I'd write this, lambdas or not:

public static List<Integer> sortDescending(List<Integer> ints) {

      ints.sort(new Comparator<Integer>() {
          @Override
          public int compare(Integer o1, Integer o2) {
              if (o1.equals(o2)) {
                return 0;
              } else if (o1 < o2) {
                return 1; 
              } else { 
                return -1;
              }
          }
      });

      return ints;
  }
My personal perspective is that your use is a typical abuse which turns simple code into something unreadable and overly complex. This makes code hard to maintain and buggy. Not to mention, it's nigh impossible to step through in a debugger..


I'll meet you halfway:

      ints.sort((o1, o2) -> {
          if (o1.equals(o2)) {
            return 0;
          } else if (o1 < o2) {
            return 1; 
          } else { 
            return -1;
          }
      });
Or may i suggest a version with a guard clause and a simple ternary:

      ints.sort((o1, o2) -> {
          if (o1.equals(o2)) return 0;
          return (o1 < o2) ? 1 : -1;
      });
There's definitely no need for the 'new Comparator' boilerplate any more. That's not the kind of verbosity that adds clarity; it's just ceremony.


shrug. This seems like a pretty standard use of the ternary operator to me. I mean, just google examples of Comparator, and you'll find tons of examples like this:

   @Override
   public int compareTo(Object arg0) {
       Country country=(Country) arg0;
       return (this.countryId < country.countryId ) ? -1:
              (this.countryId > country.countryId ) ? 1:0 ;

   }
(http://www.javacodegeeks.com/2013/03/difference-between-comp...)

But that's orthogonal to my point, which is that lambdas offer significant improvements to readability because they remove the irrelevant cruft and simplify the code.


And lambdas (or similar) has existed in C#, Python, Scala, Javascript and other languages for years. I still thinks this means that those languages has had large benefits compared to Java (7 and older). Now that Java 8 has lambdas even Java developers can learn to write better and more readable code. I also thinks that Java 8 is good enough for most projects now but Java 7 wasn't. Just my thinking.


I'd have to agree, the GP is very bloated when a simple ternary will suffice.


one line is way more readable than 7 lines taking up valuable vertical and brain space

it could also be accomplished with

    return -1 * o1.compareTo(o2);


Why not:

    return o2.compareTo(o1);


because the o2 vs o1 is easy to miss, while the -1 makes it obvious i'm intentionally reversing. my .02


Not if you give them more descriptive names


No, you can't. In particular -1 * Integer.MIN_VALUE == Integer.MIN_VALUE.


That would probably never matter in practice, though—I've rarely seen compareTo() return anything other than -1, 0, or 1; certainly never anything approaching MAX/MIN_VALUE. Still, bravo for considering all of the edge cases.


Ant has a bad reputation? I clearly didn't get the memo - I find Ant to be a great little tool.


Some of us don't care for XML as programming language syntax.


I've used Ant, Maven, and Gradle, and Ant is the only one that's never given me a minute's trouble. But it's true that it has a bad reputation. It feels harder to use when everything is working right.


Agreed, find errors in Ant scripts is a pleasure compared with piles of Maven plugin errors.


Ant's one of those "seldom skills". You set it up in the beginning and then tweak a little bit. Yes it works, it's fine. I just find it funny that it hasn't changed or evolved in a long time. I just keep taking my old examples and tweaking them. It's weird.


Agreed, ant is solid, the build system makes sense and is clearly laid out.


Lambda expression for comparator can be further shortened (for numeric types, descending):

( o1, o2) -> o2 - o1

No ternaries or else-ifs required. Swap o1 and o2 if you want ascending.


>>Java8's lambdas + streams provide significant improvements.

It will take more than a decade before we see any decent adoption of Java 8 in the industry.

You are still going to see piles and piles of getters/setters, Enums, your design patterns taken to far extreme. Writing such pointless ceremonial code is the bloodline of Java community.

Merely introducing a new version hardly changes anything.


The community that takes design patterns to far just happens to use Java (1.4 ;( ) if they used a different language they would do the same to that :(

Anecdote: I once saw a Perl shop that could have been the worst of Enterprise Java. They where the same because they where ENTERPRISE, they suffered in Perl in the same way the common office programmer suffers in Java.


I was with you until the Lambda stuff. I find the anonymous class _far_ easier to read and code.


Verbosity matters for reading and maintenance far more than it does for writing. IDEs can make the writing faster, but they can't make the code as easy to comprehend as it would be in a more expressive language. And remember that lines of code is the only proven risk factor for bugs.

Most sites are not Twitter. They're not Stack Overflow. They're not even Nanowrimo. I've watched a company spend two years, dozens of developers, and over a million in ESB license fees failing to write a site that was expected to have, at peak, 100 users/day. Their competitor had four guys writing Ruby, and was profitable after the first month. Nor are the performance advantages "permanent"; even if you use Java, you will probably have to rewrite if you reach Twitter scale, because your initial app won't be clusterable (or if it is, it's massively overengineered and your business will fail). So do it the way twitter succeeded - write the first version in Ruby, and then worry about performance when you need to.

The advantage of using the same language on both sides of a boundary are real but overstated. If you have a system with multiple components, you probably need to evolve the interfaces between them, and you need to be able to upgrade without downtime. Which means you need well-defined interfaces for which you understand the compatibility implications - in other words, you need something like Thrift. I've used Thrift even for Java-Java interfaces, but once you're using something like that it doesn't matter which language is on the other side.

Still, the library point is valid, as is the point about spending time with a language. Better to have one language that you know very well than ten in which you dabble. But by the same token it's worth taking the time to make sure that language is the very best available. I use Scala for everything, and there's plenty to learn - maybe even twice as much as a "normal" language. But if I'm focusing on that one language, I can afford to take the time to learn it really well. And Scala combines the expressiveness, clarity and scripting-suitability of Python (yes, it can be unclear if you use silly method names or libraries that use silly method names - don't do that then) with the strong type-safety and performance of Java. It's a great language in any case, but especially if you want a single language for everything, I don't think anything else comes close.


> I've watched a company spend two years, dozens of developers, and over a million in ESB license fees failing to write a site that was expected to have, at peak, 100 users/day.

I'm sorry to hear that. But you understand that this had nothing to do with Java, right? Java didn't make those people do that. That was just good old fashioned human stupidity. It's entirely possible to write simple things in Java, without ESBs and a person-century of effort.

It's even possible to write simple things in Java EE - there's an enjoyable little book about it: http://press.adam-bien.com/real-world-java-ee-night-hacks-di...

> Nor are the performance advantages "permanent"; even if you use Java, you will probably have to rewrite if you reach Twitter scale, because your initial app won't be clusterable (or if it is, it's massively overengineered and your business will fail).

I don't think this is true either. The normal approach to writing scalable apps these days is the twelve factor approach:

http://12factor.net/

And that works just as well for tiny deployments as huge ones. It doesn't involve doing anything arcane and expensive up front. It's mostly common sense. Scaling out will involve a lot of changes, but incremental ones.


It's entirely possible to write simple things in Java, without ESBs and a person-century of effort.

That I don't disagree with (see Java4K and various other demoscene-like competitions), but when the mainstream culture of Java is oriented towards architecture-astronautism and "enterprisey" bureaucratic excesses of complexity, that's what the majority of Java developers you find are going to do. Ask them why a simpler (and less time-consuming) solution wouldn't suffice and they'll respond with things like "robustness", "extensibility", "modularity", "encapsulation", "abstraction", etc. even when none of these properties are truly applicable to the situation at hand. If I were to guess why, they're just so accustomed to writing code with such indirectness that a simple solution feels "wrong" to them. I worked very briefly for a Java shop and on one occasion my code was rejected, and was told to "refactor" a fairly trivial 20-line method in one class into 8 separate classes each containing 1-line methods on account of the fact that my original code was not "extensible" nor "modular" enough. I was suggested to introduce a design pattern to do this. Any advantage of that extra flexibility was never realised since the application was eventually completely scrapped in a rewrite. (I left shortly after that.)


"was told to "refactor" a fairly trivial 20-line method in one class into 8 separate classes each containing 1-line methods"

How typical is this level of non-value adding misguided pedantism? I understand that big software consultancies would want to milk their clients for all the work they can for implementing function points. But what profitability models drive developers to this level of weirdness? Is it just a cultural pathology?


It's plain and simple pedantry, and it's not confined to Java. This mindset has a healthy representation in the Ruby community, which actually makes programming in Java much less distasteful to me -- if I'm going to be writing AbstractSingletonFactoryAdapters, then at least let my AbstractSingletonFactoryAdapters be fast.


This is excessive but I've seen numerous similar cases. Premature code future-proofing has always struck me as similar to premature code optimisation. Generally something that newer/weaker devs tend to do until they learn better.


Enterprise. It is just how the enterprise world works.


No it is not. Just because you have a one bad experience, doesn't mean that is how the enterprise works. There are hundreds of thousands of enterprise shops out there. We don't do anything like the craziness you guys are talking about. We make it work with the easiest code possible. If necessary we refactor when we need to make a solution more generic.


Java at Amazon, Google, Twitter etc. is generally less pedantic and more focused. I have been a Java developer since 1997 and the only time I've seen the type of pedantry you are talking about is at non-technology companies where the most important metric is how cheap a developer is, not how much value they can add.


> I'm sorry to hear that. But you understand that this had nothing to do with Java, right? Java didn't make those people do that. That was just good old fashioned human stupidity. It's entirely possible to write simple things in Java, without ESBs and a person-century of effort.

It's an extreme example of the same mistake this blog post is making. I mean, from a certain point of view they were right - if the site had reached twitter scale, it would have needed those things. The market genuinely is growing, and the problems the system solves exist in almost every industry. I expect those four guys won't keep their system in Rails forever.

Maybe using PHP really will make your system slower by a factor of 15. So what? A trivial saving in development time - say a week over your first year, a 2% factor - is well worth that 15x performance penalty for most businesses.

((Don't use PHP, kids. But not because of the performance))

> The normal approach to writing scalable apps these days is the twelve factor approach

Hmm, I wonder how many people have heard of this, and you say it's "the normal approach".

Debugging distributed systems is and always will be harder than debugging monolithic systems. Even the simple engineering good practices from that page, like explicitly declaring dependencies, have a cost. My Google friends tell me their explicit policy is to design a service for one order of magnitude more than the current traffic, and expect to rewrite it after that.

And once you're doing the things you need to scale - explicitly defined interfaces, all calls going via the network or something equivalent to it, service discovery - then changing the language used in parts of the system really isn't that big a deal. You can do it incrementally. (I have experience of doing just that, at last.fm)


> I expect those four guys won't keep their system in Rails forever.

For people who didn't know this, I would like to add that Twitter was written in Rails as well. They switched later on for a couple of reasons[stackoverflow].

[stackoverflow] https://stackoverflow.com/questions/9747857/why-couldnt-twit...


i use PHP and i got customers and revenue and retention rate too

facebook use php

deal with it

programming language is one thing, marketing your solution is another thing


facebook is using php compiled to C++, and that's only for their frontend. Mind your anecdotal evidence :)


Actually, Facebook is using PHP executing on a JITting virtual machine:

https://www.facebook.com/notes/facebook-engineering/speeding...

Mind your out-of-date rebuttals to anecdotal evidence :)


> The normal approach to writing scalable apps these days is the twelve factor approach

I've never even heard of this. I agree with most of this advice, but, I wouldn't exactly call it a defacto standard.


My bad. I suppose i live in a bubble just like anyone else. I do think this is a well-known approach within the bits of software culture that talk about scalability. If you're a regular reader of highscalability.com, or a developer at Netflix, or one of the sad nerds who wish they were (eg me), or you've read the Heroku documentation, you've heard of 12-factor. But no, not everyone has, and in particular not every working stiff who shovels Java for a living.


Is there an update to this book or something similar that speaks to Java +7?


The book is mostly about the use of the Java EE APIs. As such, it's not all that affected by the evolution of the core language from 6 to 7 to 8.

However, it probably will be affected by the evolution of the Java EE API. EE 6 was a huge, massively simplifying, change from EE 5, which is why it needed a book like this. EE 7 was a fairly incremental change from EE 6, and EE 8 is set to also be a modest step forward.

The biggest change in EE 8 - and i don't know whether to laugh or cry about this - is that Java will be getting a standard web MVC layer. Fifteen years after such things first appeared on the scene, and five years after they became passé. Maybe there'll be an API for controlling dialup modems or AIM clients next.


> they can't make the code as easy to comprehend as it would be in a more expressive language.

It's a little hard to make a general statement using an vague term like "expressiveness".

Static typing can actually make things clearer. That's a kind of expressiveness. You can know with complete certainty what type of data the code works with, just by looking at it. No need to rely on a certain set of unit tests living somewhere else to confirm your assumptions. And if you say "well just read the function docs", how is that any less verbose in the end? It's the same verbosity, minus the compiler guarantees.

On the other hand, there are situations where DSLs can greatly cut down on route programming. Like Apache Pig vs. calling Java APIs. But that's a more extreme example, an actual speciality "domain" to make a specific language for.

I might help to use a more precise term like verbosity. Then we can ask, is this verbosity really helpful (like explicitly declaring types), or can we compact it without losing significant information. Fortunately Java 8 has made some progress with adopting features that cut down on unnecessary verbosity.


Static typing can make things clearer, indeed, however Java has really shitty static typing. Also this is a common misconception:

> You can know with complete certainty what type of data the code works with, just by looking at it.

First of all, the type is only a limited view of the shape of the underlying data, written from the perspective of the business logic using it. In a micro-services architecture it happens often to see the same data exposed with types that are often very different, depending on what you're trying to accomplish. And too often developers that work with Java are complecting the business logic with the actual data, which is often pure data that's being messed up with short term business logic rules.

And furthermore, Java developers don't work with static type safety. Tell me, what does a String tell you? What does a Double tell you? How often have you seen explicit type-safe numeric types in Java (e.g. lets say values that are in kilowatts, or meters, or other units of measure)? You don't see that, because Java is awful at expressing such types, from the lack of operating overloading, to the completely retarded generics system and the lack of type-classes.

Second of all, the type IS NOT sufficient documentation when dealing with non-determinism and if side-effects happen in your system, then that's non-determinism. And when non-determinism happens, you need to document the protocol of communication and static types in mainstream languages cannot capture that, which is a PITA because that would be far more useful than seeing that this Person has an email address.


> In a micro-services architecture it happens often to see the same data exposed with types that are often very different

You mean micro-services that use dynamic instead of strongly typed APIs? That's really more a critique of such architectures than the facility of static typing.

> Tell me, what does a String tell you? What does a Double tell you?

It tells you you can't use a String where a Double is needed, without unit tests, from the very moment you type the reference in your IDE.

You're correct that it doesn't eliminate all possible problems such as validating the unit of measurement, and that it's not sufficient documentation in and of itself. But that's not the goal of static typing. It's there to eliminate a very large swath of problems through simple declarations in code.


Type safety is valuable, but you can have equivalent or better type safety in a much less verbose language than Java. e.g. I use Scala - it's not quite as concise as Python, but it's pretty close, and the language is powerful enough that I can express more possible effects directly in the type system (Does this method make an async call? Does it access the database? Does it log audit events?) without the code becoming unreadably verbose.


Care to share more details of these companies including how the Ruby ones become profitable after a month with 4 guys on payroll? No offense but I've got to check the facts these days.. :).

Also, don't forget Fred Brooks article about the Second System. I betcha smart engineers on tight budget can hack in Java just as quick as those 4 guys and achieve the same result. My apology, Java today is as productive as Ruby on Rails.

The difference between rewriting a Rails site to Java and an already written system un Java to a more modern architecture is huge. One can slowly move from old Java architecture to the newer one but it'll be trickier from Rails to something else... don't forget the accumulated Ops experience managing jvm based app server, the devil in details for those experienced engineers who have been there and done that...


> Care to share more details of these companies including how the Ruby ones become profitable after a month with 4 guys on payroll? No offense but I've got to check the facts these days.. :).

It was small industry, those were basically the only two companies in it, I don't feel I can. (I've already changed some small details e.g. it wasn't actually Ruby). In any case it's just one person's anecdote - but I bet it's happened a lot.

> My apology, Java today is as productive as Ruby on Rails.

Citation needed. In the programming language shootout Ruby still comes out much shorter than Java, and like I said, the only proven risk factor for bugs is number of lines of code.

> One can slowly move from old Java architecture to the newer one but it'll be trickier from Rails to something else...

When I worked at last.fm this was literally my entire job (well, from PHP). You're rearchitecting anyway, creating stable interfaces and putting load balancers in there because those are also things you need to do as you're scaling up. Changing languages is no harder.

> don't forget the accumulated Ops experience managing jvm based app server, the devil in details for those experienced engineers who have been there and done that...

You can hire the experience - Java is literally the easiest language to hire for (I mean, hiring is still hard, and there are a lot of crap java programmers around, but there is a bigger pool of experienced programmers out there than any other language). And you're going to need to hire anyway; your ops team will have to grow, your engineering team will have to grow more, and you absolutely cannot rely on the engineers who bought the first version still being around when the time comes to rewrite; the half-life of an engineer in a startup is not large.

Twitter was the article's choice of example, not mine - and from a business point of view Rails worked really well there.


>the only proven risk factor for bugs is number of lines of code.

I'm sure you can cite that, but it feels wrong in this context.

That is, given the same language, or equally verbose languages, it may be true and applicable. But, if comparing a more verbose language to one that is less so, then the former will naturally yield a higher LOC count. But, does this mean it's more bug prone? There aren't any more logical constructs, flow control mechanisms, etc. The language simply requires more lines to express the same intentionality.

In fact, I wonder how a more verbose language would compare with a less verbose one if we normalized for some verbosity factor. So, let's say language A is twice as verbose as language B, such that when the LOC count of A is twice that of B, we consider them equal (call it the same "Effective LOC").

I actually wonder if, in this case, language B would have a higher bug count per effective LOC, owed to its terseness and/or reduced readability.


[flagged]


This behaviour - downvoting without explanation irritates me too when there is very lucid and concisely structured argument you can oppose.

As such, I do not find your argument for verbosity normalizing convincing :)

I fail to see how normalizing some risk metric against a verbosity of language will provide any valid data in the general context. For numerical algorithms, where a multiplication is just as verbose in any language then there is no difference.

But when manipulating collections, for example in C I need to write int i; for(i = 0; i < someSize; i++){...}

This has several places where the verbosity of language can make it easier to write bugs that slow down the progress a bit. If we add these tiny slowdowns throughout the lifecycle of the entire application the cost is not neglible if compared to a situation where these bugs would not appear at all. Some other language:

for i in collection do:...

Which does really have no place to shoot oneself in the foot unless the iteration logic itself does something funny.


Well, I can appreciate the reply versus a downvote, but "I do not find your argument [against] verbosity normalizing convincing." :)

>I fail to see how normalizing some risk metric against a verbosity of language will provide any valid data in the general context.

OK, then let's look at the corollary: that is, not normalizing against verbosity would mean, roughly, that you're claiming that a language that is twice as verbose would yield twice the bugs over the same app. I don't think that's the case nor what you intend to say.

I think you're also confusing complexity with verbosity. An extremely terse language can be very complex, and may even suffer from readability issues.

Overall, the notion of LOC alone being a risk-metric absent any additional context seems an oversimplification.


"Overall, the notion of LOC alone being a risk-metric absent any additional context seems an oversimplification."

Yeah, I agree completely. Didn't think too long before answering there, I'm afraid. I confused the fact that in my experience increase of LOC correlates with increased risk of bugs with there actually being a causality between the said observables.

For me personally languages with higher LOC are harder to read, but this is just about the languages I like and not a generalization that can be applied to any language in general (i.e. Ocaml is nicer than C in this sense but APL or J would get me just terribly confused).

Basically, of the languages I consider readable, and when dealing with container operations, it's easier for me to parse especially those that either have basic containers as fundamental data types in the language (e.g. Python, F#) or have a uniform syntax over typical algorithms and containers (Clojure) rather than verbose languages like C or Java.

In these instances, it's not about the overall LOC count of the languages but the fact that they make common operations more legible and easier to reason with than C. I.e. they have less non-value adding burden typically. Why they are nicer, is not because of their LOC, though, but their LOC is a side-effect of their features that make them nice, I think.

Thanks for pointing this out :)


>Thanks for pointing this out

Well, I think you actually described it more eloquently, once we got there. :)


What you argue is not that LOC in itself causes bugs, but that certain programming syntaxes are both complex (thus induces bugs) and takes up more LOC.


Oh, that I did. Very true.


>You're rearchitecting anyway, creating stable interfaces and putting load balancers in there because those are also things you need to do as you're scaling up. Changing languages is no harder

I have to disagree here. With just a little forethought, a good bit of the code can be reusable. For instance, your data access layer.

And, the more forethought you put into it, the larger the potential reusability. This doesn't have to be premature optimization. It's just a balance between getting it done as quickly/efficiently as possible while still making some sensible, fairly low-cost coding decisions for scalability. For instance, everything I write now is load-balancer ready. This was achieved largely through a simple library that understands its environment via a simple config directive, and proxies relevant calls (e.g. when pulling the client IP or checking whether the request is secure, it determines when to pull from the request headers stamped on by the load balancer versus invoking request.getRemoteAddr() or request.isSecure()). Of course, there are other coding decisions you make, but it's really not as much extra work as how you implement.

In any case, unless you're purposely writing completely nasty throwaway code, there is always some reusability, which typically makes starting from scratch in a new language a much weightier prospect than making some scalability enhancements to the existing base.


> In any case, unless you're purposely writing completely nasty throwaway code, there is always some reusability, which typically makes starting from scratch in a new language a much weightier prospect than making some scalability enhancements to the existing base.

It's not really from scratch. If you've figured out the correct structure and interfaces to solve your problem you can reuse all that when porting to a different language, and that's the hard part of development.


>If you've figured out the correct structure and interfaces to solve your problem you can reuse all that when porting to a different language

Well, I think you're underestimating the sheer brute force work needed to port an app with a large-ish LOC base.

But, beyond that, if you've gone through the care of structuring it correctly such that the structure and interfaces are preservable once scalability needs arise, then all the more reason not to port it. Presumably, at that point you'd have, not only the structure, but working code.

So, if it can be so readily adapted to a new language and you're preserving so much code, then why bother porting it? Kind of makes may original argument. Just apply the scalability tweaks on the existing code base and you're done.


> Well, I think you're underestimating the sheer brute force work needed to port an app with a large-ish LOC base.

I have done this professionally. You don't port everything, you just port services as they become bottlenecks. By the time you need to scale like this, you already need to have multiple engineering teams and you need well-defined interfaces between components, so having parts of your system in different languages doesn't impose an additional cost.

> So, if it can be so readily adapted to a new language and you're preserving so much code, then why bother porting it? Kind of makes may original argument. Just apply the scalability tweaks on the existing code base and you're done.

Sure, which is probably why Digg was happy to carry on using PHP. For the vast majority of systems you never get to the scale where using Java is worthwhile (at least in performance terms).

When do you want to port? When your server costs get high enough that a 15x performance factor is worth the constant cost in dev time that using a lower-level language would cost[1]. It might take more effort than writing in Java from day 1 - but it might not, if you go through several iterations of prototyping/refactoring in PHP and then only port once you've found the correct design. And more importantly, you get to pay the Java price much further down the line, when you're bigger and more profitable. As PG says, an early-stage startup should do things that don't scale.

[1] I'm not convinced you can't have your cake and eat it, with e.g. Scala or Haskell. But assuming for the sake of the argument that the only languages were Java and PHP and PHP really was more productive than Java but less performant.


>I have done this professionally. You don't port everything, you just port services as they become bottlenecks.

Yep, been there too. Except, in the case I'm thinking of, it wasn't for performance. We went with a multi-language approach for different reasons, and we ended up with a hybrid that no-one liked. Then, we finally decided to port everything to one language.

All of this to say that a multi-language approach can have its own drawbacks, which is not to say that it's never appropriate. There should just be a really good reason for it. Generally, I'm not sure that starting with a plan to half-port a non-performant app is a good reason. But, I'd never say never.

I'd also add (again) that if you've really taken the time to structure the app so well that you have clean interfaces and modularized, easily-portable services, then it begs the question: did you really save so much time by then implementing that design in PHP vs Java? As you said, the design is the hard part, and I'm just not seeing the notion of a quick non-scaling app, somewhat hastily implemented in PHP, being compatible with the idea of a tight, service-oriented, modular design. I think you kind of have to choose one.

I don't suppose any approach is necessarily the absolute right approach per se. But, given that the article is about picking one approach/language (Java) and sticking with it, I'd have to say that I'm still convinced that it may indeed be optimal, even after reviewing your points.


> I'm just not seeing the notion of a quick non-scaling app, somewhat hastily implemented in PHP, being compatible with the idea of a tight, service-oriented, modular design. I think you kind of have to choose one.

Oh sure, the initial code was pretty terrible. But by the time we were moving parts to Java it had all gone through a lesser or greater amount of refactoring; the best design is iterative and emergent, and we had the http://c2.com/cgi/wiki?WhatIsAnAdvancer experience several times over. In the early stages you really can iterate faster in not-java; as the correct design emerges and the codebase gets larger the interfaces tend to firm up, and at that point it becomes more reasonable to port pieces for performance.


> like I said, the only proven risk factor for bugs is number of lines of code.

There's never been a proof that writing code in Ruby WILL give you LESS bugs than in Java just because you'll end up with LESS LOC. I think this is a generic statement that needs to be clarified.

I agree and I will not argue that LESS lines of code "might" give you LESS bugs given that you're writing it using the SAME language (version 1 in Java has more lines than version 2 in Java, maybe because in version 2, the developer gained more experience and can write idiomatic Java and use libraries instead of rolling his/her own). But Ruby yielded less bugs because of less line of code is a marketing speak to sell the religion of Ruby.

Sometimes I wonder why developers aren't forced to just use LISP since everybody in the whole world knows that LISP is super expressive that it MUST resulted in far less code right? Right?

> When I worked at last.fm this was literally my entire job (well, from PHP). You're rearchitecting anyway, creating stable interfaces and putting load balancers in there because those are also things you need to do as you're scaling up. Changing languages is no harder.

Fred Brooks Second System http://en.wikipedia.org/wiki/Second-system_effect is exactly what you're experiencing, forget the language war for a second please. Really.

I work for a company that has been using Java since probably 2002/2003 (I joined in 2012). Server-side in Java with Client-side in Swing, slowly evolving the Server-side POJO (probably no Application Server), to EJB 2.x (shudder) to EJB 3.x and goes to the cloud we go (AWS). Recently we refactor a certain part of our code and added Microservice written in JAX-RS because we have to integrate with another product suite internally. That's what I called re-use and evolution of code-base: 10 years of Java where some of the code from the past were/are reused and still in production today. (.... but boy those old code aren't pretty, hehehehe).

Oh, I almost forgot the part where we used shell script to build, moved to Ant, moved to Ant + Ivy, and slowly moving to Maven (if we need to write a new microservice, maven by default, the rest have to move slowly).

Oh, here's the best part: last year we moved away from homegrown migration tool to use Flyway, 4-6 lines of Java code to initialize and execute the migration workflow dropped in our old Java code.

So yes, if we had to re-write and re-write and re-write to different languages every time, it is definitely will be harder.

> You can hire the experience - Java is literally the easiest language to hire for (I mean, hiring is still hard, and there are a lot of crap java programmers around, but there is a bigger pool of experienced programmers out there than any other language).

Ops, not devs.

> and you absolutely cannot rely on the engineers who bought the first version still being around when the time comes to rewrite; the half-life of an engineer in a startup is not large.

Thank God it's Java, not PHP, not Perl, not Ruby (I give Python a pass because I'm being nice). IDE helps a lot. This reminds me of Zed Shaw blog about charging a lot of money fixing Rails mess as a consulting service.

> Twitter was the article's choice of example, not mine - and from a business point of view Rails worked really well there

I'm not suggesting that they made a bad move or whatnot I'm just merely debunking the common stories of how small team beat big team (that may have big expectation/big scale yet not focused on solving customer needs) because of the technology/languages. Talent is something else. Tech/Languages/Scaling? sounds like ego problem there.


> Sometimes I wonder why developers aren't forced to just use LISP since everybody in the whole world knows that LISP is super expressive that it MUST resulted in far less code right? Right?

You've fallen for Lisp propaganda :P. If you look at the shootout, Python and Ruby are comfortably ahead of Lisp in the expressiveness stakes.

> Fred Brooks Second System http://en.wikipedia.org/wiki/Second-system_effect is exactly what you're experiencing, forget the language war for a second please. Really.

Really not. This was one of the leanest places I've ever worked; everything we did there was absolutely necessary for the scale we were operating at. I've seen second-system effect in action; last.fm wasn't it. Writing Java will not save you from having to scale horizontally; maybe it's 2x, 5x, 10x faster than a dynamic language, but if you're growing then these kinds of constant factors only buy you a small amount of development time.

> Recently we refactor a certain part of our code and added Microservice written in JAX-RS because we have to integrate with another product suite internally. That's what I called re-use and evolution of code-base: 10 years of Java where some of the code from the past were/are reused and still in production today. (.... but boy those old code aren't pretty, hehehehe).

If you're using microservices multiple languages really shouldn't be a problem. It's not like we rewrote everything; services that were fine in PHP stayed in PHP. We moved things to Java as and when we needed to. If everything's a service (Thrift in our case) then it really doesn't matter what language is on the other end.

And it's not exactly "from scratch". Physically typing out the code is never the bottleneck; most of the hard part of programming is design, getting the correct decomposition of the problem. Porting well-written code from one language to another language that supports the same paradigms is really not that hard, and certainly doesn't mean throwing away all the lessons of the first codebase.


> If you look at the shootout, Python and Ruby are comfortably ahead of Lisp in the expressiveness stakes.

The code in the 'shootout' is verbose, to make it fast. Much faster than Ruby or Python.

Generally small code in Ruby and Python can be more compact. For larger code this is then no longer the case, once the macro-advantage kicks in...


> Verbosity matters for reading and maintenance far more than it does for writing.

I would argue that on average verbosity improves readability. Yes it may take you slightly longer to read the code, but verbosity often results in the code conveying more information or expressing it clearer (or both).


I would rewrite that as "_explicitness_ improves readability". When I read Java code, I rarely have trouble to know what the code is doing (at least at a local scale).

Not all static-typed languages are readable because they're not all explicit. In C++ for example, even the most trivial snippet of code can be obfuscated by all sorts of abuse: operator overloading, implicit calls to copy constructors, preprocessor macros, etc. Scala suffers the same problem, perhaps even worse, doing tons of stuff automatically i.e. in a way that's not obvious by just staring at a code fragment such as an individual method. Organizations that have success writing large-scale code in such languages [I can speak for Google here], typically have careful style guides that ban the bad stuff and are strongly enforced by code review process; but in that case you're not using language X anymore, you're using some "safe subset" of X.

Of course you can't have any high-level abstraction without some tradeoff of maximum explicitness; virtual calls for example make hard to know which exact code is invoked by "just staring" at an invocation. The trick is striking a healthy balance between power and readability. Java is not perfect in this criteria (it errs a bit in the side of caution), but it's certainly much better than any dynamic-typed language.


Just repeating the same thing twice doesn't help with anything. The standard examples of Java verbosity - repeating variable types, getters and setters, anonymous classes instead of lambdas, using the visitor pattern to emulate pattern matching - don't make anything more readable or clearer (indeed many people find the Java version more confusing to read).

What features does Java have that you're saying help code convey more information or lead it to be expressed more clearly? I find that my more concise Scala code usually both is clearer (there's just less irrelevant clutter e.g. braces) and conveys more information (because e.g. error handling with Either and for/yield makes it clear which parts of a function could have errors, whereas with try/catch all you know is "there's a function somewhere in this block which throws").


> Just repeating the same thing twice doesn't help with anything.

I completely agree - but not all (or even most) of Java's verbosity is from repetition. The traditional example of `Foo foo = new Foo();` as repetition ignores the fact that `Foo` will not always be repeated as the first will often be an interface (or superclass) and the second will be an implementation, e.g. `Set<String> set = new HashSet<>();`

> What features does Java have that you're saying help code convey more information or lead it to be expressed more clearly?

My comment regarding verbosity wasn't in comparison to Scala, I was thinking of Ruby, Python, Lua, et al (I'm a huge fan of Scala btw, but the post was on the benefits of Java versus dynamic languages). Anyway to answer your question with a few examples:

* Java's method signature gives me a lot of information, looking at `public int doStuff(String foo)` tells me the visibility, what it will return, and exactly what I can pass it - even to someone completely unfamiliar with the language. Looking at `def doStuff foo` tells me nothing other than how many arguments it takes (if you're familiar with Ruby you'll also know the visibility).

* Similarly when you see `return foo` you know (even knowing nothing about Java) that it's returning `foo` and that `foo` is the intended return value.

* Someone who's never read a line of Java in their life can look at `Map<String, Integer> foo = new HashMap<>();` and know that `foo` is a map (and will most likely conclude it has Strings for keys and integers for values). If you've never coded in Lua and you see `foo = {}` you have no idea what that is (if you've seen similar in other languages you can make a good guess, but you don't know).


A significant amount of the article is arguing that Java for everything is better because the author and his coworkers already knows it. I can make the same argument for Python _for me_. And for my company too; we have a ton of Python developers already, so it makes sense to write things in Python if possible in case someone needs to change or improve anything.

The author also talks about how Java's verbosity is a trivial issue, and in terms of "stuff you have to type", I agree. The point isn't to save a few characters to type. To me, the problem with Java's verbosity is that it _impedes understanding_. The excessive notation required by type declarations and generics and so on are visual noise that distract from what the code is doing.

There are some valid points raised too, such as concerns about Python's scalability, but that's an argument for _choosing the right tool for the right job_, which, while mocked at the beginning of the post as a way to avoid an interview question, is still good advice. For a lot of projects, Python is fast enough to handle the expected processing, has an ecosystem with libraries that handle all of the things the project might need to do, and is portable enough to run on the platforms necessary. For some projects, it fails one of these, and another language may be a better choice. That's okay!

I think the best takeaway here is that it is sometimes useful to see if you can leverage your existing knowledge in one programming language by applying it to a task you don't normally use it for. By all means, write shell scripts in Java, maybe that's really useful! Or maybe write a GUI in Haskell! Transpile BASIC to frontend code!

(For context, I use Python for web development (both small and large sites), scripting, and a few personal projects like a music player or emulator. I did a bunch of Java in college and some internships.)


> A significant amount of the article is arguing that Java for everything is better because the author and his coworkers already knows it.

Far more of the article is spent on arguments that are valid for any compiled statically-typed language. So much so that he feels the need to point out why Java [as opposed to C#, C++, D, Go] in the penultimate paragraph.


Though the lack of noise could also translate to parsing things in my head trying to understand what is happening in this super short code....hence it takes longer to read the code!


Maybe, but what are the examples? "Foo f = new Foo()" takes longer to read than "f = new Foo()". An anonymous class is longer than a lambda and also less readable, as Java folk have thankfully finally realized. "public static void main" does not clarify anything. Getters and setters are the bane of my Java-reading life, because 99.9% of them are the exact same autogenerated four lines, but you still have to read them all in case one of them is different.

Also, there's a huge jump in readability at the point where a method or class fits on a single screen. So if 4 lines of Java = 1 line of Brand X, but it takes me the same amount of time to read 4 lines of Java or 1 line of Brand X - that's still a win for Brand X, because it's much easier to write classes that fit on a single screen.


True! It requires some skill to write concise code that can be understood easily. I think that the required verboseness of Java makes things worse than the potential for excessively-short code does in Python, though.


> There are some valid points raised too, such as concerns about Python's scalability

But if you think about the two python scalability problems :

1) speed

2) programs become unmaintainable as they grow way quicker than they do in java and the like

Nobody's arguing to write shell-scripts in Java. Why are people arguing writing websites that will include more than a trivial amount of functionality in anything but Java ?


(1) isn't really something that's terribly arguable one way or another (In my experience Python is plenty fast for most tasks, but my tasks differ from your tasks).

I question (2) though. Why do you think that a Python program will become unmaintainable faster than a Java program? Is it type errors? Or maybe you think it's difficult to figure out what values are expected in a given variable? Or is it something else?


The problem with verbosity and repetition is not that it takes longer to type the code, at all. The problem is that it creates dependencies which you have to manage by hand.

Changing `Foo a = new Foo()` to `Bar a = new Bar()` doesn't seem that bad... except when you have to propagate that change through the code base. Half of Java's tooling is dedicated to solving a problem that doesn't exist in good duck-typed languages or those with type inference.

Verbosity is also a warning sign for lack of expressive power. If you have a pattern like `if (cmd == "run") run();` in multiple places in your codebase, you want to make it so that changing one changes them all. Java won't let you factor this out easily, but worse, it won't catch you when you make a mistake (better languages will either do first-class functions or pattern matching and exhaustiveness checks).

Note that this has nothing to do with static vs. dynamic; verbosity is a problem that can be solved in many ways, but it is a problem. The author also spends a lot of time equating statically typed with fast; well, there are plenty of very fast dynamic languages.

There certainly are reasons to like Java, but these aren't them.


> Changing `Foo a = new Foo()` to `Bar a = new Bar()` doesn't seem that bad... except when you have to propagate that change through the code base. Half of Java's tooling is dedicated to solving a problem that doesn't exist in good duck-typed languages or those with type inference.

A sweeping change like that is hard in Java, but it's nearly impossible in Python. That is, unless you're willing throw up your hands and assume your new duck looks enough like the old one, and cross your fingers that you don't find out in production one day. With a modern IDE like Eclipse, it's a fairly trivial matter to find all references to the class, navigate call hierarchies and make the necessary changes to adapt to the change in type. In a sizable Python program, good luck. You're pretty much forced to rely on string searches - hope you picked a distinctive function name - or interactive debugging. Ease of refactoring is a huge win for static types IMHO.


I'll be the first to agree that Java-style class hierarchies and duck typing don't mix well, but not every dynamic language is Python. Clojure, for example, is very easy to refactor when it's (very rarely) necessary.

Not saying static typing doesn't have it's advantages – tooling is probably Java's greatest strength – but there are other, equally valid, solutions to the problem.


DISCLAIMER: I write mostly java, at home and at work.

Refactoring goes a lot further than just renaming types. A refactor script _WILL_ rename both sides of 'Foo x = new Foo();' to 'Bar x = new Bar();', so given the right utilities (and if you use java for everything, it's _MUCH_ easier to become an expert at the tools!) this is not any more effort at all.

However, there are refactors for things that are much more difficult in a duck typed language. For example, if I have a bunch of methods named 'execute()' in my code, and I decide that this is a sad state of affairs and ripe for a refactor, I can refactor one of them to a different name and the tools will 'get it right', renaming the right calls (calls into this type) and not renaming the wrong ones (calls to another type's execute() method which has no relation to this type's execute() call). In python, you just can't do that. You'd have to rename all of them, defeating the point.

Similar concerns crop up for 'find callers', or 'add argument to method'.

There are also refactor scripts that are equally possible in both python and java, but which nevertheless require either a lot of manual editing, or an intelligent tool that can automate it, such as 'extract method' (taking the selected code and turning it into a (helper) method, figuring out which variable(s) would have to be passed along to make it all work as needed.

The point is: Duck typing does not obviate the need for refactors. It does make certain refactors impossible to 'safely' automate ('safely' in the sense of ensuring that, post-refactor, the code does the same thing as it did pre-refactor).

As far as 'dynamic == slow, static == fast' being a bit of an oversimplification, yup, that's true. Java _IS_ a heck of a lot faster than python, but that's mostly an implementation detail; you could make a pretty quick python. dynamic definitely does not help, but it can be worked around. Javascript JIT engines are seeing a lot of serious improvements right now, and a large part of it is guesstimating type info. They're getting pretty fast.

In the spirit of the article, though, static typing isn't just a boon for speed reasons (based on the practical upshot that java IS fast, and most dynamic solutions simply aren't, even if they could be with more engineering efforts): It becomes quite useful when you start having to read the additions to your code written by someone else, or rereading your own code half a year down the line when updates are required. explicit static typing also helps with refactoring, which is useful especially when you have to fix or extend your project.


Refactoring goes a lot further than just renaming types. A refactor script _WILL_ rename both sides of 'Foo x = new Foo();' to 'Bar x = new Bar();', so given the right utilities (and if you use java for everything, it's _MUCH_ easier to become an expert at the tools!) this is not any more effort at all.

Ctrl-Shift-R B A R

No, not much effort at all. Just twice as many keystrokes.

I wouldn't even mind the verbosity if it actually gave me some speed improvements, but it doesn't. There are plenty of statically typed languages where you just write x = new Foo() and the compiler will figure out the types for you.


Great, I suppose, but you didn't answer his execute() example at all. I don't care if you do it in vim, emacs, or an IDE, the problem is that in a dynamic language, you can't do it safely at any speed or with any number of keystrokes. Counting keystrokes is therefore completely beside the point.


Counting keystrokes in programming is like counting letters in a novel - the amount of time put to think of something, to discuss it, takes the vast majority of time. Keystrokes used to write something is irrelevant (especially if you type with more than 2 fingers)

And if the whole arguments boils down to Java not having a var/val keyword - yes, that would be handy; but you would then still need tools to figure out what is the type of val foo = calculateSomething();


It will give you faster compilation speed, though.


Think about it, does it really?

To parse Foo x = new Foo();, javac has to perform type inference on the right hand side to figure out its type, and then check whether that type is a subtype of the left hand side. Telling the compiler: "hey, trust me, variable x is of type Foo" doesn't make the compiler's job any easier at all.


In that case specifically, no, but in general doing type inference means running a constraint solver over the entire program, which will definitely add some overhead to the compilation time.


Yup, the best example I know of is resolving implicit scopes in Scala.


F2 on my IDE. One key, no need for Ctrl-Shift-R


One hand position still over the keys and uses common fingers, and is easy for emacs users (Ctrl + Shift + R), versus leaving the typing keys entirely to climb to a command key that's used sufficiently infrequently that you have to look at where it is.

At least that's my experience.

Oh, and more fun. If you're on a modern keyboard, you have to type the function key since apparently volume up and down and expose are more important than function keys.

Long story short: what's faster and 'less' for some, is more for others. And this is why we have options! :D


I don't understand the point. Are you claiming that search and replace functionality provides the same ease of use as an actual rename refactor ?

  Foo x = new Foo();
  int Fool = 5;
I'm sure you see the problem.

Dynamic languages are great, until the program grows. Then you hate yourself for having picked a duck/dynamic typed language (including Go, btw : programs become unmaintanable if they grow, not as bad as python and the like, but ...).


I don't understand the point. Are you claiming that search and replace functionality provides the same ease of use as an actual rename refactor ?

No, I'm saying you need extra key strokes to activate that rename refactoring functionality, which is unnecessary in an ideal situation.

To refactor the java code

    Foo x = new Foo();
you need to hit the key combo to active your IDE's refactoring thingy, then type the new name.

To refactor a less verbose statically typed language:

    x = new Foo();
You just type over the old name, no refactoring key combo necessary.

This discussion isn't about static versus dynamic. It's about useless verbosity versus less useless verbosity.


Still don't understand. Let's take the changes you need to make :

  Foo.java
    ...
    class Foo {
      ...
    }

  SomeOtherFile.java
    ...
    Foo x = new Foo();
    ...
Equivalent in Python:

  some_file_in_a_library.py
    class Foo:
      ...

  some_other_part_of_the_program.py:
    x = Foo()
    
Keystrokes to change the name "Foo", in Java :

1) Position cursor on Foo.

2) Alt-shift-R "Bar" (+ enter)

Keystrokes to change this name, in Python :

1) position cursor on Foo

2) Change to bar (5 or 6 keystrokes)

3) Open some_file_in_a_library.py (couple dozen keystrokes, most people I see do this have to switch to mouse and use that)

4) Change the classname

5) Go through all the unit tests that you should have that test the class (you need 5x more unit tests in Python compared to Java as well, to have equivalent tests), and do the same. Yes, all of them.

Java wins out, by a factor of 3, maybe even 5. Even if the class definition and the usage were in the same file, it would still win by a lot.

Refactoring simply doesn't work reliably in Python. Heroic efforts by Jetbrains notwithstanding, it just doesn't compare.

So I don't see what you're complaining about. Making changes is only faster in Python in tiny programs, where you don't have the problem of interdependencies. As soon as you have some of them, Python starts losing out, bigtime.


..plus you need to know where the class is being used!

Being able to refactor classes/methods/variables names without even care where those are used is a huge benefit IMHO


If you are prone to having the "if (cmd == 'run') run();" pattern in multiple places, no language is going to fix your copy pasta and the maintenance issues it has. Java absolutely has mechanisms to fix that and factor it out, it just bs to say otherwise.


It's a pain when you are first learning and typing every keystroke, but with a modern IDE (IntelliJ) you don't really need to worry about things like this.


In the strongly typed language Scala you get the same benefits as in the duck type languages, and even better :-) You can do:

  val usersById = HashMap[UserId, User]()
if elsewhere you have defined: `type UserId = String`. This is very readable I think :-) And changing the type of UserId is done in one place only.


better languages will either do first-class functions

Modern Java has first class functions.

https://docs.oracle.com/javase/8/docs/api/java/util/function...


That's why I like Limbo and later Go's implicit typing:

     a := Foo():
a now has whatever type Foo() returns. If you change the definition of Foo then you don't have to cascade your type change through all of your source code.


I hesitate to even begin to imagine the kinds of bugs this could lead to.


Committer to Apache HBase here:

I agree with the author on some level. All of HBase and Hadoop (except for a little bit of native stuff) is implemented in Java.

I found that to be + and a -.

Java is easy to understand and to follow, lends itself very well to large-team development, and performs well in most situations. The alleged verbosity I do not mind. I have tools, and well structured code is easy to follow.

Java (or the JVM really) does have limits, though. What I miss by far the most are simple pointers and access to the RAM outside of the Java heap. Then again I am working on a low-latency database. Yes there are DirectByteBuffers but they are annoying to use, just gimme a struct (some IBM folks are working on a proposal for that for Java). Everybody in this space who is using Java invents their own off-heap code to avoid heap allocations and the inevitable garbage collections. G1 will make it better, but not eliminate this.

I still user other tools: Python, Ruby, Bash (yes), JavaScript, C/C++, etc, and I disagree with the author's premise. It depends very much on what I attempt to do which language/ecosystem I will use for that.

Edit I: In the end I prefer to versatility of Java over the limits I face with it. Would I write a Kernel in Java: No. At least not with the current JVM.

Edit II: We should not conflate Java with the JVM.


I guess you aren't aware of

http://openjdk.java.net/projects/panama/

http://openjdk.java.net/projects/valhalla/

http://openjdk.java.net/projects/sumatra/

Some of the features will come in Java 9, others in Java 10.


You have to appreciate bombastic statements like this for forcing you to confront your assumptions. "Everything in Java? Even a kernel? That's absurd." you think, and then wonder what makes it absurd, and realize that it could perhaps be done with some modifications, and remember Singularity, etc.

But on the other hand, this is well trod ground. Everything WAS going to be Java. Remember picoJava, the bytecode-native processor? Remember Cocoa Java, for OS X desktop apps? Remember HotJava, the pure Java web browser? These things were tried, and they failed. Performance issues, especially around startup and memory usage. The weightiness of the JVM, what Jobs called a "big ball and chain." The weird foreignness of Swing apps. The generalized misery of applets. Etc.

So honest question: what's different this time?


Great perspective! I don't think 're-implement the world in java' was the point of the blog post. I do follow you're line of thought however. Vala is a Java like language (in the same way C# has a subset that is Java like) that is AOT compiled by translating to C.

Interestingly, it has a few departures that make it very un Java like. For example, Vala uses reference counting for memory management and provides a 'weak' keyword, passing reference cycle management off to the programmer. And voila, no gc (edit: or rather no centuries level of effort garbage collector implementation, with associated performance indeterminism). Another departure is no dynamic class loading.

Point: I use Vala as a proof by example there's a language out there that's statically typed, highly productive, GC'd, and AOT friendly, for which some formulation of "X Everywhere" is not far fetched.


> So honest question: what's different this time?

We've rediscovered ahead-of-time compilation.


You forgot JavaOS.


I am more convinced by the part "write everything in one language", and less convinced that Java is a great choice for that language.

On the other hand, if you're going to write everything in one language, you do need a language that is capable of doing nearly everything, and doing it well. And I see how Java is a reasonable choice.

But yeah, I think "pick the right language for the job" (and the corresponding "when all you have is a hammer...") under-estimates the extent that the right language for the job is the one you know best, because you'll be able be most effective in it.


The biggest thing for me is that the tooling around Java makes maintaining large projects extremely easy. Being able to refactor hundreds of files in a few keystrokes without worry lets me sleep well at night. It's certainly a lot faster to get up and running with a dynamic language, but the initial build out is a small percentage of the overall time you are going to spend with a codebase.

I've also built just about everything in Java from HFT algos, to an exchange, to a web server, to thick clients so I have an idea in my mind about how to solve any new problem that comes up.


I think this is the key point in the debate - weighing initial development time against ongoing development and maintenance. It's something that's hard to grasp until you've been around for a while working on real-world large-scale projects. And it's a hard thing to get the sense of when you're in school, writing throwaway code that doesn't last past the end of the semester.

When you understand this, then you can make an honest assessment - is it really important to get the first build out that much quicker? Sometimes it is. But I think it's overemphasized. The first one to market doesn't always win. And the shift from new development to maintenance happens quicker than you might think.


First to market has never ever been about using a dynamically typed language. Getting the ideas from talk to concepts, testing, bugfixing and marketing takes vastly more time than actually developing the code. So while Python might enable me to show my prototype on Monday, while that Java version wouldn't be seen until Friday, there still is quite a lot of time before you can say it's properly released.

Where these "fast" to develop languages shines are throwaway prototypes. For some people their ideas flow out much faster with dynamically typed language. But it is all too well known that even though the manager said you could throw it away, they change their mind because "it's basically finished, right?".

That said, you are spot on. Initial development is likely not where you want to focus at all, for any kind of project that needs to be maintained for more than a few months.


If you're actually using good tools (Something like IntelliJ or Eclipse, and something like Maven or Gradle), and you use sane variable and function names (business oriented instead of tech oriented) verbosity is one of the worst arguments against Java.

The verbosity, static typing, etc, of Java contributes information to the "next guy" about developer intent and is incredibly valuable.


"You just don't get Rails [Python / ...], ri-ight??"

;)


I completely buy the idea "write everything in one language", even if I do it with a different language for completely different reasons.

In general I think "use the best tool/language for the job" and anyway any tool/language will have pros and cons, nothing is perfect.

My context is I was a big ECMAScript fan, then I moved to use something called ActionScript 3.0 and there I just found the "right balance" between verbosity, correctness, speed, etc.

That's the work part, I use AS3 and AIR to build mobile app for iOS/Android.

Then there is the hobby part, in 2006 Adobe open sourced their ActionScript Virtual Machine (AVM2), I started to work on it (OSS project RedTamarin) in 2008 because I had this silly idea "it would be fun to run AS3 on the command line".

So, few months ago, with a not too bad release of this RedTamarin project, in the spirit of "use your own dog food" and trying to push the limit of what can be done with this open source project, I kind of decided to use only AS3 for all development, either work or home.

I don't do that because I think it is better or faster, but mainly to see how much I can reuse in code and logic, and if ultimately it make things easier for me (as any dev I'm lazy).

The result is quite interesting, so far I can run AS3 in shell scripts, as server side CGI, as command line tool, and tons of different use case I would have not necessarily explored if I didn't forced myself to use the same language for everything.

My point here is the same way you can learn a different programming language every few months/years to learn new stuff, there is also a value of forcing yourself to use only one programming language for everything.

In my case it forced me to explore some context deeper instead of taking them for granted, sure some ppl could say you waste your time because you're reinventing the wheel, but I would argue you learn a lot more when you try to know all the little details that make a wheel works :).


interesting,I need to check it out,you should add a link to the project. I definetly like AS3,it's a good compromise between javascript and java.


here you go http://www.redtamarin.com/

and the g+ community https://plus.google.com/communities/111596731002136630496

and yeah it's kind of why I'm doing that, AS3 is for me a good balance

as a side note, the way redtamarin is implemented you have access to almost all POSIX C functions from AS3 which can also be seen as a "Friendly Dialect of C"


First of all, I want to say that if you like Java, and know it well, and believe it to be the right tool for your particular application, that you should absolutely use it.

> That Java is the right language for all jobs. (Emphasis his.)

> The advantages of C and C++ [...] don’t apply to my work.

So, choose the right tool for the right job.

As for the examples given:

> At one company I wrote a simulator that allowed me to run my Java services without a fully-functional site. (The unit under test is Java, so it makes sense to write the simulator in Java, rather than Javascript)

> My partner Dan Collens suggested Java [for a log parser], since it’s right there and we know it and it’s fast. (The log parser is used so often that the amortized opportunity cost of developing in Java is more than paid off by faster processing, therefore Java is the right tool for the job)

> And finally, I went to write a simple program that put up a web interface. (This is something the author has done many times before and knows how to do well in Java, and his primary goal is getting it running ASAP, therefore Java is the right tool for the job)

I still think you should choose the right tool for the right job. It just happens that the author's work is constrained in such a way that Java turns out to be the right tool in most, if not all cases.

Honestly, though, I would rather choose the same tool for a job each time by deciding that it's, by merit and virtue, the best tool for the job, rather than relying upon the author's silly heuristic.


This is the correct response to this article. He makes a big deal out of saying he doesn't need to "choose the right tool" anymore. But then later, he feels compelled to qualify that Java is the right tool for him, which sort of invalidates his former point.

In other words, I viewed this article as a large waste of time. Nothing has been added to what is already conventional wisdom.


It's not so much that Java is great at everything. It's more like it doesn't suck at anything. Every other language has, somewhere, a deal-breaker for some particular use. I've not found one for Java. And Java's biggest downside, frankly, is that it hasn't attracted fresh young talent in a while, so it doesn't have really hot frameworks and libraries.


While I do think Java is great I think that's an exaggeration, I'm sure there are quite a few deal-breakers for particular uses. Personally I've opted not to use Java before because it cannot compile to a self contained native binary.


Java projects can be compiled to a self contained native binary using http://www.excelsiorjet.com/ (though this is a proprietary tool, with a gratis license option for non-commercial projects).

Curious: why is this a requirement for you?


You will be excited to learn about gcj, then. The Gnu Java compiler compiles to native code, but it's currently not maintained, so newer Java features are out of reach.


You will be excited to learn about gcj, then. The Gnu Java compiler compiles to native code, but it's currently not maintained, so newer Java features are out of reach.

gcj has been abandoned. It was last updated over 5 years ago. It's not clear to me why you would even mention it.

I'm a software developer that primarily uses and likes Java, and the lack of a good and free ahead-of-time compiler for Java that produces native binaries is what I miss most in the Java ecosystem.


There's Avian. It can produce standalone, compact ELF files that have no dependencies. It's not an AOT compiler though. The problem with AOT in the Java ecosystem is quite a lot of modern frameworks and the like have ended up relying on the ability to synthesise code at runtime. Android has put a check on that kind of behaviour but it's still there.

There's also Excelsior, which is an AOT JVM, but it's for Windows only.

I agree that a really good AOT JVM would be very nice. It doesn't necessarily imply better performance however. I remember when GCJ compiled Eclipse for the first time, lots of people were surprised that it didn't magically fix every performance problems. GCJ engineers view was "HotSpot is an excellent compiler and it will take a lot of effort to beat it". When Sun Java became open source therefore, a lot of the incentive to develop GCJ disappeared. It was always primarily a licensing project not a performance project.


There's also Excelsior, which is an AOT JVM, but it's for Windows only.

Unfortunately, it's also extremely expensive. That's not to say it isn't worth every penny in some situations, but I've gotten kind of spoiled by free development tools for personal projects. I'm glad the days of spending hundreds of dollars for things like C compilers are long behind me.

I agree that a really good AOT JVM would be very nice. It doesn't necessarily imply better performance however.

For some application domains, I would be happy to trade speed -- and even features -- for the ability to create a native binary with no dependencies.

This is one area where I find the Go programming language interesting. I prefer Java, but the lack of a good and free ahead-of-time compiler for Java that creates native binaries with no additional dependencies is a killer feature for some situations.


Then you might be happy to know that AOT is planned for the reference implementation for Java 9, eventually Java 10.

Also that Oracle Labs have SubstrateVM, which is an AOT compiler based on Graal.

Then there is also JikesRVM and RoboVM.


Looks like it is Windows, Linux and Mac. No 32bit on Mac, though.

http://www.excelsiorjet.com/


IMO, being tethered to the JVM is both its greatest strength and its greatest weakness. The JVM really is a masterful piece of engineering, but it is optimized so heavily for the server that any use case that deviates requires huge hacks to get what you want. For example, running a JIT on Android was so sluggish that Android had to design an entirely new runtime(ART).


The JVM runs very well on the desktop as well as the server. I have to point out: Android runs Dalvik, not the JVM. But here's the point: Java isn't tethered to the JVM. Use the JVM for server, desktop, Use ART or Dalvik for Android. Use Jikes, Excelsior Jet, RoboVM or other VMs, compilers for other targets. The limitation you raise doesn't really exist.


Well, Dalvik is a JIT and ART can also do JITC and is designed for newer devices. So not sure that's a great example. The main reason Android doesn't use the HotSpot JVM is memory usage and licensing, I guess. The JVM class/jar format is very inefficient in many ways. On the other hand Dalvik is a very weak JITC. ART is stronger because it has more time to work and is, frankly, better engineered. Dalvik had a lot of problems even quite late in its lifecycle with things like lock inversions and strange method count limits, etc.


Java's start up time makes it pretty crappy for command line utilities.


Java's start-up time is on the order of tens of milliseconds:

http://nicholaskariniemi.github.io/2014/02/11/jvm-slow-start...

The 'Hello' program there takes a little over 100 ms for me. I guess my computer is even less of a powerhouse than the author's.

FWIW, the Python equivalent takes about 30 ms on my machine. So, you pay maybe 70 ms to use Java. I don't think many users will notice an extra 70 ms on their command line.

Java's notoriously slow startup is really about the slow startup of software written in Java. Application servers are probably the worse offenders - how can it take a minute and a half to start a fancy webserver? What's it doing in there? They've got a lot better, though; the current generation of app servers start in one or two seconds. Not that anyone cool uses app servers any more anyway. Big bloated GUI apps also deserve some shame here (although i will forgive Eclipse, because i like my IDEs with some meat on them). Language platforms like Clojure and Groovy also manage to take their time, but then they're doing some pretty amazing stuff, i suppose.


When did you last try it? Startup time was optimised heavily some time ago and nowadays I don't notice any real difference unless I wrote some toy app and used "time". The JVM starts fast enough that you can write command line utilities just fine.


It is certainly substantially better than it used to be, but it is still pretty far away from an AOT compiled native executable. And forget it entirely if you are running Clojure or Groovy code.


The class of tasks for which Java's startup time is an issue is very very small. I wouldn't use it for a device driver because of resource issues but there aren't many command line commands where 0.08s is an issue.


LuaJ is an order of magnitude slower to startup than Lua, IIRC. Could be LuaJ's fault, not Java's, of course.


Startup time on my Win7 box: 0.08 sec.


This is exactly how I feel about Scala now.

I really wanted to like Java because of the ecosystem and the JVM, but there ARE a few warts that you will face everywhere - verbosity is one, all the Spring stuff using annotations to wire up dependency injection and AOP and whatnot is another.

Scala has the whole JVM ecosystem, static typing and forget about DI/AOP/OOP patterns. Feels like best of both worlds for me.


I find Java much more pleasant without Spring; I much prefer Jetty+Jersey+Guava+Guice. It sounds like that's pretty similar to how you're using Scala.


I've never been a big fan of Spring so I was pleasantly surprised to discover Dropwizard which includes the tools you've mentioned, a few others, some best practices, and a little glue.


80% of the problems with java as it's usually written are bad policy rather than fundamental language problems. But there are real cases where language limitations mean you have to either use an unpleasant framework or write unpleasant code.

Jersey's annotations are pretty nice, but they're still annotations, not really part of your code. You can be bitten by silly errors like an implementation's annotations not quite matching those on its interface, and when (as is often the case) the annotations get repetitive for a group of similar services, there's no way to factor the common part out. In Spray I can write route definitions that are just as neat as the Jersey ones, but it's plain old code which is an enormously powerful concept; a route can be refactored just like any other code.

Guice is similar, e.g. declarative transaction support; better than managing database transactions by hand, but annotation-based proxying is a bit "magic" and confusing to debug. In Scala I can use a monad for transactional operations; the code (using for/yield) is almost as effortless as annotations, but operations which use the database show that in their type and the type system enforces that my transaction boundaries are in the right place. Even more importantly, refactoring in the normal way is safe.

(Also e.g. the lifecycle features in Spring are really valuable (and virtually impossible to do without annotations in Java, at least pre-8). In Scala there's scala-arm, which achieves the same thing in a monadic way, with the same advantages as doing that for database transactions. And since the same abstractions are used in both cases, you can write types and helpers that work with both "database operation" and "requires lifecycle-managed resource")


So here's the thing about annotation and Jersey, I believe you can annotate the seralization of return type once at the top of your resource class, the rest, like http verb, needs to be repeated unless you take the convention one more level up a'la Rails. But that's Rails, a web framework that people said does not fit for microservice. Sinatra is.

But if you take a look at how Sinatra (or Rails) serialize the returned object, you notice the duplicated code. Especially if you want to return both JSON or XML based on the request header. To add to this, both frameworks do this serialization as part of the code logic that you have to write, instead of slapping annotation once...

Let's take this further: exception mapping to http response code. In JAX RS, you can map application exception to certain WebApplicationException with specific http response code, I believe you have to handle them manually in Sinatra. You would have to catch the exception and convert it to the intended one per method on your controller.


> But if you take a look at how Sinatra (or Rails) serialize the returned object, you notice the duplicated code. Especially if you want to return both JSON or XML based on the request header. To add to this, both frameworks do this serialization as part of the code logic that you have to write, instead of slapping annotation once...

I can't speak for Sinatra, but in Spray I'd just write a directive for this - maybe it exists already, but if not, it's a couple of lines - and then I can use it just like any of the built-in directives. And this is a perfect example of why "just code" is so powerful. Jersey is a very well-designed framework and I'm sure you can find examples where the built-in Jersey thing is better than the built-in Spray thing. But no framework is perfect, at some point you find yourself having to extend these things - and in Jersey's case, IIRC once you want to write your own annotation you need a magic .service file containing a class name to use to interpret that annotation. And then the only way to pass dependencies to that processor is by static global variables. Good luck refactoring that, and don't expect to be able to use hot code replace when debugging it. And good luck remembering how the mechanism works in six months' time. "Plain old code" has a lot to recommend it here.

> Let's take this further: exception mapping to http response code. In JAX RS, you can map application exception to certain WebApplicationException with specific http response code, I believe you have to handle them manually in Sinatra.

Again, trivial in Spray - I do my error-handling with Either and then I have a meta-marshaller that knows what to do with the error case. Better still, error handling isn't a special case - I do exactly the same thing if I have async code in my methods (can JAX-RS handle Futures? Can it handle a different kind of Future from a non-standard third-party library?). I can do exactly the same thing with a database-transaction monad, and then I can have session-in-view but in a principled, safe, zero-magic way. I can do the same thing to e.g. show debug traces if a special header is present - like Jersey's dynamic choice of serialization format that you were so impressed by, but it doesn't have to be built into the framework, it's just code that I can write myself.


I've been using Jersey since 2010 and I have never need to write my own annotation. Maybe I'm lucky enough that Jersey fills my need perfectly and maybe you're right that once I needed to write my own annotation, I may run into a bit of trouble (though some people do write annotation only to be consumed by reflection, hence bypassing the service file) but I guess... that's like.. what... 1-5% extreme use-cases? Like... LISP macros that makes programmer reached nirvana or something?

But in my case, Jersey fills my need without me writing low-level REST code (dealing with exception to HTTP status code, marshalling objects to different formats) embedded in my controller/business logic.

> I can do exactly the same thing with a database-transaction monad, and then I can have session-in-view but in a principled, safe, zero-magic way.

You sound like programming in another level higher than mine. I applaud that. I'll revisit Spray/Scala _when_ I found a definitive use-case for this. For now, Java seems to fit the bill for pretty much 99% my use-cases and fit my taste as well (less low-level code stuff because it is built-in the framework that is well-architected/well-designed so that I can focus on business logic code).


> You sound like programming in another level higher than mine. I applaud that. I'll revisit Spray/Scala _when_ I found a definitive use-case for this. For now, Java seems to fit the bill for pretty much 99% my use-cases and fit my taste as well (less low-level code stuff because it is built-in the framework that is well-architected/well-designed so that I can focus on business logic code).

Sometimes you don't need it, but there are blub-paradox cases as well; I tried to sum up a few of the things I retrospectively recognize I was missing in Java in http://m50d.github.io/2014/05/16/signs-your-java-program.htm...

A lot of it is just being able to track things in the type system that you wanted to track in Java anyway, but it seemed too hard. I mean, I've worked in Java codebases where it would have been very nice to see which methods accessed the database as part of their type. I've even seen one that used a kind of Hungarian notation to express this - in fact if I can point to a single place that set me on the road to Scala, it's http://www.joelonsoftware.com/articles/Wrong.html . Because I read that and then thought: hang on a minute, why not just make whether a String is encoded part of its type-type, the type that's enforced by the compiler?


Hey, Thanks for your article. I've read that and I can see how/where Scala is useful!

I'm definitely going to learn Scala once my adventure in JavaScript world wrapped up.


Ditto. Spring feels like "the worst of Java", while the exact combo you list above is some of the best and the set I reach for. Jetty is showing its age a bit right now, but it's so much nicer than dealing with Tomcat.


If only you knew the power of monads.


I think the difference is that stuff is less hastily cobbled together. People use additional libraries because they add value, not because they paper over ugliness and holes of existing libraries.

Scala feels "designed", while Java feels "evolved".


Yet I have 99% probabilities that my next JVM gig will be Java than Scala, as very few customers ask for Scala skills on their Request For Proposals.


How is this related to the topic?


That even though Scala is better designed than Java, without Java's cruft earned through evolution, most companies will keep on searching for Java developer skills.


We were discussing quality, not popularity.


What he said, but C#.

C#'s one of the most versatile languages which can target most of the popular platforms, e.g: iOS/Android (Xamarin), WindowsPhone, Windows, Linux, OSX, Silverlight, PS4, XBox (announced), Unity3D and NaCL.

C#/.NET's biggest weakness of sub-optimal cross-platform support should also be resolved in the near future now that .NET's compiler, core runtime and class libraries are OSS and with Microsoft announcing support and plans to release official distributions for Linux and OSX - so .NET will finally have multi-platform support of a single code-base resolving earlier issues or running .NET on OSX/Linux due to different impls.


My version would be "what he said, but choose any well-supported statically typed language, particularly one with decent type inference, since that gets you a lot of the convenience of dynamic typing without all of the very many runtime-error downsides".


C# has replaced scripting languages for me. It might be faster to write a python program to do something simple, but the amount of time saved on such small things is minimal.

As soon as a project gets large, it outgrows the scripting language anyway.


He learned something that most good Perl programmers learn fairly quickly:

The interpreter/compiler is just the VM; the real language is the combination of all libraries available for it.


There's no shortage of good libraries for Python. He just chose to not learn about them.


And all the fast ones aren't implemented in Python....


So what? For most problems there are fast, well-designed libraries available with idiomatic python interfaces; why would you care about the implementation details?


Note, this is coming from the same guy who programs in x, which was also implemented in C(++). Like the JVM, CLR ad nauseum. :)


Do you know that there are JVM and CLR meta-circular implementations, right?

And that the reference implementations get less C++ code with each release.


Because the whole point of the OP is being able to use the same language for the whole stack.


You are. Sure you call libraries that aren't written in Python, but that seems just as irrelevant as the fact that the JVM is written in C.


Which JVM?! There isn't such thing as "The JVM", there is the JVM standard, reference implementations and certified JVMs.

Oracle has JVMs implemented in a mix of C, C++ and Java, up to pure Java (Maxime), just like many other JVM vendors and research institutes also do.

Even Oracle is playing with the idea of using the Maxime JVM, now Graal, to eventually replace Hotspot.

The Java 7 and Java 8 reference implementation saw a lot of C++ code being replaced by Java code, thanks to new JIT intrinsics.

The idea that C is the only way to implement VMs needs to die.


> Which JVM?!

The Oracle one, aka the one production Java code is usually deployed on. I am aware of several of those research projects but they're, well, research projects.

Even if the JVM were fully implemented in Java, the OS most likely wouldn't be. Even if it were, the CPU microcode almost certainly wouldn't be. At some point your Java will be running on something not-Java, even if that thing is "logic gates". But it doesn't matter - just as the implementation language of the libraries you use in Python doesn't matter.


There are lots of production JVMs, they aren't research projects.

- Oracle JVM

- Oracle J/Rockit

- Websphere JVM

- OS/400 JVM

- HP-UX JVM

- Aix JVM

- Aonix Perc JVM

- ...

> But it doesn't matter - just as the implementation language of the libraries you use in Python doesn't matter.

If I can achieve the same execution speed with pure Python, then yes it doesn't matter. However, that isn't the case.


Some good, some aren't, some used to not work with Python 3, some still don't work with Python 3, some reinvent the wheel died due to not being popular (sql object, pylon, turbogears), some looked relic and not worth to learn ( plone, zope).

Like the article said, it's fun and quick to hack in Python but just ain't everybody taste... especially seeing the age and the quality of some of those libraries.


Java is perfect also for client side. We have a client app (a complex VoIP softphone) with different codebase for all platforms (C++ for windows, java for android, ObjectC for iOS). Right now we are in the way to reduce all this in one single codebase written in Java and the user interface in html/css/javascript, so the user interface is always running in a webview.

-Java for windows desktop (there are pretty installers which automatically download and install the JRE if not present)

-Java for MAC and Linux desktop (same as for windows desktop. the same installer tools can generate also Linux and MAC packages)

-Java for Android (with a very minor conversion for which we already wrote a converter app)

-Java for Web (currently using a java Applet which works perfectly. We plan to use GWT to transform to JavaScript in the future)

-Java for iOS (will see)

This way we plan to cover 99% of all devices with java only (with some minor transformation for some platforms). What is your opinion on this? I am in the right direction?


This is horrible, but not because of the Java part — it's the webview that puts your desire for a single UI technology stack ahead of user's desire for a decent UX.


On mobile devices the issue is Oracle dropping the ball and leaving to third parties (RoboVM, CodenameOne,...) the work of providing JVM implementations.

This on iOS, still no story on Windows Phone, which actually happens to be over iOS on some European countries.


On Android you already have java :)

The big question is iOS for which there is no mature tool yet. hopefully j2objc will be enough.

Windows phone ...i think that we will wait to see a higher market share before to dig into it


> On Android you already have java :)

Java 6! Java 7 is only fully available for 4.4 upwards, and only the language, with cherry updates for the library.

Meanwhile one needs to resort to Xtend and Scala, if I want to enjoy a bit of Java 8 on Android, across versions. Or use hacks like retrolambda.

On Windows Phone vs iOS, it depends on your target market. On countries like mine (Portugal) you will surely see more WP on the street.

Of course, US and others are a different matter.


I am using java 1.5 features only :) Actually i never understood this spike about language features. For me the focus is always on the problem what i am trying to solve (VoIP in this case) and never the language. Actually any language would do for me in which i can apply some encapsulation for better code management (think of java classes). The rest doesn't matter :) I was started with C and then C++, but for me C++ is still C with classes :)


>i never understood this spike about language features

You should really read about the Blub Paradox. Imagine writing all your coded in assembly. It would suck because assembly is an inferior language To those you mention. Now imagine working in a language that is higher level than what you've (yet) been exposed To.


We are working hard on making RoboVM as mature as possible. There's already plenty of applications on the App Store using RoboVM. Happy to talk if you need more info for decision making. Ping us at hello@robovm.com.


> Java is perfect also for client side.

Unless you want it to look totally native client-side. The extra effort required to make a Java app look platform native is something that (near as I can tell) no one has ever attempted.


Not true - here's my attempt:

Windows: http://www.solaraccounts.co.uk/images/screenshots/invoices.j...

OS X: http://www.solaraccounts.co.uk/images/screenshots/invoices_m...

The trick is to use the Java SWT library rather than Swing. (In my case I also added a few platform-specific hacks such as having a big toolbar at the top of the main window in OS X but not Windows).


IntelliJ has historically looked pretty native on MacOS X. At least until Yosemite pointlessly reskinned Aqua to look more ugly. Now I find myself quite happy that IntelliJ is not a native Mac app because I preferred the old look anyway :)

You can make the apps look native, if you really care. But in an era when web apps are the shizzle why would you even care? No web app even tries to look native. They just do their own thing and nobody cares.


>IntelliJ has historically looked pretty native on MacOS X.

Because they require the use of Apple's hand-rolled Java 1.6

https://youtrack.jetbrains.com/issue/IDEA-117324#comment=27-...


For the UI we are using html in webview. So the app "engine" is all in java, only the UI is html (so this is also cross platform)


Isn't Java FX tackling that?


For development speed and code maintenance, this is ideal. Your team only needs to master one language and its set of tools and libraries.

You are pinioned by this choice on some practical levels. Mainly, some users and use cases demand the speed and lightweight user-experience of native apps. The native-vs-[java] experience is typically quite noticeable on all the platforms you've mentioned -- desktop, web, and mobile.


Right now I am working on the windows desktop app. I can tell you, that you don't notice any difference at all in speed (I also wrote a simple "container" app in native c++, so it is also loading instantly ..there is a ~2 sec delay to load the JVM, but meantime the user already sees the UI)


I've mostly embraced the JVM (as opposing to hating it), but I find myself reaching for Clojure a lot more than Java (although I have an Android app that I'm tinkering with). I find that an IDE helps (I use NetBeans for pure Java), but whereas I can hack just about anything in Clojure, Python or Go without much hassle, Java slows me down for some reason - I suspect it's the humungous class hierarchies and the time required to find whatever I need to accomplish simple tasks.


Once you get used to working in Java (and have a relatively stable toolchain you can depend on), it's realistic to develop applications in Java almost as quickly as Clojure, though complex aggregations that Clojure makes one-liners will often be vastly slower to develop.

IntelliJ makes a lot of things easier as well.

When it comes to Java, you just need to really get familiar with your tools before you can be as productive, but once you are you can move quickly. Using Java 8 doesn't hurt either, streams are pretty decent.


In Java 8, those one liner aggregations are now possible and part of the standard library.


I love Java 8 streams, but they're still awkward compared to Clojure.


This whole "expressive vs. performance" is a false dichotomy. Languages like Scala and Haskell are performant like Java and expressive like Python. Not to mention the work being done on JIT compilers by V8/HHVM/PyPy that are helping to close the performance gap for dynamic languages.


I am maintaining at the moment some Scala code I did not write. Sometimes you wish for less expresiveness.


A couple years ago there were several people complaining that is was a write-only language.

(Of course, others said that it was a matter of educating your devs about when not to use some features...)

When I first tried it, the slow compilation killed it for me (not a problem for Clojure because a connected Emacs makes for a killer setup...)


Clojure too. Very fast. Very readable. Very expressive.


I would just add one more thing - I doubt there is another language where you write native apps for Android, iOS and Web sharing 70% of the code: http://arstechnica.com/information-technology/2014/11/how-go...


From the JVM side, we have: Scala, Clojure, Groovy, Kotlin, etc thanks to RoboVM.

From the CLR side, we have C# and F# thanks to Xamarin.

Even the worst language among the six I have listed is still far better than the verbosity of Java.


AS3 - with AIR for publishing on mobile - with SWF to publish on the web (for desktop browsers)

and I would argue with the added bonus that you can share the UI without an horrible result


C++ (Using something like emscripten for the web)

Although, i'd pick java over C++ unless i'm doing some very performance critical


While true, it is a pain on Android, given how the Android team treats the C and C++ developers.

The official set of APIs is quite limited and JNI is required for any app that isn't a game.

Even C++ libraries that are wrapped in Java classes, like SKIA, are only accessible via JNI.


C#, with Xamarin.


You can add Windows and OS X to that list.

(Although the Google Inbox team didn't produce a Windows or OS X native client, there's no doubt that such a client could have run the java code shared between Android, iOS and Web)



JS?


Java doesn't seem too popular here but used right it can work pretty well, imo.

For instance, I use Java for the backend of a name generator web app. It's astonishingly fast and displays results almost instantaneously despite running a good amount of backend calculations.

This speed became an issue because you'd push the go button and the names would update - but it seemed like nothing happened. So I ended up adding an artificial delay twice (the first time it wasn't enough of a delay).

On the other hand, its structure and methods can at times be frustratingly complex.


In real-world benchmarks in a real app I have tried to make Clojure slower than Java. I can't. In rare cases Java will beat it in insignificant ways in insignificant amounts, but I found that Clojure sometimes beats it in significant ways because of the runtime's tendency toward laziness. Furthermore, Clojure is a very dynamic language that can leverage every library Java has plus all its own.

As a result I will not program in Java willingly. There's just no reason to do it. Not with at least one language that's far better in real, quantifiable ways. There are other languages that run on the JVM that could tell a similar story. Unfortunately those are not Jython or JRuby.


Its hard to explain, but I feel like Java would be a better choice for doing something like audio decoding, while Clojure is orders of magnitude more productive to prototype a webapp.


You have to admit that for coders, the joy of writing helps a lot for job satisfaction. I write both Java and Python (for very different applications) and I just always feel like Java makes it hard to write anything elegant almost on purpose. The proliferation of huge frameworks and FactoryFactories clearly doesn't help.

I think you can underestimate the value in actually enjoying writing - I'm just more motivated every day I can write elegant python code. Conversely every day I spend fighting Java for an elegant solution and winding up inevitably with something a bit half-arsed because of some limitation in the language I just feel grumpy.


I'm of two minds on this. Certainly it's important people find enjoyment in the day-to-day reality of their job. Unhappy people don't write good code in any language. But I honestly do thing people can have too much fun writing code. We've all fallen in love with something we've written even though it might not have been the simplest or most understandable or idiomatically sound.

Writing Python is fun. But that joy can cloud your judgement, and if we are to consider ourselves professional, we have to look beyond just that and make decisions based on our employers best interest. Sometimes that might be Python, but in my experience, quite often that's boring old Java.


The problem is that one guys "Joy Of Writing" rapidly becomes the next guy's "Torture Of Reading", and with enough of a time-interval those two can be the same person.


I feel Python is good in this regard compared to other interpreted languages. There's a lot of emphasis on "Pythonic" style which you tend to pick up as you learn, so people are discouraged from excess magic (Explicit is better than implicit) and the syntax at the very least lends itself to sane formatting (especially with PEP8). Personally I've rarely had any true WTF moments reading either my own code or code from (reputable) OSS projects.


With dependency injection you dont need factories.IoC containers will make write you way less code.And they scale better.


You might not need factories, but they get foisted on you anyway. But the proliferation of "programming patterns" in java I think is symptomatic of a basic user-unfriendliness in the language.

Off the top of my head I can think of three Patterns just for creating objects (Factories, DI, Builders) - the fact that these are even required, that object creation isn't self evident, suggests there's something wrong in the language design


Having literally deciding to learn java last week for no particular purpose other than having enough understanding to be able to comprehend our software (which is written primarily in java) and prevent brain deterioration, I'm encouraged by the fact that the comments in this thread (so far) don't appear to be very negative (like when reading about php).

While I did buy a book, I wonder if anyone has any suggestions on a good java beginner's book assuming someone has "prosumer" programming knowledge (shell programming, some perl, some php, sysadmin skills and so on). Suggestions?


Welcome to the Java world! Like some of the comments so far I think the Java world is actually a pretty cool place to be right now, the language and approaches are becoming a lot less verbose. I blogged about some of the best Java books, hope it'll help you out! http://scalabilitysolved.com/dont-hold-back-your-java/


Warning: These are not beginner books.

"Learning Java" http://chimera.labs.oreilly.com/books/1234000001805/index.ht... seems to be a decent review of the language and ecosystem, although it doesn't cover many of the new technologies in common usage (many of which are mentioned in this thread).


Thanks for that.

Question though. The first book you listed (which got excellent amazon reviews as well) was published in 2008. Typically I've been biased into thinking that a book had to be somewhat recent. Obviously this isn't the case here though. (Do you agree with that in some situations btw?). I would have never purchased this book if you hadn't pointed it out so thanks it's in my cart.


Effective Java is a solid choice, and a lot of the advice is still relevant six years later :) Also, JCIP is a go-to if you want to get more than a passing handle on concurrency in Java.


Agreed, the java books I listed still provide more value to my core Java than more recent books. I do the majority of my Java work now in the Play framework, when I use a new framework or library blogs and stackoverflow are my go to resources, for a deeper understanding of the library then those books are the way forward.


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

1.7 introduced a simplified version:

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


And Guava has Map<String,User> userIdMap = Maps.newHashMap() which uses Java's type inference rules, and works in 1.6 (I think even in 1.5)


I think that the argument about verbosity is a subtle red herring. It's not that you just have to write slightly longer words to do the same thing. It's that you can't do the same thing at all because the underlying constructs of the language are lacking in key powers of abstraction that make it easy to simplify the problem you are trying to solve. You end up inventing whole class hierarchies and patterns to emulate things that are either just built into other languages or are easy to achieve because they offer more powerful language features (like reified generics, etc.). Java 8 helps a lot, but there are still fundamental weaknesses.

Having said that, I'm still a fan of Java. There's no other language that I can sit down and reliably navigate through someone else's code in as easily - and that comes partly because it's powers of abstraction are so limited.


I've been writing Python and Java(Android) side by side for a few months. I feel that for all the advantages of initial speed that python offers it takes a lot away. Especially in large projects. I spend a significant amount of my python time trying to understand Types, and if those areas are not covered by tests then I'm Fked, I'll have to spend hours trying simulate the exact conditions of how an error occurred.

Don't get me wrong, I love python, but writing python requires a lot of restraint and experience. Novice programmers who build a python code base just screw things up, especially those who don't yet understand the value of readability and maintainability.

I'd much prefer novice code on Java than on Python.


The headline does not match his conclusion at all, in my opinion. What he's trying to say is that "dynamic scripting languages are slower and more error-prone than compiled, statically typed languages". And to determine whether or not a scripting language is ever a good idea from 3 or 4 examples does not seem like a good idea. E.g. Lua seems to be a pretty good fit for the WoW UI scripting stuff and EA used Python (apparently successfully) for their Sims 4 scripting (sorry for it both being examples of games, those were just the first that came to my mind :D)


That's where Go comes in very well in the interviews assuming interviewer also knows or can understand Go. It has short and precise syntax and the code usually doesn't need explanation.


It's also not very useful.


You know, one of the things I notice about Java adherents: they think programming is hard. There's this weird conservativeness to their culture. The only times I've worked on Java teams, I felt like the biggest hurdle was convincing people that things could actually be done. Its like they're convinced that every programmer sucks.

I don't even hate java the language. It's far too mediocre to even bother to hate. I just dislike java the community. It's so depressing.


> I’m even taking this to an extreme and using Java shell scripts.

Having a strong Java background, it is a pleasure to write Groovy for shell scripts.

I like the blog post. Whenever I looked into other languages/platforms, I found the "tradeoffs" of Java (as pointed out by the other languages/platforms) to be less important for me. Java/the JVM may be evolving slowly. But it evolves and does it in a reasonable way (JCP, frameworks).


Why not just use Groovy for everything instead of java ?


Speaking of - how is Groovy doing these days? I looked at the Groovy webpage and I saw ads splattered here and there - never a good sign, I also see that the mailing lists are pretty quiet. Is Groovy dying?


Whether Groovy is dying depends on how other languages do (like Javascript or JRuby).

Groovy has found its niches and will not die soon. For instance, Gradle is built around it or Jetbrains is using it building IDEs like IntelliJ.

The ads are probably helping to finance some of the codehaus infrastructure.


A new niche might be: Groovy on Android

http://www.infoq.com/news/2014/06/groovy-android


They're moving to a new site: http://beta.groovy-lang.org/


The site at groovy.codehaus.org doesn't mention anything about the new site (actually www.groovy-lang.org). Until it does the new site is unofficial and just one of the 5 despots at Codehaus trying to grab control of the product away from the other 4 despots there. That despot has tried other tricks like soliciting for subscribers to his weekly "news mailout" which is mainly links to tweets mentioning Groovy.


Mmm. I got this from Guillaume Laforge's blog: http://glaforge.appspot.com/article/a-new-groovy-website-in-...

He's one of the core groovy developers - unless he's one of those despots you're talking about?


If an old site for anything (here, groovy.codehaus.org) doesn't mention it's moving to a new site (here, www.groovy-lang.org) then I question what's going on. As for your link, it's a link to a personal blog and not an article on the Codehaus Groovy site so it's just as unofficial as the supposed new site for Groovy.


I'd say not too good.

Of course there are those two projects everyone mentions, Grails and Gradle, but I would say it's more correct to describe them as the only two niches where Groovy is actually used a bit, it's not like Gradle and Grails are just "flagship products" of a greater ecosystem.

For both, there are already better replacemens available, so I don't think they will grow much in the future.


It's a stretch to say that Gradle actually uses Groovy. Groovy 1.7 added a "DSL" into its parser whereby we could omit parentheses in function calls. Gradle uses this facility for its CSS-style syntax.

In theory, we can drop out of the DSL to add Groovy code (as you can with Leinengen to add Clojure code, etc etc) but in practise virtually no-one does that. I've checked the Gradle build scripts for some large open source projects, even Groovy's own build scripts, and nowhere have I seen anything other than the DSL syntax used.

Gradle 2 brought the facility where you could configure a build using any JVM language via an API, and now Java 8 has lambdas I suspect this facility will get used more, and Gradle might even replace Groovy with a custom lightweight DSL for builds not requiring extra programming.


What do you replace Gradle with?


I'm extremely happy with SBT.


Because type safety is actually really valuable?

/uses Scala for everything, from scripts to backend. Groovy usually translates 1:1 into Scala, but without sacrificing type safety.


In current version of Groovy you can mix static and dynamic typing in different sections of code by telling the compiler what are your preference.


Up to a point - I found the static support was quite buggy and I got the impression not many people were actually using it. Has it improved in the last few years?


Why would you ever _not_ want typechecking?


Static typing comes with benefits and costs. If you don't want to pay the costs and can forego the benefits, dynamic typing is fine.


Generally people that don't like explaining what they mean to a computer.


If your type system requires explaining things to a computer, your type system sucks, not static typing.

I use types because the compiler can explain things to me.


There are not many technical reasons for not to do that (like the speed of invokedynamic). It has been a consideration for at least one project I was part in.


That's what I do. It has the added benefit that anything you do to improve using Groovy can be leveraged with plain Java too.


As also can Clojure though with less bugs.

More

Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact

Search: