Java for Everything
teamten.com
teamten.com
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.
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.. @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.
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.it could also be accomplished with
return -1 * o1.compareTo(o2); return o2.compareTo(o1);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.
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.
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.
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...
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)
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.
> 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.
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.
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.
(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.
coll.sort(comparing(identity(), Integer::compareTo));
Or:
coll.sort(reverseOrder())
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.
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.
( o1, o2) -> o2 - o1
No ternaries or else-ifs required. Swap o1 and o2 if you want ascending.
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.
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.
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...
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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...
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:
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 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)
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...
facebook use php
deal with it
programming language is one thing, marketing your solution is another thing
https://www.facebook.com/notes/facebook-engineering/speeding...
Mind your out-of-date rebuttals to anecdotal evidence :)
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.)
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?
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.
I've never even heard of this. I agree with most of this advice, but, I wouldn't exactly call it a defacto standard.
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).
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").
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).
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.
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.
> 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.
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.
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.)
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.
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 ?
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?
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.
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.
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.
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.
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
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.
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 ...).
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.
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.
Being able to refactor classes/methods/variables names without even care where those are used is a huge benefit IMHO
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();
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.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.
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.
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.Modern Java has first class functions.
https://docs.oracle.com/javase/8/docs/api/java/util/function...
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.
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.
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?
We've rediscovered ahead-of-time compilation.
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.
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.
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.
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.
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.
The verbosity, static typing, etc, of Java contributes information to the "next guy" about developer intent and is incredibly valuable.
;)
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 :).
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"
> 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.
In other words, I viewed this article as a large waste of time. Nothing has been added to what is already conventional wisdom.
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 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.
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.
Also that Oracle Labs have SubstrateVM, which is an AOT compiler based on Graal.
Then there is also JikesRVM and RoboVM.
Curious: why is this a requirement for you?
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.
The interpreter/compiler is just the VM; the real language is the combination of all libraries available for it.
And that the reference implementations get less C++ code with each release.
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.
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.
- 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.
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.
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.
Scala feels "designed", while Java feels "evolved".
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")
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.
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.
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).
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?
I'm definitely going to learn Scala once my adventure in JavaScript world wrapped up.
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.
As soon as a project gets large, it outgrows the scripting language anyway.
-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 on iOS, still no story on Windows Phone, which actually happens to be over iOS on some European countries.
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
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.
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.
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.
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.
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.
Because they require the use of Apple's hand-rolled Java 1.6
https://youtrack.jetbrains.com/issue/IDEA-117324#comment=27-...
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 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.
(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...)
Although, i'd pick java over C++ unless i'm doing some very performance critical
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.
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.
and I would argue with the added bonus that you can share the UI without an horrible result
(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)
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.
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.
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.
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.
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
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?
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.
"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).
1.7 introduced a simplified version:
Map<String,User> userIdMap = new HashMap<>();
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.
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.
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.
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).
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.
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.
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.
He's one of the core groovy developers - unless he's one of those despots you're talking about?
/uses Scala for everything, from scripts to backend. Groovy usually translates 1:1 into Scala, but without sacrificing type safety.
I use types because the compiler can explain things to me.
My view of Java may be a bit biased, since I also tend to look at things from the sysadmin pov nowadays. I can only tell that I never disliked Java until I had to take care of the monstrosities the Java developers bring to life, and mind you - I started out as a Java dev back in 2000.
The main issue I have with Java is the JVM and memory usage and leaks. No matter what people claim - no memory leaks in Java is a fairy-tale. We run both custom C++ and Java services (about 50/50) on a few hundred servers - and I cannot find a single issue in our ticketing system related to memory problems with any of our C++ services. Java services? Every. Single. Week. When I get an alert some JBoss unexpectedly died or became unresponsive - "java.lang.OutOfMemoryError" is most likely going to be the problem. A lot of those are permgen space errors, and yes you can try all the "fixes" like increasing the permgenspace, permgensweeping, enabling class unloading, ... but these don't always fix the problem and slow down your services. Every time this happened in our own services, this had to be fixed by our developers. It takes weeks to locate the problem, and you end up deploying new versions, upgrading JBoss, JSF, Bouncycastle, ... whatever.
It's mostly the "memory is not an issue" attitude most java devs have. It's not JBoss specific, we also have some services written in pure Java suffering the same problems - but the majority of the Java apps run in JBoss here. Stress tests in test/qa usually don't bring up the issues I've seen, which sometimes only occur after weeks of running flawlessly with production-grade loads.
The 'fix' is then running the critical apps twice behind a load balancer, waiting for one of the 2 instances to die (for logs/memory dumps), automatically restarting them - and hoping they won't go down simultaneously. Truth is - memory management in Java is HARD. When problems pop up, apparently finding the source of it is very difficult. I can't count the times I've heard "we think it should be fixed now", only to be confronted with another alert that the service died again a few weeks later. If it was one service we'd run, it would be fine, but we run quite a few more - resulting in weekly interruptions, tickets, sending of memory dumps to developers, convincing them - again - that it is their problem and not mine, ...
So well - I'm sick and tired of Java. The only thing worse to deploy and manage are Ruby apps. But that's a personal opinion.
All statements of the form "it's relatively faster to write programs in language Y than language Z" are incorrect because it disregards important parameters such as programmer experience with languages Y and Z, and whether or not it's a comparison between 2 different programmers.
Also there are some performance gains that only pay off at Twitter or Facebook scale [1]. Sometimes shaving milliseconds costs time but rakes in little to no benefits.
Php it's another example, Facebook uses php and it made changes to its compiler in order to make it way faster.
So bottom line, if people feel better writing in Python let's write Python and improve it to make it faster.
That said, I don't understand the obsession with 1 language to rule them all that the Java and Javascript crowd seem to share. I do understand having 1 go-to that you reach for to build projects. Something broadly applicable like Java, C# or Python.
But shell scripting in Java? Seems a bit extreme, I'd never bother. You can pull out a Python/Powershell script that does whatever you're trying to do and do it much easier and faster. There's a reason Windows has C#/Powershell, and Linux has (as an example) Java/Python.
Here's my issue: no matter what problem you try to solve the solution looks like Java. I want my solutions to look like my problem.
Static imports go part of the way there, and if you're good at naming and architecture, the learning curve for any particular system remains relatively low. It's a hack/sugar, but it helps.
But that's about as far as you can go using only stock Java, e.g., no syntax extenders, no byte code treachery, etc. AOP can help, but everyone has to be aware of it, and comfortable with a system designed with AOP from the beginning.
Java for shell scripts? No thanks.
I then had to laugh when I needed to explain some JavaScript (and jQuery) I wrote to him and exclaimed, "What the hell is this doing!". I had to get back to him a few minutes later on.
As for Java and C# on the web. I just wish it was more accessible to smaller companies. 100% of my freelance stuff are using cheap hosting that rarely support anything more than Perl/PHP.
One year ago I would have agreed with you, but I have since discovered some of the newer PaaS solutions like CloudFoundry / Pivotal CF [1] and OpenShift [2].
I'm using Pivotal CF for my current side project (a public website + web service) and am paying about $7/month.
Some ASP.NET web hosts offers $10/mo plans (a bit more if you want to use SQL Server). Or go with Azure Websites (Shared), starting from ~$15/mo if you think you need to scale up real soon.
The same goes with development costs as well (if you are using a Windows machine already).
Visual Studio Community edition is free and has support for extensions (where Express does not). They are great for freelancers. Do note that commercial licensing kicks in for > 5 developers.
http://www.informationweek.com/cloud/software-as-a-service/p...
BTW. I work with Java & GWT and I find it overkill for our needs. It took 5 months to make a 4 views, each with image or video grids and upload button.
On the side. I have on my free time working with Django and have a website with Authentification, comments, categories... In the end, my personal project has more features.. less lines.
Instragram uses Django and so is Disqus. Are those slow?
I work with the same stack and don't understand what could have taken so much?
Or did you include time spent reading the docs?
Ok, Java is not terrible (PHP is terrible), and the JVM is a marvel of eat-your-RAM engineering, but this makes me sad, because there are only two things that can be said about Java: it's not terrible and it has a big ecosystem. There is nothing brilliant about it. It is slowly crawling toward convenient feature, but it's never going to be at the same level as a well-designed functional language in terms of correctness and readability-to-expressiveness ratio.
I am developing a very simple framework, insipred from Sparkjava and Play Framework: https://github.com/mustafaakin/WebOM It basically maps either HTTP requests or Websocket connections to Java objects with typed parameters.
Are there any drawbacks with it?
Except the part about scalability, that's just BS. It has little to do with language and is all about architecture. Sure, at some point language can help you squeeze every ounce of performance out of the hardware (although my money would not be on Java for that), but that's only in cases where either performance is critical or the scale is so huge that saving on hardware makes a big difference.
Java people take many things for granted.
http://benchmarksgame.alioth.debian.org/u32/python.php
I mean, I would agree that 1s versus 1.3 seconds doesn't really matter. But look at those numbers we're talking 40-50 TIMES faster in half the cases. The number I tend to use is that one programmer is worth 10 servers. But this has diminishing returns : the larger the site gets, the more you'll focus on servers.
But even for small sites. Python is about double java's productivity, no more. That only helps you for very small programs.
So for large sites, python would have to be 40-50 times more productive than java. This is exactly python's weak point, and java's strong point ...
And from experience I know. Large python programs are horrendously difficult to change. They're like how large perl programs used to be. Changing a tiny thing in one far removed part of the program affects 10 other places in the program, with absolutely no warning, until the site crashes. And then you put a try-catch in your main loop and AAARGH.
Also, I don't like the CLBG - it removed PyPy and a bunch of other implementations of various languages. I would be intrigued to see the speed of PyPy on that particular set of benchmarks, for instance.
http://benchmarksgame.alioth.debian.org/play.html#languagex
But we all seem feel the same way about this, we all feel that we should sit on our hands and wait for someone else to do the chores we don't wish to do.
Hah, if only it was always just three letters... :)) Usually more, and it's called NOISE. That's why C# has "var" and C++11 has "auto" (with all the benefits of strong typing still in place, obviously)
"And other languages like D and Go are too new to bet my work on."
I'd argue that D isn't really that knew, only niche. It's been around for over 10 years now.
I was first exposed to Python in 2002. The sentiment in the quote above is reminiscent of the reasons I came back to Java. With a little Bash and some Java or a little Python and some Java I can do pretty much anything I need from system services to web to rich clients.
Edit: Great article.
I was in full agreement aside from this. Unit tests are more than just a substitute for static typing.
A parser is a discrete chunk of code that's general-purpose (likely to be called from lots of places with different content), but with a fairly straightforward list of cases that you can/should test to see how correct and robust it is.
There's a lot of code that fits into this category; not just parsers.
For me I've found I only need a few things to get started. One is the JDK, obviously. Another is Maven. It downloads dependencies for you and is pretty standard (there's also Gradle which some projects use). Finally there is IntelliJ for development. That's about it. Pretty much everything else can be downloaded and installed automatically be Maven or your IDE.
For web development, I've found Ninja Framework to be quite nice. The documentation is very good. The biggest problem is that it tends to delegate to lots of other libraries for functionality, and often those libraries have been around a long time and in some semi-standardised state that can be horrifically confusing (e.g. Hibernate). The Java world REALLY likes to take good open source libraries and then copy their interfaces into standards that other products can then implement. This sounds great in theory, and I'm sure some people do benefit from that, but it makes learning this stuff a giant PITA because the documentation for everything always has five versions, four implementations and every annotation or API has two identical versions in different namespaces, only one of which will actually work. Argghhhhh.
However if you do make it past this swamp, then the tools themselves are actually rather powerful and performant.
1. An IDE (I highly recommend IntelliJ IDEA)
2. A build and dependency management tool (I prefer Gradle, but Maven is a reasonable choice - though way more verbose)
Beyond that point, a lot depends on what you want to do. Some of my preferences (YMMV):
* logging: slf4j over logback
* json serialization/deserialization: jackson
* db access (if you don't need or want ORM): jdbi
* db migrations: flyway
* REST services: jersey
* networking: netty
* embeddable http server: jersey
* http client: apache-commons http client
* metrics: codahale's metrics
If you're building a backend webservice I highly recommend looking at Dropwizard, which handles a lot of the boiler plate for you.
I like Play, but that's 'cause I use Scala. It has a Java version, but IDK how good it is.
Your package manager will get you the compiler (probably as part of a package for the whole JDK).
You can use whatever editor you already like. It'll help if it has some support for Java's syntax, like highlighting or whatever.
If you want to add one non-essential tool, it should probably be a build tool that knows how to download libraries and compile your code against them. Gradle is the only sensible choice right now - it's far from perfect, but it should be tolerable. Again, your package manager will probably have Gradle. You only need it on the development (and CI) machine, not on the target.
At some point, you should probably give an IDE a go, to see how useful automatic refactoring is. Eclipse and IntelliJ are both free and pretty good (IntelliJ has free and paid versions, but the free version has everything you'll need to begin with). People love to argue over which is better, but the truth is that there's not a massive gap between them. Any IDE takes some getting used to, so it's probably better to start with a straightforward editor rather than an IDE.
If you want to use IntelliJ on the Mac, you might need to edit its Info.plist file to allow it to use a current version of Java. For some reason it's pinned to 1.6 by default. Gets me every time.
I can't think of anything you need to do to use Java that is remotely sysadminish, unless you count installing packages.
It's been years since i've read a Java book. Back when i did, by far the best was Just Java. Thinking In Java was also great. However, those were last revised 10 and 8 years ago respectively, so possibly not worth picking up today. They certainly won't tell you anything about the rather crucial new stuff in Java 8.
Install eclipse. Get a non-JavaEE version - probably "eclipse for java developers". It's flaky software and you will have to babysit it sometimes, but it's still the best choice.
Use maven, then you don't need a sysadmin to maintain your libraries. You just add libraries as dependencies (you can even use a search wizard in Eclipse) and it Just Works. Start by using the new maven project wizard; I would skip archetype selection entirely, but if you want to use a particular framework you can choose one of those and get a "hello world".
Add libraries one at a time. If you're writing a web application I love Wicket which is literally the best-designed library ever. Aside from that you're facing things that, like eclipse, are a bit clunky; sooner or later you will have to learn Spring and Hibernate. Everyone loves to hate them and with good reason, but people will expect you to know them, and they do have good parts.
Try to do as much as possible in pure java. Use embedded jetty and write a normal application rather than messing with war packaging. Use annotation-based Spring configuration rather than XML, and the same for Hibernate.
The whole ecosystem is old and crufty. You will have to get used to random crappy workarounds for all sorts of problems, and you will probably have to cargo-cult some things to get stuff working. This is unfortunate, but I guess it's the price of stability. There are good sides to the ecosystem too. Sorry to be such a downer.
Honestly, you just listed some of the best reasons to use Java.
Other languages are less dependent on a heavy IDE; I can write Python or even Scala in vim (+ repl in another tab) reasonably comfortably, and while vim has its warts it's a lot less fragile than eclipse.
Spring is IMO not worth the complexity compared to explicitly constructing things, but if you really want to do that there are ways to do it in Scala (e.g. just using implicits, reader monad) that don't require annotations or XML and don't have anything like the number of quirks (e.g. autoproxying, about 10 magic lifecycle methods, configuration-dependent behaviour on duplicate beans) that Spring does.
Likewise Hibernate is nice but it has some irritating misbehaviour (e.g. passing empty lists can cause it to make SQL syntax errors) that isn't present in ActiveRecord or even modern JVM alternatives.
I didn't expect my comment to be so negative when I started writing it, but as I started to try and explain the basics I realized how many arbitrary workarounds a very basic Java app needs. A lot of this is 10 years of accumulated cruft rather than fundamental problems, but at the sharp end new users still have to deal with it.
Many can give examples of successful or failed projects in both languages but it's just conjecture.
The only correct way to look at language choice, and the only objective one, is to use the language you are productive in. The best language is the one you master.
Love this quote. This is a thought-provoking article, even if you don't agree with everything as stated.
Or if you want to own the hardware, you can do the equivalent with a Chef script, or a Puppet script, or..
No one is going to set up 500 servers by hand.
If they're (e.g.) ec2 microinstances, 500 servers would cost you about $6,000/month, which is comparable to the monthly cost of just one extra programmer (maybe much less, if you're in a high wage location and you add in all the benefits, etc.) And remember, that's assuming you're operating at reddit scale, which, to be blunt, you're not likely to be doing.
The article is full of similar handwaving (e.g, "it's only 3 extra characters" when most class names are far longer than 3 characters, and you also have to multiply that extra typing by the number of lines in your codebase).
I'm glad Java works for him. Me, I abandoned it around the year 2000 and have never looked back.
Or web client with a lot of logic in the browser.
Or even a custom, native windows client. (Ok, Swing or SWT, but, ...really?)
"Language X for Everything" is simple not possible, regardless of the value for X.
* C# (and/or F#) to build iPhone, Android, and Windows Phone apps [1]
* F# code that compiles to JavaScript for front-ends [2]
* C# (and/or F#) code for Windows and *nix clients [3]
They are not perfect (nor the tooling are free), but it is possible.[1] - http://xamarin.com/
[2] - http://websharper.com/
* C# code that compiles to Javascript for front-ends [1]
Or, indeed, any .Net-targetted language like Nemerle, Boo and <gasp> VB.[1]: http://jsil.org/
Apart from the ecosystem and the language itself, it's often the reference (or only) implementation which makes it unsuitable for a particular job.
Do you know of any good and free ahead-of-time Java compilers that produce native binaries without any additional dependencies?
I haven't been able to find any, but perhaps my Google-fu is weak. gcj is obviously not a good answer.
For good ones I only know of commercial like Aonix, Websphere Real Time, Excelsior JET, JamaicaVM and a few others.
If you want to go free and are happy just with GNU/Linux and Mac OS X/iOS, then RoboVM might be an option.
If you want to go research, there is Graal/SubstrateVM from Oracle Labs and JikesRVM, a meta-circular JVM.
I think he goes a bit too far with "unit tests are a waste of time" (maybe he just means for type checking). But other than that this perfect captures my very pragmatic view towards Java. There's a lot to be said for consolidating on one server language, and if you're going to pick one language, that's the one.
The last time I tried to do anything in Java, I was instructed to "just run the maven build script". After watching that flaming train wreck I walked away and haven't looked back since.
Just pickup any Android device and you can see the lag, ever wonder why all the java phones have 4 GB of memory and a quad core processor just to draw a 1920x1080 screen?
Jackson is good, and more powerful in terms of model mapping, but I find it much more complicated to work with.