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.
Ditto. Spring feels like "the worst of Java", while the exact combo you list above is some of the best and the set I reach for. Jetty is showing its age a bit right now, but it's so much nicer than dealing with Tomcat.
I think the difference is that stuff is less hastily cobbled together. People use additional libraries because they add value, not because they paper over ugliness and holes of existing libraries.
Scala feels "designed", while Java feels "evolved".
That even though Scala is better designed than Java, without Java's cruft earned through evolution, most companies will keep on searching for Java developer skills.
80% of the problems with java as it's usually written are bad policy rather than fundamental language problems. But there are real cases where language limitations mean you have to either use an unpleasant framework or write unpleasant code.
Jersey's annotations are pretty nice, but they're still annotations, not really part of your code. You can be bitten by silly errors like an implementation's annotations not quite matching those on its interface, and when (as is often the case) the annotations get repetitive for a group of similar services, there's no way to factor the common part out. In Spray I can write route definitions that are just as neat as the Jersey ones, but it's plain old code which is an enormously powerful concept; a route can be refactored just like any other code.
Guice is similar, e.g. declarative transaction support; better than managing database transactions by hand, but annotation-based proxying is a bit "magic" and confusing to debug. In Scala I can use a monad for transactional operations; the code (using for/yield) is almost as effortless as annotations, but operations which use the database show that in their type and the type system enforces that my transaction boundaries are in the right place. Even more importantly, refactoring in the normal way is safe.
(Also e.g. the lifecycle features in Spring are really valuable (and virtually impossible to do without annotations in Java, at least pre-8). In Scala there's scala-arm, which achieves the same thing in a monadic way, with the same advantages as doing that for database transactions. And since the same abstractions are used in both cases, you can write types and helpers that work with both "database operation" and "requires lifecycle-managed resource")
So here's the thing about annotation and Jersey, I believe you can annotate the seralization of return type once at the top of your resource class, the rest, like http verb, needs to be repeated unless you take the convention one more level up a'la Rails. But that's Rails, a web framework that people said does not fit for microservice. Sinatra is.
But if you take a look at how Sinatra (or Rails) serialize the returned object, you notice the duplicated code. Especially if you want to return both JSON or XML based on the request header. To add to this, both frameworks do this serialization as part of the code logic that you have to write, instead of slapping annotation once...
Let's take this further: exception mapping to http response code. In JAX RS, you can map application exception to certain WebApplicationException with specific http response code, I believe you have to handle them manually in Sinatra. You would have to catch the exception and convert it to the intended one per method on your controller.
> But if you take a look at how Sinatra (or Rails) serialize the returned object, you notice the duplicated code. Especially if you want to return both JSON or XML based on the request header. To add to this, both frameworks do this serialization as part of the code logic that you have to write, instead of slapping annotation once...
I can't speak for Sinatra, but in Spray I'd just write a directive for this - maybe it exists already, but if not, it's a couple of lines - and then I can use it just like any of the built-in directives. And this is a perfect example of why "just code" is so powerful. Jersey is a very well-designed framework and I'm sure you can find examples where the built-in Jersey thing is better than the built-in Spray thing. But no framework is perfect, at some point you find yourself having to extend these things - and in Jersey's case, IIRC once you want to write your own annotation you need a magic .service file containing a class name to use to interpret that annotation. And then the only way to pass dependencies to that processor is by static global variables. Good luck refactoring that, and don't expect to be able to use hot code replace when debugging it. And good luck remembering how the mechanism works in six months' time. "Plain old code" has a lot to recommend it here.
> Let's take this further: exception mapping to http response code. In JAX RS, you can map application exception to certain WebApplicationException with specific http response code, I believe you have to handle them manually in Sinatra.
Again, trivial in Spray - I do my error-handling with Either and then I have a meta-marshaller that knows what to do with the error case. Better still, error handling isn't a special case - I do exactly the same thing if I have async code in my methods (can JAX-RS handle Futures? Can it handle a different kind of Future from a non-standard third-party library?). I can do exactly the same thing with a database-transaction monad, and then I can have session-in-view but in a principled, safe, zero-magic way. I can do the same thing to e.g. show debug traces if a special header is present - like Jersey's dynamic choice of serialization format that you were so impressed by, but it doesn't have to be built into the framework, it's just code that I can write myself.
I've been using Jersey since 2010 and I have never need to write my own annotation. Maybe I'm lucky enough that Jersey fills my need perfectly and maybe you're right that once I needed to write my own annotation, I may run into a bit of trouble (though some people do write annotation only to be consumed by reflection, hence bypassing the service file) but I guess... that's like.. what... 1-5% extreme use-cases? Like... LISP macros that makes programmer reached nirvana or something?
But in my case, Jersey fills my need without me writing low-level REST code (dealing with exception to HTTP status code, marshalling objects to different formats) embedded in my controller/business logic.
> I can do exactly the same thing with a database-transaction monad, and then I can have session-in-view but in a principled, safe, zero-magic way.
You sound like programming in another level higher than mine. I applaud that. I'll revisit Spray/Scala _when_ I found a definitive use-case for this. For now, Java seems to fit the bill for pretty much 99% my use-cases and fit my taste as well (less low-level code stuff because it is built-in the framework that is well-architected/well-designed so that I can focus on business logic code).
> You sound like programming in another level higher than mine. I applaud that. I'll revisit Spray/Scala _when_ I found a definitive use-case for this. For now, Java seems to fit the bill for pretty much 99% my use-cases and fit my taste as well (less low-level code stuff because it is built-in the framework that is well-architected/well-designed so that I can focus on business logic code).
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've never been a big fan of Spring so I was pleasantly surprised to discover Dropwizard which includes the tools you've mentioned, a few others, some best practices, and a little glue.
So what? For most problems there are fast, well-designed libraries available with idiomatic python interfaces; why would you care about the implementation details?
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.
Some good, some aren't, some used to not work with Python 3, some still don't work with Python 3, some reinvent the wheel died due to not being popular (sql object, pylon, turbogears), some looked relic and not worth to learn ( plone, zope).
Like the article said, it's fun and quick to hack in Python but just ain't everybody taste... especially seeing the age and the quality of some of those libraries.
> I’m even taking this to an extreme and using Java shell scripts.
Having a strong Java background, it is a pleasure to write Groovy for shell scripts.
I like the blog post. Whenever I looked into other languages/platforms, I found the "tradeoffs" of Java (as pointed out by the other languages/platforms) to be less important for me. Java/the JVM may be evolving slowly. But it evolves and does it in a reasonable way (JCP, frameworks).
Speaking of - how is Groovy doing these days? I looked at the Groovy webpage and I saw ads splattered here and there - never a good sign, I also see that the mailing lists are pretty quiet. Is Groovy dying?
Of course there are those two projects everyone mentions, Grails and Gradle, but I would say it's more correct to describe them as the only two niches where Groovy is actually used a bit, it's not like Gradle and Grails are just "flagship products" of a greater ecosystem.
For both, there are already better replacemens available, so I don't think they will grow much in the future.
It's a stretch to say that Gradle actually uses Groovy. Groovy 1.7 added a "DSL" into its parser whereby we could omit parentheses in function calls. Gradle uses this facility for its CSS-style syntax.
In theory, we can drop out of the DSL to add Groovy code (as you can with Leinengen to add Clojure code, etc etc) but in practise virtually no-one does that. I've checked the Gradle build scripts for some large open source projects, even Groovy's own build scripts, and nowhere have I seen anything other than the DSL syntax used.
Gradle 2 brought the facility where you could configure a build using any JVM language via an API, and now Java 8 has lambdas I suspect this facility will get used more, and Gradle might even replace Groovy with a custom lightweight DSL for builds not requiring extra programming.
The site at groovy.codehaus.org doesn't mention anything about the new site (actually www.groovy-lang.org). Until it does the new site is unofficial and just one of the 5 despots at Codehaus trying to grab control of the product away from the other 4 despots there. That despot has tried other tricks like soliciting for subscribers to his weekly "news mailout" which is mainly links to tweets mentioning Groovy.
If an old site for anything (here, groovy.codehaus.org) doesn't mention it's moving to a new site (here, www.groovy-lang.org) then I question what's going on. As for your link, it's a link to a personal blog and not an article on the Codehaus Groovy site so it's just as unofficial as the supposed new site for Groovy.
Up to a point - I found the static support was quite buggy and I got the impression not many people were actually using it. Has it improved in the last few years?
There are not many technical reasons for not to do that (like the speed of invokedynamic). It has been a consideration for at least one project I was part in.
I am more convinced by the part "write everything in one language", and less convinced that Java is a great choice for that language.
On the other hand, if you're going to write everything in one language, you do need a language that is capable of doing nearly everything, and doing it well. And I see how Java is a reasonable choice.
But yeah, I think "pick the right language for the job" (and the corresponding "when all you have is a hammer...") under-estimates the extent that the right language for the job is the one you know best, because you'll be able be most effective in it.
(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)
I cannot keep my sanity when I use dynamic languages in fairly big projects. I just cannot organize my code and all the functionality good. So, I looked at the options at Java and most of them looked either very complicated(Spring) or insufficient.
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.
I'm not sure what you're trying to do. If you're talking about dependency injection:
1) be aware that you're ditching some safety by relying on it
2) look at Guava
I just map a request like /users/:groupId?orderBy=name to A java object like "int groupId", and "String name" and it puts them automatically by converting, and if you wish you add some checks, notnull, range etc. and It replies bad request to client. Therefore, I do not do this conversion and checking each time.
I'm starting to put together my own Java web framework to make things easier to get started quickly and borrowing ( heavily) from other language frameworks. https://github.com/bluedevil2k/Jiffy
Java doesn't seem too popular here but used right it can work pretty well, imo.
For instance, I use Java for the backend of a name generator web app. It's astonishingly fast and displays results almost instantaneously despite running a good amount of backend calculations.
This speed became an issue because you'd push the go button and the names would update - but it seemed like nothing happened. So I ended up adding an artificial delay twice (the first time it wasn't enough of a delay).
On the other hand, its structure and methods can at times be frustratingly complex.
You have to admit that for coders, the joy of writing helps a lot for job satisfaction. I write both Java and Python (for very different applications) and I just always feel like Java makes it hard to write anything elegant almost on purpose. The proliferation of huge frameworks and FactoryFactories clearly doesn't help.
I think you can underestimate the value in actually enjoying writing - I'm just more motivated every day I can write elegant python code. Conversely every day I spend fighting Java for an elegant solution and winding up inevitably with something a bit half-arsed because of some limitation in the language I just feel grumpy.
The problem is that one guys "Joy Of Writing" rapidly becomes the next guy's "Torture Of Reading", and with enough of a time-interval those two can be the same person.
I feel Python is good in this regard compared to other interpreted languages. There's a lot of emphasis on "Pythonic" style which you tend to pick up as you learn, so people are discouraged from excess magic (Explicit is better than implicit) and the syntax at the very least lends itself to sane formatting (especially with PEP8). Personally I've rarely had any true WTF moments reading either my own code or code from (reputable) OSS projects.
I'm of two minds on this. Certainly it's important people find enjoyment in the day-to-day reality of their job. Unhappy people don't write good code in any language. But I honestly do thing people can have too much fun writing code. We've all fallen in love with something we've written even though it might not have been the simplest or most understandable or idiomatically sound.
Writing Python is fun. But that joy can cloud your judgement, and if we are to consider ourselves professional, we have to look beyond just that and make decisions based on our employers best interest. Sometimes that might be Python, but in my experience, quite often that's boring old Java.
You might not need factories, but they get foisted on you anyway. But the proliferation of "programming patterns" in java I think is symptomatic of a basic user-unfriendliness in the language.
Off the top of my head I can think of three Patterns just for creating objects (Factories, DI, Builders) - the fact that these are even required, that object creation isn't self evident, suggests there's something wrong in the language design
The problem with verbosity and repetition is not that it takes longer to type the code, at all. The problem is that it creates dependencies which you have to manage by hand.
Changing `Foo a = new Foo()` to `Bar a = new Bar()` doesn't seem that bad... except when you have to propagate that change through the code base. Half of Java's tooling is dedicated to solving a problem that doesn't exist in good duck-typed languages or those with type inference.
Verbosity is also a warning sign for lack of expressive power. If you have a pattern like `if (cmd == "run") run();` in multiple places in your codebase, you want to make it so that changing one changes them all. Java won't let you factor this out easily, but worse, it won't catch you when you make a mistake (better languages will either do first-class functions or pattern matching and exhaustiveness checks).
Note that this has nothing to do with static vs. dynamic; verbosity is a problem that can be solved in many ways, but it is a problem. The author also spends a lot of time equating statically typed with fast; well, there are plenty of very fast dynamic languages.
There certainly are reasons to like Java, but these aren't them.
DISCLAIMER: I write mostly java, at home and at work.
Refactoring goes a lot further than just renaming types. A refactor script _WILL_ rename both sides of 'Foo x = new Foo();' to 'Bar x = new Bar();', so given the right utilities (and if you use java for everything, it's _MUCH_ easier to become an expert at the tools!) this is not any more effort at all.
However, there are refactors for things that are much more difficult in a duck typed language. For example, if I have a bunch of methods named 'execute()' in my code, and I decide that this is a sad state of affairs and ripe for a refactor, I can refactor one of them to a different name and the tools will 'get it right', renaming the right calls (calls into this type) and not renaming the wrong ones (calls to another type's execute() method which has no relation to this type's execute() call). In python, you just can't do that. You'd have to rename all of them, defeating the point.
Similar concerns crop up for 'find callers', or 'add argument to method'.
There are also refactor scripts that are equally possible in both python and java, but which nevertheless require either a lot of manual editing, or an intelligent tool that can automate it, such as 'extract method' (taking the selected code and turning it into a (helper) method, figuring out which variable(s) would have to be passed along to make it all work as needed.
The point is: Duck typing does not obviate the need for refactors. It does make certain refactors impossible to 'safely' automate ('safely' in the sense of ensuring that, post-refactor, the code does the same thing as it did pre-refactor).
As far as 'dynamic == slow, static == fast' being a bit of an oversimplification, yup, that's true. Java _IS_ a heck of a lot faster than python, but that's mostly an implementation detail; you could make a pretty quick python. dynamic definitely does not help, but it can be worked around. Javascript JIT engines are seeing a lot of serious improvements right now, and a large part of it is guesstimating type info. They're getting pretty fast.
In the spirit of the article, though, static typing isn't just a boon for speed reasons (based on the practical upshot that java IS fast, and most dynamic solutions simply aren't, even if they could be with more engineering efforts): It becomes quite useful when you start having to read the additions to your code written by someone else, or rereading your own code half a year down the line when updates are required. explicit static typing also helps with refactoring, which is useful especially when you have to fix or extend your project.
Refactoring goes a lot further than just renaming types. A refactor script _WILL_ rename both sides of 'Foo x = new Foo();' to 'Bar x = new Bar();', so given the right utilities (and if you use java for everything, it's _MUCH_ easier to become an expert at the tools!) this is not any more effort at all.
Ctrl-Shift-R B A R
No, not much effort at all. Just twice as many keystrokes.
I wouldn't even mind the verbosity if it actually gave me some speed improvements, but it doesn't. There are plenty of statically typed languages where you just write x = new Foo() and the compiler will figure out the types for you.
One hand position still over the keys and uses common fingers, and is easy for emacs users (Ctrl + Shift + R), versus leaving the typing keys entirely to climb to a command key that's used sufficiently infrequently that you have to look at where it is.
At least that's my experience.
Oh, and more fun. If you're on a modern keyboard, you have to type the function key since apparently volume up and down and expose are more important than function keys.
Long story short: what's faster and 'less' for some, is more for others. And this is why we have options! :D
To parse Foo x = new Foo();, javac has to perform type inference on the right hand side to figure out its type, and then check whether that type is a subtype of the left hand side. Telling the compiler: "hey, trust me, variable x is of type Foo" doesn't make the compiler's job any easier at all.
In that case specifically, no, but in general doing type inference means running a constraint solver over the entire program, which will definitely add some overhead to the compilation time.
I don't understand the point. Are you claiming that search and replace functionality provides the same ease of use as an actual rename refactor ?
Foo x = new Foo();
int Fool = 5;
I'm sure you see the problem.
Dynamic languages are great, until the program grows. Then you hate yourself for having picked a duck/dynamic typed language (including Go, btw : programs become unmaintanable if they grow, not as bad as python and the like, but ...).
Still don't understand. Let's take the changes you need to make :
Foo.java
...
class Foo {
...
}
SomeOtherFile.java
...
Foo x = new Foo();
...
Equivalent in Python:
some_file_in_a_library.py
class Foo:
...
some_other_part_of_the_program.py:
x = Foo()
Keystrokes to change the name "Foo", in Java :
1) Position cursor on Foo.
2) Alt-shift-R "Bar" (+ enter)
Keystrokes to change this name, in Python :
1) position cursor on Foo
2) Change to bar (5 or 6 keystrokes)
3) Open some_file_in_a_library.py (couple dozen keystrokes, most people I see do this have to switch to mouse and use that)
4) Change the classname
5) Go through all the unit tests that you should have that test the class (you need 5x more unit tests in Python compared to Java as well, to have equivalent tests), and do the same. Yes, all of them.
Java wins out, by a factor of 3, maybe even 5. Even if the class definition and the usage were in the same file, it would still win by a lot.
Refactoring simply doesn't work reliably in Python. Heroic efforts by Jetbrains notwithstanding, it just doesn't compare.
So I don't see what you're complaining about. Making changes is only faster in Python in tiny programs, where you don't have the problem of interdependencies. As soon as you have some of them, Python starts losing out, bigtime.
Counting keystrokes in programming is like counting letters in a novel - the amount of time put to think of something, to discuss it, takes the vast majority of time. Keystrokes used to write something is irrelevant (especially if you type with more than 2 fingers)
And if the whole arguments boils down to Java not having a var/val keyword - yes, that would be handy; but you would then still need tools to figure out what is the type of val foo = calculateSomething();
Great, I suppose, but you didn't answer his execute() example at all. I don't care if you do it in vim, emacs, or an IDE, the problem is that in a dynamic language, you can't do it safely at any speed or with any number of keystrokes. Counting keystrokes is therefore completely beside the point.
It's a pain when you are first learning and typing every keystroke, but with a modern IDE (IntelliJ) you don't really need to worry about things like this.
> Changing `Foo a = new Foo()` to `Bar a = new Bar()` doesn't seem that bad... except when you have to propagate that change through the code base. Half of Java's tooling is dedicated to solving a problem that doesn't exist in good duck-typed languages or those with type inference.
A sweeping change like that is hard in Java, but it's nearly impossible in Python. That is, unless you're willing throw up your hands and assume your new duck looks enough like the old one, and cross your fingers that you don't find out in production one day. With a modern IDE like Eclipse, it's a fairly trivial matter to find all references to the class, navigate call hierarchies and make the necessary changes to adapt to the change in type. In a sizable Python program, good luck. You're pretty much forced to rely on string searches - hope you picked a distinctive function name - or interactive debugging. Ease of refactoring is a huge win for static types IMHO.
I'll be the first to agree that Java-style class hierarchies and duck typing don't mix well, but not every dynamic language is Python. Clojure, for example, is very easy to refactor when it's (very rarely) necessary.
Not saying static typing doesn't have it's advantages – tooling is probably Java's greatest strength – but there are other, equally valid, solutions to the problem.
That's why I like Limbo and later Go's implicit typing:
a := Foo():
a now has whatever type Foo() returns. If you change the definition of Foo then you don't have to cascade your type change through all of your source code.
If you are prone to having the "if (cmd == 'run') run();" pattern in multiple places, no language is going to fix your copy pasta and the maintenance issues it has. Java absolutely has mechanisms to fix that and factor it out, it just bs to say otherwise.
The headline does not match his conclusion at all, in my opinion. What he's trying to say is that "dynamic scripting languages are slower and more error-prone than compiled, statically typed languages". And to determine whether or not a scripting language is ever a good idea from 3 or 4 examples does not seem like a good idea. E.g. Lua seems to be a pretty good fit for the WoW UI scripting stuff and EA used Python (apparently successfully) for their Sims 4 scripting (sorry for it both being examples of games, those were just the first that came to my mind :D)
This post makes me wonder, what about Jython? I don't use it, but it would be a nice fit for the OP (writing performance critical code in Java, and use Jython as a glue).
"Java for everything, because it's the only statically type language with a fast runtime I know well".
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.
Java is perfect also for client side.
We have a client app (a complex VoIP softphone) with different codebase for all platforms (C++ for windows, java for android, ObjectC for iOS). Right now we are in the way to reduce all this in one single codebase written in Java and the user interface in html/css/javascript, so the user interface is always running in a webview.
-Java for windows desktop (there are pretty installers which automatically download and install the JRE if not present)
-Java for MAC and Linux desktop (same as for windows desktop. the same installer tools can generate also Linux and MAC packages)
-Java for Android (with a very minor conversion for which we already wrote a converter app)
-Java for Web (currently using a java Applet which works perfectly. We plan to use GWT to transform to JavaScript in the future)
-Java for iOS (will see)
This way we plan to cover 99% of all devices with java only (with some minor transformation for some platforms).
What is your opinion on this? I am in the right direction?
On mobile devices the issue is Oracle dropping the ball and leaving to third parties (RoboVM, CodenameOne,...) the work of providing JVM implementations.
This on iOS, still no story on Windows Phone, which actually happens to be over iOS on some European countries.
I am using java 1.5 features only :)
Actually i never understood this spike about language features. For me the focus is always on the problem what i am trying to solve (VoIP in this case) and never the language. Actually any language would do for me in which i can apply some encapsulation for better code management (think of java classes). The rest doesn't matter :) I was started with C and then C++, but for me C++ is still C with classes :)
>i never understood this spike about language features
You should really read about the Blub Paradox. Imagine writing all your coded in assembly. It would suck because assembly is an inferior language To those you mention. Now imagine working in a language that is higher level than what you've (yet) been exposed To.
We are working hard on making RoboVM as mature as possible. There's already plenty of applications on the App Store using RoboVM. Happy to talk if you need more info for decision making. Ping us at hello@robovm.com.
For development speed and code maintenance, this is ideal. Your team only needs to master one language and its set of tools and libraries.
You are pinioned by this choice on some practical levels. Mainly, some users and use cases demand the speed and lightweight user-experience of native apps. The native-vs-[java] experience is typically quite noticeable on all the platforms you've mentioned -- desktop, web, and mobile.
Right now I am working on the windows desktop app. I can tell you, that you don't notice any difference at all in speed (I also wrote a simple "container" app in native c++, so it is also loading instantly ..there is a ~2 sec delay to load the JVM, but meantime the user already sees the UI)
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.
IntelliJ has historically looked pretty native on MacOS X. At least until Yosemite pointlessly reskinned Aqua to look more ugly. Now I find myself quite happy that IntelliJ is not a native Mac app because I preferred the old look anyway :)
You can make the apps look native, if you really care. But in an era when web apps are the shizzle why would you even care? No web app even tries to look native. They just do their own thing and nobody cares.
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).
This is horrible, but not because of the Java part — it's the webview that puts your desire for a single UI technology stack ahead of user's desire for a decent UX.
That's where Go comes in very well in the interviews assuming interviewer also knows or can understand Go. It has short and precise syntax and the code usually doesn't need explanation.
The same argument can be made for any mature language with a solid ecosystem of tools and libraries.
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.
It has a lot to do with language.
If your language's runtime has solid threading and reasonably pauseless GC (at several gigabytes heap) you run into much much less problems with scalability.
You forget just how much difference there is between languages. Comparing Python and Java for example, it's easy to find things that take 1-2 cpu cycles in Java (or even 0), that take thousands of cpu cycles in Python (e.g. function calls).
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.
And yet there is a benchmark in that particular set you linked in which Python runs in 3/4 the time.
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.
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.
I agree that the project size (LOC and usage) matters a lot and that small projects could use almost any language. I don't agree that everything i linear. A project with 10 times the LOC is not just 10 times harder to build, it might be anywhere from 20-100 times harder. For example, 10 000 LOC is possible for a developer to read and remember quite well, 100 000 LOC is much harder and takes longer to read. 1 million LOC is probably really, really hard to read and understand (especially when we are talking about old code with a lot of cruft and possibly multiple changes in the design over time).
So for a small code base that happens to have millions of users you should probably go for a fast language and take the time to optimize a lot. For a large code base with very few users you should probably use an expressive language and don't care about performance. And then you have all in-betweens which are left as an excercise to the reader ;-)
If you're actually using good tools (Something like IntelliJ or Eclipse, and something like Maven or Gradle), and you use sane variable and function names (business oriented instead of tech oriented) verbosity is one of the worst arguments against Java.
The verbosity, static typing, etc, of Java contributes information to the "next guy" about developer intent and is incredibly valuable.
It's not so much that Java is great at everything. It's more like it doesn't suck at anything. Every other language has, somewhere, a deal-breaker for some particular use. I've not found one for Java. And Java's biggest downside, frankly, is that it hasn't attracted fresh young talent in a while, so it doesn't have really hot frameworks and libraries.
While I do think Java is great I think that's an exaggeration, I'm sure there are quite a few deal-breakers for particular uses. Personally I've opted not to use Java before because it cannot compile to a self contained native binary.
You will be excited to learn about gcj, then. The Gnu Java compiler compiles to native code, but it's currently not maintained, so newer Java features are out of reach.
You will be excited to learn about gcj, then. The Gnu Java compiler compiles to native code, but it's currently not maintained, so newer Java features are out of reach.
gcj has been abandoned. It was last updated over 5 years ago. It's not clear to me why you would even mention it.
I'm a software developer that primarily uses and likes Java, and the lack of a good and free ahead-of-time compiler for Java that produces native binaries is what I miss most in the Java ecosystem.
There's Avian. It can produce standalone, compact ELF files that have no dependencies. It's not an AOT compiler though. The problem with AOT in the Java ecosystem is quite a lot of modern frameworks and the like have ended up relying on the ability to synthesise code at runtime. Android has put a check on that kind of behaviour but it's still there.
There's also Excelsior, which is an AOT JVM, but it's for Windows only.
I agree that a really good AOT JVM would be very nice. It doesn't necessarily imply better performance however. I remember when GCJ compiled Eclipse for the first time, lots of people were surprised that it didn't magically fix every performance problems. GCJ engineers view was "HotSpot is an excellent compiler and it will take a lot of effort to beat it". When Sun Java became open source therefore, a lot of the incentive to develop GCJ disappeared. It was always primarily a licensing project not a performance project.
There's also Excelsior, which is an AOT JVM, but it's for Windows only.
Unfortunately, it's also extremely expensive. That's not to say it isn't worth every penny in some situations, but I've gotten kind of spoiled by free development tools for personal projects. I'm glad the days of spending hundreds of dollars for things like C compilers are long behind me.
I agree that a really good AOT JVM would be very nice. It doesn't necessarily imply better performance however.
For some application domains, I would be happy to trade speed -- and even features -- for the ability to create a native binary with no dependencies.
This is one area where I find the Go programming language interesting. I prefer Java, but the lack of a good and free ahead-of-time compiler for Java that creates native binaries with no additional dependencies is a killer feature for some situations.
Java projects can be compiled to a self contained native binary using http://www.excelsiorjet.com/ (though this is a proprietary tool, with a gratis license option for non-commercial projects).
When did you last try it? Startup time was optimised heavily some time ago and nowadays I don't notice any real difference unless I wrote some toy app and used "time". The JVM starts fast enough that you can write command line utilities just fine.
It is certainly substantially better than it used to be, but it is still pretty far away from an AOT compiled native executable. And forget it entirely if you are running Clojure or Groovy code.
The class of tasks for which Java's startup time is an issue is very very small. I wouldn't use it for a device driver because of resource issues but there aren't many command line commands where 0.08s is an issue.
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.
IMO, being tethered to the JVM is both its greatest strength and its greatest weakness. The JVM really is a masterful piece of engineering, but it is optimized so heavily for the server that any use case that deviates requires huge hacks to get what you want. For example, running a JIT on Android was so sluggish that Android had to design an entirely new runtime(ART).
Well, Dalvik is a JIT and ART can also do JITC and is designed for newer devices. So not sure that's a great example. The main reason Android doesn't use the HotSpot JVM is memory usage and licensing, I guess. The JVM class/jar format is very inefficient in many ways. On the other hand Dalvik is a very weak JITC. ART is stronger because it has more time to work and is, frankly, better engineered. Dalvik had a lot of problems even quite late in its lifecycle with things like lock inversions and strange method count limits, etc.
The JVM runs very well on the desktop as well as the server. I have to point out: Android runs Dalvik, not the JVM. But here's the point: Java isn't tethered to the JVM. Use the JVM for server, desktop, Use ART or Dalvik for Android. Use Jikes, Excelsior Jet, RoboVM or other VMs, compilers for other targets. The limitation you raise doesn't really exist.
I like how the author made the point about the commenting. I never realised it until I started my work training at a big company. I'm reading my colleague's C# (ASP.NET MVC) code and find it requires no commenting to understand even though I started learning C# pretty much on the job.
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.
> 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.
PHP vs ASP.NET hosting prices are close to parity now.
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.
Does anyone know a good starting point for learning not just Java, but how to install everything I need? I consider myself the Neo of OOP and a master devops, but every time I tried to use Java I hit a wall of unreadable manuals/guides , software impossible to install/maintain, and mixed opinions among Java devs. Like it can't be used without a dedicated sysadmin.
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.
I've heard mixed things about Play's Java version. YMMV, but the last I heard it was a "second-class citizen". Unfortunately I don't work with any templating myself, but I note that Dropwizard supports both Mustache and Freemarker. Would those work for you?
Great list. I wish this list and ones like it had a name other than "modern java" to distinguish tools/projects/people/interest/books. Because it's hard to name something that's a synonym for "new". Eventually "more modern java" is needed. And then "most modern".
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.
My opinionated viewpoint, if you want to learn this stuff for a job:
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.
> I'm confused. Is there something else in another language with better solutions for IDE, dependency management, dependency injection, etc.?
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.
I've mostly embraced the JVM (as opposing to hating it), but I find myself reaching for Clojure a lot more than Java (although I have an Android app that I'm tinkering with). I find that an IDE helps (I use NetBeans for pure Java), but whereas I can hack just about anything in Clojure, Python or Go without much hassle, Java slows me down for some reason - I suspect it's the humungous class hierarchies and the time required to find whatever I need to accomplish simple tasks.
Once you get used to working in Java (and have a relatively stable toolchain you can depend on), it's realistic to develop applications in Java almost as quickly as Clojure, though complex aggregations that Clojure makes one-liners will often be vastly slower to develop.
IntelliJ makes a lot of things easier as well.
When it comes to Java, you just need to really get familiar with your tools before you can be as productive, but once you are you can move quickly. Using Java 8 doesn't hurt either, streams are pretty decent.
The biggest thing for me is that the tooling around Java makes maintaining large projects extremely easy. Being able to refactor hundreds of files in a few keystrokes without worry lets me sleep well at night. It's certainly a lot faster to get up and running with a dynamic language, but the initial build out is a small percentage of the overall time you are going to spend with a codebase.
I've also built just about everything in Java from HFT algos, to an exchange, to a web server, to thick clients so I have an idea in my mind about how to solve any new problem that comes up.
I think this is the key point in the debate - weighing initial development time against ongoing development and maintenance. It's something that's hard to grasp until you've been around for a while working on real-world large-scale projects. And it's a hard thing to get the sense of when you're in school, writing throwaway code that doesn't last past the end of the semester.
When you understand this, then you can make an honest assessment - is it really important to get the first build out that much quicker? Sometimes it is. But I think it's overemphasized. The first one to market doesn't always win. And the shift from new development to maintenance happens quicker than you might think.
First to market has never ever been about using a dynamically typed language. Getting the ideas from talk to concepts, testing, bugfixing and marketing takes vastly more time than actually developing the code. So while Python might enable me to show my prototype on Monday, while that Java version wouldn't be seen until Friday, there still is quite a lot of time before you can say it's properly released.
Where these "fast" to develop languages shines are throwaway prototypes. For some people their ideas flow out much faster with dynamically typed language. But it is all too well known that even though the manager said you could throw it away, they change their mind because "it's basically finished, right?".
That said, you are spot on. Initial development is likely not where you want to focus at all, for any kind of project that needs to be maintained for more than a few months.
It's easy to make python faster, you have PyPy, you can even program everything in python and then make a simple C code for the bottleneck and wrap it with python.
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.
Having literally deciding to learn java last week for no particular purpose other than having enough understanding to be able to comprehend our software (which is written primarily in java) and prevent brain deterioration, I'm encouraged by the fact that the comments in this thread (so far) don't appear to be very negative (like when reading about php).
While I did buy a book, I wonder if anyone has any suggestions on a good java beginner's book assuming someone has "prosumer" programming knowledge (shell programming, some perl, some php, sysadmin skills and so on). Suggestions?
Welcome to the Java world! Like some of the comments so far I think the Java world is actually a pretty cool place to be right now, the language and approaches are becoming a lot less verbose. I blogged about some of the best Java books, hope it'll help you out! http://scalabilitysolved.com/dont-hold-back-your-java/
Question though. The first book you listed (which got excellent amazon reviews as well) was published in 2008. Typically I've been biased into thinking that a book had to be somewhat recent. Obviously this isn't the case here though. (Do you agree with that in some situations btw?). I would have never purchased this book if you hadn't pointed it out so thanks it's in my cart.
Effective Java is a solid choice, and a lot of the advice is still relevant six years later :) Also, JCIP is a go-to if you want to get more than a passing handle on concurrency in Java.
Agreed, the java books I listed still provide more value to my core Java than more recent books. I do the majority of my Java work now in the Play framework, when I use a new framework or library blogs and stackoverflow are my go to resources, for a deeper understanding of the library then those books are the way forward.
"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).
343 comments
[ 3.2 ms ] story [ 299 ms ] threadI 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.
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.
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.
http://www.infoq.com/news/2014/06/groovy-android
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.
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.
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)
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.
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.
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
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.
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
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:
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.
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();
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.
Modern Java has first class functions.
https://docs.oracle.com/javase/8/docs/api/java/util/function...
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.
Are there any drawbacks with it?
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.
-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).
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.
The verbosity, static typing, etc, of Java contributes information to the "next guy" about developer intent and is incredibly valuable.
;)
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.
http://www.excelsiorjet.com/
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.
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.
[1] http://www.pivotal.io/platform-as-a-service/pivotal-cf
[2] https://www.openshift.com/
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.
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.
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.
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.
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.
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).