I like the changes in Java 8, but I'm concerned about Java fragmentation between Oracle/OpenJDK and Android. It seems Android is stuck on Java 1.6 (since Dalvik is not "true Java" and is more like a VM that happens to implement a language very similar to Java 1.6). There's now a huge gap between 1.6 and 1.8. It's not just syntax like lambda and default methods. It's also the supporting API changes in collections (streams) and others. Dalvik was based on Apache Harmony which is a dead project and will never get the Java 8 API changes implemented. Does anyone know if Google is going to do something about Java 8 and Android?
Dalvik is being slowly replaced by ART (Android RunTime). Also, you can pretty easily hack Java 7 or even Java 8 into Android to use lambdas. Official, default support is coming soon.
Except those lambdas are not as efficient as the standard compliants VMs, as they make use of invokedynamic to generate better code, even inline calls for small lambdas.
Are you sure about that? I've looked at the way invokedynamic generates lambdas, and it's just generating anonymous classes at runtime using ASM. Inlining is from the JIT and applies to anonymous classes as well. I'm pretty sure you can get the exact same results without invokedynamic, you just have a lot more .class files to distribute.
I think you got it right. According to Grzegorz Kossakowski's comment (which is more accurate than the misleading article) :
http://www.takipiblog.com/2014/01/16/compiling-lambda-expres... , Java 8's lambda's aren't particularly efficient. They do create an anonymous class instance at runtime, as you say. Scala closures are implemented in a similar way, without invokedynamic, and as he says, and currently there is no performance win from invokedynamic's use in Java 8 vs the Scala impl. But it does hold promise of future optimizations, as he says:
"However, the key thing about invokedynamic is that it's essentially a JVM-level macro that defers lambda translation strategy to LambdaMetaFactory which is a library class. If Java 9 or 10 gets more direct (and performant) support for lambdas that won't require classes and object allocations then it can swap implementation of LambdaMetaFactory and all _existing_ code written for Java 8 will get performance boost. That is the brilliance of using invokedynamic in context of translating lambdas. We'll have to wait for future versions of Java to experience those benefits, though."
Well, for one, Lambdas are desugared into methods, not anonymous classes. Early on they used anonymous classes because it was convenient but that wasn't the final translation strategy.
My impression from the openjdk code is that each lambda generates:
1. A method in its parent class.
2. An invokedynamic instruction at the call site.
The invokedynamic instruction calls LambdaMetafactory, which compiles an anonymous class at runtime that calls method #1. So the only benefit of using invokedynamic is fewer class files, by deferring generating them until runtime.
It was a misunderstanding on my part about where they were claiming the anonymous class was generated. Early versions of Lambda were nothing more than sugar on top of anonymous inner classes and the claim above sounded very similar to that. However, I see that inside the LambdaMetaFactory anonymous classes are generated based on the call site. Probably the biggest difference is that Java 8 can avoid an object allocation when the lambda doesn't capture. Not sure if Scala supports this but I'm sure that it could do it.
Which might be fixable with ART as it's an on-device ahead-of-time compiler (I think it optimizes too? can't find references...). I have no idea if it actually does work for this in practice or not, though.
Well sure. But people don't update their Java installs either, neither do all businesses. They're likely not going to be able to take advantage of v8 stuff. And can dumbphones on a Java platform (Symbian? Nokia? Others?) run the new Java flashiness? Every platform has problems like this.
Arguing whether Java 8 will be completely supported or not ignores the nature of the Android API. Android doesn't even support 100% of Java 6 because it is not a desktop JDK and does not intend to replicate everything.
However, the Android team has actively been adding default support of Java 7 features piece by piece in recent months. They intend to handle Java 8 in the same manner. It's not clear which features will be supported in what version of Android, but lambdas are clearly a priority and can already be used today by early adopters using retrolambda.
There is a good reason that Sun didn't want this to happen and tried to stop it in court — successful against Microsoft, failed against Google. If I remember right, most everyone on here was rooting for Google to win and continue to fragment the language.
I wrote a lot of J2ME stuff a few years ago and you're spot on. I spent two weeks doing Java 8 bits with NetBeans which was really nice and spent the last two evenings writing my first Android app and what a complete mess it is. Plus the Android tooling is horrible to get working reliably - most problems being solved by "restart eclipse".
I also did some J2ME stuff back in 2003, most with Sharp and Nokia devices.
I read somewhere that some in the Android team are C converts doing their first Java gig.
Have you seen how broken are the generated Renderscript bindings? They don't have anything to do with Java conventions and feel completely out of place.
Haven't looked at render script yet. Still scratching head on the layout engine stuff and View infrastructure. It's fugly. I usually write C#+WPF and C++/Qt and HTML/Java EE and all of those are massively nicer to deal with.
If you are two days in and still getting around how Views and layout works I wouldn't call it a mess yet. You are still pretty early into it. Its not messy its just new to you.
From my experience once you get past the initial hump of learning their basic APIs and conventions its a very easy to work with platform. Maybe I am biased because I spend a lot of time with it. I also really like the tooling. How is it acting unstable for you?
Reflection
Serialization
Lambda expressions (JSR 335)
JNI and application native code
User-defined class loaders
Full annotations support (Runtime annotations)
Thread groups and demon threads
Full Math APIs (with BigDecimals)
Concurrency utilities
Full security APIs
Full collection APIs (Sorted collection classes)
Oracle was offering licensing for "real Java" at around $1 per device. This was too high for Google that wanted to make it entirely free. Kind of silly, since Android hardware manufacturers pay much more than that to Microsoft in patent licenses.
It's unlikely that the patent licensing situation would have been different with Java ME. It is entirely likely that it would not have been completely open source due to Sun (and ultimately Oracle) restrictions on Java ME.
They support Java 7 syntax, however they do not have the API improvements in Java 7. For example, Java 7 introduced a much improved File IO API in the java.nio.file package. It has very useful classes like Files (http://docs.oracle.com/javase/7/docs/api/java/nio/file/Files...)
This is a much bigger issue for Java 8. Just supporting only Java 8 syntax changes greatly reduces the benefits of the new lambda and default methods. Much of the power of the changes, especially lambda, require the changes to the collections API.
No, Android does not have any of this because Apache Harmony was killed by the Java 7 API changes. Namely, the documentation was no longer open, and Oracle withheld the TCK, effectively killing Harmony by making it uncertifiable as a Java implementation.
Harmony didn't die per se - It was killed by Oracle. Google's rationale for engineering a Java-ish VM with Java APIs was only legal up until Java 6.
Not to mention debacle it creates on your system. Android requires/plays-well with JDK 6 and you probably want to be running the latest version of Java for security purposes. Maintaining multiple JDKs have been nothing but troubling for me.
Especially since Google hasn't updated its Java language much lately. I think the solution for Google is to deprecate Java and start using Go. That would solve more than one problem for them.
There are a bunch of rumors that Google will announce expanded GoLang support on Android at IO. What that means I'm not sure and I can't find the link for it now. It was a somewhat credible source but not one I'd bet the farm on or anything. I suspect if anything is announced it would be GoLang ndk support but we can dream and hope for more. A python to Davlik compiler would be a very interesting move also.
I'm back to java after having an unsatisfying experience 2 years ago with Spring MVC, (this time i use the "play framework"), and it seems to confirm my intuition that the language itself is really just fine.
The problem lies more in bloated frameworks and corporate culture where everything needs to be standardized, regulated, and the purpose of a mandatory non-free training session.
Add to that the fact that every single topic is covered by at least 3 or 4 libraries, and you get a more complete view of the situation.
I kind of like that things are standardized/regulated in the Java space. If you're using anything close to industry standard tools and methodologies I can come in and be an effective member of your team faster. I know it can sometimes be more exciting to build something in a way no one else has ever built it before, but it's usually a bad business decision to do so.
This is one of the reasons why I still lament javascript. It seems like everyone and their mother is using a different framework to accomplish essentially the same task. The flavor of the week last exactly that long: a week.
How's Play! compare to Spring? I'm working on a bloated Spring whale (1.5M LoC, 485 Spring XML config files) and wondering if something like Play! can do it better, or if complexity is simply a beast that will inevitably turn any project into a turgid mass.
I ask since friends at Google will laugh at a bar if you even say "Spring," but I'm curious what else can do it all (Guice/Gin?). Perhaps nothing can and the trick is to simply have small, cohesive projects linked by common REST (et al) API's and to merely skirt complexity entirely. However, for workflow and state management, you'll inevitably need some common integration point.
I did a side project in Play! some time ago. While it was generally OK to use, Java in Play is definitely a second class citizen compared to Scala. Most documentation (which btw is sorely lacking) concerns how to do stuff with Scala and you'll have to figure out how to do the same in Java yourself.
Even worse, breaking backwards compatibility between even minor releases seems to be standard for this framework. So once you've finally managed to find some piece of documentation from some random source on the net (as again, the official documentation is pretty much a joke) you'll find that it doesn't work at all because it was written with Play! 2.0 in mind which is different from 2.1 which is different from 2.2 and so on.
Once you figure it out, it's a pretty nice framework. It's a shame so little attention seems to be paid to exposing that in a better fashion.
> Java in Play is definitely a second class citizen compared to Scala
Much agreed. I started a side project with a quick deadline with Java in Play and switched to Scala (even though I had to learn Scala) just because they played better together.
Play 1.2 is not-quite-as-supported as Play 2.x, but it doesn't have features that mostly make sense for Scala (e.g., text-based templates, not Scala-DSL ones)
I can strongly recommend Dropwizard for the plan. It is much less stuffy/enterprisy and you can easily split big apps into smaller services. It is some glue code on top of Jersey run in embedded mode Jetty (thus very little ops work needed).
Play Framework is also nice, but a bit too much opinionated! Meaning hard to make it do something in another way, which happens in real world big applications...
I've used Dropwizard but with my latest project I dropped it in favor of assembling libraries manually. There's nothing wrong with Dropwizard per se, it's biggest strength is that everything you need works out of the box, but it bundles some older versions of libraries (like jersey, jetty). I am now using latest Jersey, Jetty (embedded), Atmosphere, Ebean and RxJava with Kotlin. It wasn't that hard to setup everything manually and the benefit is that I can add anything I want. I work with Python and C# mostly and don't have that much experience with Java/JVM, but I really like this setup. I've also considered Play 2 with Java, but it didn't feel right to me and the documentation was out of date. Perhaps it's better with Scala, but I don't really want to learn an entire new language and ecosystem. Kotlin is similar to C# so for me it was a breeze to pick it up and I can transparently use any Java library with Kotlin by just importing it.
Jetty is up to date, but Jersey is old yes. But the new jersey is also a bit problematic, more stuffy and slow (from the benchmarks of others, I haven't done it myself). But the good thing is, there is a big and passionate contributor community around dropwizard (check their github/google groups) and this means if the new versions of libraries are worth updating, they get in pretty quickly.
Spring is a huge umbrella project that contains many parts, some good, some not so good. Guice or picocontainer work well, but you can achieve the same effect by using spring's Java configuration and avoiding silly things (AOP, shudder), and that way you can migrate existing spring XML piece by piece.
If you're writing an actual webapp (i.e. something that outputs html) then I highly recommend Wicket; it's the most beautiful framework I've ever used, in any language. If it's just REST APIs I can't really recommend anything - by the time I started writing those I'd switched to Scala (in which Spray is wonderful).
I'm with you that Spring has ALOT of parts. At my company they allowed us to use some parts of Spring and not others. Our stack was Spring MVC, with Apache Tiles, serving JSPs with some JQuery in there all wrapped up with Spring Security. It was much better than what we had before, JSF and ICEFaces and ADF. JSF frustrates me to no end.
Now we're moving towards a more modern stack. Using Jersey for REST is nice. It does make me enjoy Java again. You annotate resources in a Spring-like way, security was easy to implement. On the front-end we use a client side JavaScript Framework, JMVC (CanJS, EJS, etc). JMVC doesn't have as much traction as other frameworks, like Angular or Ember, but it is stable and covers what we need.
But when I go home, I try to stay away from Java. It's mostly Python (Flask, Tornado, Twisted) or lately some Node (Express) on the backend and Ember on the front. It's psychological. I program at work for work and at home to have fun. For me it just feels easier and more fun to stream code in Python.
For rest services in java I really recommend Dropwizard. Wraps a bunch of great libraries together with just enough glue to make your development easy. Really great support for metrics.
I while ago I had to choose a JVM based MVC framework to work with and originally I was looking at Spring. Needless to say it's a Mount Everest of frameworks, so by looking for alternatives I've stumbled upon Play. I decided to go the whole way and use Scala with it. Never looked back since. Typesafe stack offered me a rock solid Scala/Play/Akka/Slick stack with type safety, scalability, immutability, concurency that few others have (if any).
Modern Spring is quite nice, and after having tried Play, I go back to Spring MVC, but use Spring-Boot with Jetty was the embedded container.
Its much like Dropwizard, but better integrated with Spring if that is what you are used to or like.
No XML, and I can produce a usable web API with a minimal amount of boiler plate (its all wrapped up in Spring boot, much like Play wraps up a lot of stuff for you).
Yes, Spring Boot is pretty cool. Not a bit of xml in sight, unless you want it, of course. And you have the choice of deploying with an embedded Tomcat or as a more traditional war.
I think a lot of "big Java" haters haven't looked at Spring or JEE (which has seen similar massive improvements) in the last several years.
Not sure what version of Spring you are using, but the newer versions allow you to annotate your way out of the need to have so many XML files.
Code bloat is a different beast. Unless the company decides to refactor and redesign the whole thing, you probably have to live with it, like the rest of us.
Note that Play is only really comparable to Spring MVC, it's not a general-purpose dependency-injection framework. In the DI space Guice is more of a competitor to Spring.
Play is simpler compared to Spring but idiomatic Play code also requires you to learn reactive programming, something you probably won't do in Spring MVC.
I was just recently trying to decide between "new" Spring MVC, Dropwizard, and Play.
Spring now has a bunch of slick-looking guides and tutorials. But then I looked at the actual contents of their tutorial project, and it just turned me off. For an "example" REST project, they had over 50 classes not including tests: https://github.com/spring-guides/tut-rest/tree/master/6/comp... , with many being "event" classes of some sort. I mean, WTF, is this really the "idiomatic" way to build Spring REST/MVC projects nowadays? I'm trying Dropwizard for now.
Been there done that. 3.5 years of Play 1, but they decided to rewrite it in Scala and I left in anger.
Nearly one year now of servlet dev, trying nearly anything I can get my hands on. Most I have been satisfied with is Restlet for service development, otherwise nothing even comes close to Play 1.
Finally decided to harden up and learn Scala. I have set my prejudices aside and after a month, I can safely say I am a _write_only_ Scala developer. I still can't read much of the fancy code in the wild, but for my immediate needs, gluing java libraries together, it's a far superior language to Java.
My opinionated guide to developing modern Java is: get TypeSafe Activator and learn Scala.
I actually started learning Scala: completed Odersky's Coursera class and developed a Play 2 project in Scala. Overall I like it, but reading others' code is often frustrating, shorthand shortcuts in language are still kinda alien looking, and even figuring how to handle simple things like multi-file upload with Play's controllers, I feel I don't quite understand what the hell is going on underneath all that magical functional code that I myself wrote by assembling bits and pieces from elsewhere.
And then I watch stuff like Paul Phillips presentations [http://www.youtube.com/watch?v=4jh94gowim0] and I just don't know whether continuing to invest my time in Scala is a wise decision long-term.
I'll probably try Clojure at some point, but for production-grade projects I will do Java for now. I feel the most frustrating thing about tech is having to place bets constantly on what to invest your time learning. It's eerily similar to investing in stocks. You never know what's going to live or die. And I'm saying this as a former Delphi developer with multi-year experience. :)
I started Scala from cold as it were without having ever done Java. I found myself having to read Scala code (source for things like Lift) 'backwards' to understand it. I read the body of functions from top to bottom but lines from right to left as maps/flatmaps make much more sense to me when picked apart that way. Maybe this is common/standard, not sure.
I'm using Dropwizard and it was easy enough for me - former .NET developer to get things done quickly. That said if I was starting today long term project I would go with Dartlang (yes they'are server side as well)
I'm using Dropwizard for the same reason. It is dead simple and gets me going out of the box. You should also give Grails a try if you plan on having a view layer
Yes it is just a binding between Jersey and templating engines (they maintain two of them: mustache.java and freemarker. I strongly recommend freemarker, since it is more complete in UI related transformations. This way it lets your Model layer to stay clean. But if you need something exotic, you can bind to your templating engine of choice easily)
I think that to a certain extent, the standard library also encourages this culture, since that's the most prominent and arguably widely used piece of software that's written in Java and it will be used as an example of "good" code.
The continuing notion that CS classes teach objects first (I've heard recommendations that it be before even conditionals and loops, shockingly enough) I think is also a contributing factor: "When all you have are classes, everything turns into an object."
But as things like Java4K suggest, the bloat may not be inherent in the language itself; it's certainly possible to write concise, efficient Java code.
How ironic... I was an early adopter of Spring, when it was all about simple "enterprise development without J2EE". So, given enough time, does bloat follow success and does it become inevitable?
One of my opinions these days on javadoc is that you should be minimalist. Have nothing to say about the return type? Don't add @return. Same for @param. Just a sentence about the method/field/class? Just a single line /* * ... */ is fine. Have nothing of value to say on a method/field/class (e.g. a getter), don't add javadoc at all. I'm growing weary of large files with tons of redundant javadoc lines to make some checkstyle/pmd rule happy.
I always bristle when I see javadocs that include things like 'returns an object of [x] type that...' You're dealing with strong types, the signature provides all this information already. That, combined with good variable names, should do a lot of the documentation for you.
If you wanna document a method, document what problem it solves. Document any gotchas (or better yet, redesign them out o_~). Don't just repeat what reading the method's signature already tells me.
Thirded. At my last place of employment I actually made this into an informal[0] coding style rule and succeeded in getting a few people to remove the completely useless default javadoc template which Eclipse (and the like) have for new methods.
One thing I did find very important was to document if your method had any side effects that were not obvious from just its name. (E.g. if a method is called printXXX() or logXXX() you can pretty much guess what it's going to do, but saveXXX() is a little bit more ambiguous. Where is it going to save things? The database? The file system? Is it atomic? Etc.)
[0] I don't believe in formal coding styles (at least not for small teams/orgs) since what constitutes "best" practice is always context-dependent. We handled all knowledge transfer (including coding style) by intra-team code review and a few very high-level documents about the overall system architecture.
Yet, I'm always surprised in how good the official javadoc is at avoiding this problem. They always have a @return and it's usually saying something useful. I think there's two situations:
1) You're writing javadoc for something that isn't really a public facing api. In that case, I agree, remove the @return. Perhaps even remove that / * * and convert it to / *. It shouldn't be officially documented.
2) It is public facing api. It may seem that the @return is redundant, but there's really a better way to document it.
I do that a lot, or rather my commit messages are usually "mumble" or "fixed this" or "awookga". I feel this is more justified than the javadoc case because you can always just leave out javadoc, whereas the VCS forces me to put a commit message.
Just a humble suggestion, but perhaps you should enter a message which states the intent or the functionality of the change more explicitly. (If you're just doing a topic branch, then sure, just say "wip" or "blah", but please clean it up with "git rebase -i" before merging.)
Always topic branches yeah. My team puts that kind of information in the pull request, which ends up playing the role that a commit would in SVN or the like. I guess we could squash our merges to achieve the same effect, but we haven't felt the need yet - the pull request is a nicer interface than a git log.
Yes, even something trivial like "fixes whitespace" is better then nothing, but even better is squashing or amending a previous commit. Some systems prevent this...at my workplace once you've pushed to origin, there is no changing the past so saying something like "Added derp.java to fix broken build from <commit hash>" is very helpful.
I've been guilty of that kind of comments you despise when I had to work in environments where software "quality" metrics were applied to all checked in code as a part of build process and your code was marked as "low quality" because you missed @return document entry in your Javadoc. You can bet that, with few IDE templates to autogenerate all missing JavaDoc on save my metric was quite good. In addition to that, I completely stopped trying to write good docs. What you measure is what you get in the end.
Yes... mostly. I worked with a guy who, for every comment, asked "how can I eliminate the need for this comment?" Usually the answer is to name something better.
But sometimes you really need a comment, not because something is named badly, but because, even with the right name, there's something not obvious about it.
I'm a little skeptical of this. More like the developer in the future uses Gradle. Usually when I go to a project's home page, I see documentation on how to include the Maven dependency, not the Gradle dependency. It's pretty obvious how to convert one format to the other, but my point is I think most people are using Maven.
I'd say Gradle is the least awful of the 3 major build systems. Ant degrades into an unmaintainable mess as soon as any complexity enters the system. XML is a horrible scripting language, simple imperative constructs are very awkward (loops/variables/conditionals).
Maven also suffers from XML hell, but at least it has dependency management.
I've used gradle extensively and it is quite difficult to figure out what is going on. Using a debugger would be nice, but it simply doesn't work. Gradle is terribly slow on a big project, the update checks are the main culprit. They should be done automatically in the background to alleviate this pain.
Since gradle is compiled rather than interpreted, calling code in the project being built is difficult and convoluted. For example, if I want to call a DBUtil.cleanDB() method in my java code I can't reference DBUtil in my gradle script as it hasn't been built yet and the Gradle script won't compile. If gradle was interpreted this problem wouldn't exist....
I find the DSL unintuitive and the inability to specify the order of tasks execution is always a sore point.
On the positive, at least it's a language, not XML. I have never understood the java world's obsession with XML and forcing it in directions never intended. This XML obsession has led to java being a major laggard in automation tech. Java devs do many things manually that a Ruby/Python dev would be horrified at....
After doing couple of Android projects with Gradle I've felt like Maven is a godsend.
It might require writing some XML to declare what your project does, but at least it WORKS and at least it does not waste my time by forcing me to write code to include pieces of projects and properly process project (e.g. including native code, Robolectric testing, renderscript and some other things).
Also any compilation inside IDE's was orders of magnitude faster with Mvn than with Gradle... all in all setting up all the components with gradle took about 2-3x as much time. Mostly it seems like someone decided that because now you have code instead of XML for build configuration, they'll just skip most of the plugin design and force you to roll half of the build process on your own.
Right now (at least for Android), Gradle is a colossal waste of time due to lacking features, extremely slow execution and myriad of bugs which will eat away productive time on project.
> Right now (at least for Android), Gradle is a colossal waste of time due to lacking features, extremely slow execution and myriad of bugs which will eat away productive time on project
Are the sparse features, slow executes, and bugginess due to Gradle or due to the scripting language it uses? www.gradle.org/overview says they will happily support any community effort to create additional build script engines for Gradle. The Gradle developers had better do it themselves because after the Groovy++ fiasco, noone's going to put work into building something related to the Groovy ecosystem when it's likely to be skuttled and/or stolen later on.
Yesterday's Who is hiring? (https://news.ycombinator.com/item?id=7679431) only had 1 mention of Groovy or Grails (and none of Gradle) out of over 400 comments. And many (most?) of the projects tagged Groovy on Github are triggered by a single Gradle build script for a project that uses some other language. These Gradle build scripts are often 30 lines long.
So I'm not sure how Groovy will fare in the future. Nothing seems to be taking its place, though, for testing and general manipulation of Java classes. Java and Scala are statically-compiled languages for building things, whereas dynamic Clojure seems to also be used for systems programming rather than scripting. I'm guessing Oracle will heavily promote Nashorn for scripting and JavaFX, but Javascript syntax doesn't seem quite as full-featured as Groovy for now.
Back in 2009 there was a big Grails wave here in Germany. Many JUGs had Groovy and Grails talks.
There was also some people trying to use Groovy with JSF. Myself I attended a session promoted by Sun hitting at possible official support after the JSF 2.0 release.
To the point we added support to it in our in-house JSF framework SDK, still JSF 1.x based.
Since late 2010 I have been doing .NET land mostly and now back on Java land, I hardly see any Groovy besides Gradle.
I think it's just mostly the fact that tools aren't complete: e.g. IDEs will parse Maven pom.xml and use internal builders to speed up compilation while when using Gradle you're always spawning the external builder.
Same goes with other things: we had to write Groovy code to handle build cases which Maven plugins handle by default. That's mostly an ecosystem issue.
for normal dependency management you shouldn't need to write code. I've never done any android dev, so I can't comment on that. declaring a dependency is literally like this:
But I am not going to be the great gradle defender :) I have many complaints..... I would have much preferred that Rake became the default build system for java. Sadly that approach never took off....
Yeah, for normal dependencies that's true. But on Android you quickly get some additional things that have to be handled by the build system:
* Code generation from annotations (reflection on Android is slow, so doing code generation is way better)
* Attaching native .so libraries in proper directories of APK (Maven plugin does that automatically, Gradle needed writing code for that to work)
* Properly handling RenderScript backwards compatibility library (there was no Gradle support for that at all)
* Testing - Robolectric is still not supported which throws a wrench into whole Jenkins/TeamCity autotest stack and needs fiddling with emulators
> Maven also suffers from XML hell, but at least it has dependency management.
I don't find it that bad. The nice thing about it is how my IDE will auto complete almost everything and it should be possible to validate it without even using an IDE, as it has a schema. I agree with your complaints about Ant.
The thing I was hoping gradle would give me is the ability to write tests for my build. EG: I want to have more confidence that my maven filtering is working the way I want it to. But it sounds like gradle isn't built with that in mind.
Considering that groovy is dynamically typed, if my IDE doesn't auto complete (maybe it does) I think it's possible to make the argument that Maven is the least awful of the 3. At least the maven XML has a schema. I don't need yet another way to make a mistake in my build script (ie: typing issues).
> Java devs do many things manually that a Ruby/Python dev would be horrified at....
w/ regards to gradle using groovy.... in gradle I can easily add in variables to my dependencies, I can write conditionals (if System Prop X then include dependency Y).
Basically anything you can do in code, you can do in gradle very easily.
Auto-complete does work in IntelliJ 13 - at least for groovy code type stuff. Nothing for the gradle DSL (that could be implemented of course).
> Java devs do many things manually that a Ruby/Python dev would be horrified at....
Jenkins config - almost every one does this by hand. Jenkins jobs weren't really even designed to be automated (ironic, eh), you have to build a full xml doc for each job rather than say apply a similar change across all jobs (add in a -D param across all jobs for example). I know this is a Jenkins specific issue, but this mentality is very common in java land.
Others: have every dev manually install a database for their environment (Chef/Puppet/Ansible solve this - and what are they written in? Ruby/Python)
No one would ever use java for any scripting type work, the JVM startup time is awful + the file/string libs are far less powerful/usable than ruby/python.
Of course a java dev can learn one of the scripting langs, but they typically don't.
this is just my experience, but note I've seen a lot of shops...
Writing tests for your build script is an interesting idea. I wonder if this would be easy to do in something like SBT where the build definition is itself an SBT project.
Actually, Maven uses XML right - as configuration, not code. This is where Ant was terrible - you ended up writing imperative code with XML statements.
Declarative builds = intelligent tooling. Would json make it better? I hate editing json too. Personally I would go with toml but wait... that would look similar to something else...
Ant's real problem is that it never found a path towards next generation. Why isn't ivy included by default? I want something bigger and easier to use that isnt gradle or maven but is more along the lines of an Ant+ivy default. It should have a bootstrap script, it should understand default project directories... It should continue to be declarative, but it should have an xsd or similar descriptive format that can be used for tooling.
There is a future in the ant+ivy perspective that I don't see in other build tools.
I wonder if anyone said this about HTML when javascript was introduced?
once a system starts getting complicated you inevitably need code.
two points:
* gradle builds can be completely declarative. you write code only if you need it
* builds also are often used for very specific automation. in ant, you end up having to write custom ant tasks. this is fairly painful compared to just creating new classes, tasks, or scripts directly in gradle.
Specifying the dependency in Maven XML has become sort of a standard that even Gradle people use. Obviously, Maven has been around much, much longer, and a lot more people are still using it, but more and more are switching to Gradle. At the very least Gradle has come to a point that you don't have to worry about it not being maintained, or that there won't be people to ask if you've got a question.
There are no winners in the build war despite the overwhelming online support for Gradle. Personally I'm not a fan of it. I find it on the slow side even compared to maven. I'd rather have declarative builds like Ant but therefore support better tooling than super freeform tools like Gradle that force you to drop into a language with about as much type safety as Javascript. Multi-project builds are also annoying, as Gradle has to parse and validate all the connected projects before proceeding with one single task on the build you're invoking due to its design. Very annoying stuff.
The performance problems are definitely the most annoying part of using Gradle. The Gradle daemon helped a little but tended to break other things and Gradle was still pretty slow.
If you are looking for something faster and more declarative, you may want to check out SBT[0]. It is way faster than any of the other JVM build tools. Also, in the future[1] it should have much better tooling support than anything else on the JVM.
Right now, SBT + IDEA is a bit of a pain because they share the same target folder and IDEA sometimes overwrites/deletes .class files that your application (started via sbt run) hasn't loaded yet. Usually that leads to a few ClassDefNotFound errors and such. Hopefully that'll go away once we have a single SBT instance.
My two wishes for SBT would be: 1) A monadic style for .scala build files. It would make dealing with the immutable bits of project definitions so much more pleasant and we could avoid the weird semi-Scala syntax of .sbt files. And 2) A bottom-up approach similar to Pants. My team frequently end up getting a lot more project interdependencies than we bargain for simply because it's too easy to induce transitive dependencies.
Thank you, I haven't actually tried that. I really live the "I just want my IDE to work" philosophy (out of laziness), so I try to avoid configuration if I can. :)
About monadic style: I realize that it's a hard sell, but it's basically about leveraging for comprehensions (aka. do-notation) to specify your build. Shake is an example of this, although probably not particularly suited to building Scala code.
I've never had to change anything between upgrades (aside from changing deprecated stuff). Are you referring to the jump between from 0.7 to 0.10 a few years ago or have you had more recent issues?
Yeah, I just went and had a look at the project in question and I'm being unfair to SBT, it was a plugin I use to package WARs that changed underneath me. The plugin was quite closely coupled to the version of SBT, but the latest variant of it (once I found out about the migration to a different artefact) seems good.
It's interesting. Ant is a somewhat constrained imperative language. Gradle is a highly constrained declarative language built on top of, and with an escape hatch to, a completely unconstrained imperative language.
If you stay within the bounds of that the Gradle DSL can do, rather than throwing Groovy around (which is possible - i write a lot of Gradle, and very rarely write raw Groovy), then Gradle is rather nice and easy to reason about. But if you don't, well, you're going to have a bad time.
I've definitely found gradle to be faster than maven, particularly using the daemon, and even more so considering the extensive support for understanding when a task is up-to-date. I haven't run a clean task in gradle in several months, but in maven it seemed to be a crapshoot if the clean was required or not. That saves a lot of time.
Gradle is mainly being pushed by Grails and Android development.
I don't know of any other project using it. We are always doing Maven or Ant.
If Gradle is the future I hope it gets improved, I gave up on Android Studio given its dependency on Gradle and how it drags my dual core with 8 GB to its knees when compiling.
> I gave up on Android Studio given its dependency on Gradle and how it drags my dual core with 8 GB to its knees when compiling
That could be the slow, dynamically-typed Groovy in Gradle that's dragging your machine. Gradle needs to bundle another build language. Since the goal of statically-typed (and hence speedier) Kotlin is to make it easier to write IntelliJ IDEA [1], on which Android Studio is built, instead of using Java, the logical choice is Kotlin.
Gradle's developer says they'll happily support any community effort to create additional build script engines other than Groovy, but it isn't a priority for them right now [2]. Perhaps the Kotlin team need to kick off a Kotlin build engine for Gradle (though because one of the Kotlin developers was a victim of the Groovy++ fiasco, I'd understand if the Kotlin people are hesitant about having anything more to do with Groovy ecosystem software like Gradle).
Kotlin was exactly the reason I was thinking to move from Eclipse ADT to Android Studio.
So far I have been using the Eclipse ADT/CDT for my hobby development, mainly with C++ (just graphics stuff).
Then I thought to try out Kotlin instead, but could not. It was worse than waiting for my NDK C++ builds to finish, with the whole computer at 100% CPU usage.
I ended up filing a ticket, like many other developers already did.
Is Grails really pushing Gradle adoption? My experience has always been that the integration between the two is pretty bad. Are things better now that they finally... released a real Gradle plugin to support Grails 2?
Personal anecdote, I stopped trying to develop for MC Forge in version 1.7 because the gradle build they switched to was unbelievably slow and difficult to use. After several days of poking it, I still couldn't understand why asking gradle for a simple list of available tasks was taking >10 seconds, and when I tried to give my workspace to a friend on another computer, I discovered I had totally I failed to get a list of coherent commands that I was 100% sure could reproduce my workspace on a new machine, because of large amounts of scattered hidden state I had failed to detect. Part of this might be poor build config design, but gradle certainly helped enable a lot of poor behavior and certainly doesn't impress me with its performance for trivial tasks.
You should be skeptical. Many Android projects don't use Gradle. Gradle itself might be stable but Gradle issues are at the top of every single Android Studio release notes.
When that stops happening I'll start thinking about Gradle.
The title did warn that it is an opinionated guide.
I think most projects that used Maven before Gradle don't have enough incentive to migrate. A lot of the new projects, however, start out with gradle: Vert.x, Crate.io, RxJava.
This. I can't see myself using Gradle any time soon. Literally everything I've touched is maven only and I don't want to learn another DSL on top of yet another language.
The #1 thing you need to make Java usable is to abandon the JavaBean conventions. When every field requires 8 lines of boilerplate it's no wonder the code looks ugly (YAGNI, and if you do need it it's two keystrokes in your IDE to "encapsulate field"). public final fields are fine, and can get your data classes something close to readable.
I'd stick with maven for the build rather than Gradle; it's completely declarative and all the tools understand it. Learning a new language just to configure your build tool seems excessive.
For starters, you can see Groovy as "Java without semicolons". I went from Maven to Gradle and never looked back. It's superior in most ways. The tooling could be better though.
Only a very small subset of Groovy is used by the typical Gradle build script, the very subset of Groovy that's least like Java. What part of this build script from the linked article bears any resemblance to Java?...
apply plugin: 'java'
apply plugin: 'application'
sourceCompatibility = '1.8'
mainClassName = 'jmodern.Main'
repositories {
mavenCentral()
}
dependencies {
compile 'com.google.guava:guava:17.0'
testCompile 'junit:junit:4.11' // A dependency for a test framework.
}
run {
systemProperty 'jmodern.name', 'Jack'
}
javadoc.options {
docletpath = configurations.markdownDoclet.files.asType(List) // gradle should relly make this simpler
doclet = "ch.raffael.doclets.pegdown.PegdownDoclet"
addStringOption("parse-timeout", "10")
}
run {
jvmArgs "-javaagent:${configurations.quasar.iterator().next()}" // gradle should make this simpler, too
}
I understood the post I replied to as if the author wanted to configure something custom and thus needs to write code. I didn't assume that the original argument was supposed to address the configuration of a standard build. Because you'll always have to learn a new syntax for the tool. Use Make-> Learn make syntax. Use Maven-> Learn POM syntax. Use Gradle -> learn the DSL syntax. Want to extend Gradle -> learn Groovy, a "superset" of Java.
Modern Java is usually 100% XML free. Even new servlet containers/standeard REST frameworks (Dropwizarrd, embedded Jetty etc.) require no XML whatsoever.
You only need XML if you're deploying to heavyweight servlet containers (standalone Tomcat, e.g.). Even embedded Tomcat doesn't use XML.
That's not what I wanted to point out. To write a POM, you don't need to know the XML specification. If you want to write a Gradle script, you don't have to know Groovy. You just have to use the Gradle DSL which is fairly compact for most plugins. You make it sound as if you have to learn a whole new programming language, and if that was the case I would agree that Gradle sucks! If you want to do something more specific, then yes you will have to learn Groovy, but at that point the time will be spent well. Also, most of the time Groovy is weakly typed Java with lambdas and no semicolons. I think you've already spent more time arguing about not wanting to learn Groovy than time you would've needed to learn said amount of Groovy.
Maybe you can write it, if it's a solo project with a fairly vanilla build. But as soon as you have to collaborate with other people, or read examples from the internet, you're going to run into full-on Groovy; "the Gradle DSL" is not well-defined, so while most bloggers will claim they're writing idiomatic Gradle, they'll all have different subsets of Groovy in mind when they say that.
By contrast Maven has a very rigid format - there's no risk of randomly seeing a lambda or conditional expression in the middle of the XML - and its plugin model ensures that there's a very clear delineation between what's standard and what's an extension.
The "Gradle DSL" and Groovy's grammar are the same thing, mixed together in one Antlr file, and probably the largest programming language grammar I've ever seen. Here it is for Groovy 1.8, the version that shipped the paren-less parameters that Gradle uses:
> For starters, you can see Groovy as "Java without semicolons"
Not if you have to read other people's code, or understand examples you find on the internet.
> I went from Maven to Gradle and never looked back. It's superior in most ways.
What's it better at? I want my build tool to be simple; maven compiles my source and does my releases, and the main thing I have to configure is just a list of dependencies (in an admittedly verbose format). I'm actually a scala programmer, but I use maven rather than SBT because it seems to me that having lots of logic in the build system could only lead to bad things. So what are the things you see it helping with?
See my reply to vorg regarding Groovy. As a developer the argument "I don't want to learn something new" is invalid.
Gradle offers the declarative nature of Maven without pushing it down your throat. You don't have to write a plugin for something that can be expressed in 3 lines of Groovy (but you can, if you want to!). Instead of adapting your build to Gradle, Gradle adapts to your needs. That's often a point of criticism from Maven users, because every Gradle build looks different. But that's the point: Everyones needs are different. Of course that only applies if your build is beyond the standard compile/test/release configuration. A simple configuration looks pretty much like a Maven POM (minus the tag soup).
I'm aware that Groovy now supports optional typing but if I'm going this path, I prefer to switch to Kotlin, which I describe as "Java with everything that's bad removed".
If that's what you want wouldn't Ceylon be a better choice? If you're still using the Java standard library you still have the billion dollar mistake (null) everywhere.
Until you have to debug it. At which point you realise you're now writing what's effectively a different language with its own tooling and compilation (and its own bugs), and if you were going to do that then you might as well go all the way to Scala where you get much more in return.
I used Project Lombok back in the days to get read of Javabeans boilerplate. Just declare your private fields and put @Data annotation on class, and it would generate at compile time all your getters, setters, equals, toString, constructor and hashCode methods. Really helps to keep the code lean and small. Don't know does it work with Java 8 though or it didn't yet catch up.
Couldn't agree more. Use public, protected, private fields as they were meant to be used. I only dip into JavaBean anymore if I need a readable but non-writable field.
For immutable you can just use public final fields. I assume GP must be talking about fields that are mutated but only by the object itself, where outside code needs to be able to read but not write.
The bean convention doesn't help you with that one though; if you have private Date date; public Date getDate() {return date;} then people can still do getDate().setTime(1);
Yep, the thing is that Date is immutable.
I think that this public final immutable rule is ok, but one has to ensure the fields themself are really not modifiable.
Couldn't agree more.. But this comes with the most cliche discussion with a smartass looking at your code. Dude, I know what getters and setters are, I just don't agree
I'm using Java for the first time because of Android. I had played with Java when it first came out but have stayed with C/C++/C# for almost everything.
I have to say that my Java experience isn't as unpleasant as I thought it would be. I always thought C# is what Java should have been but after learning a little idiomatic Java the reality is quite okay, really.
The way you phrased that sounds to me like you've been programming for a significant amount of time. If that is the case, the Java of today offers so much that a younger Java did not, and I suspect you would have had a more unpleasant with the java of 10 years ago.
Anyone looking at where "enterprise" Java went - the whole J2EE monstrosity - would have run screaming. But the basic language is actually quite good and has been for a long time.
That pluggable type system looks amazing. One thing that's weird to me is how java included a new Optional type (seems similar to Haskell's Maybe), but the compiler (afaik) doesn't prevent you from setting an Optional field to null. Something about that doesn't feel right. (Side Note: Optional isn't serializeable. Also... what's the best practice for using Optional when I'm using JPA? Can it be used in my Entities?)
I believe Jetbrains/Intellij-IDEA has created annotations for @NotNull/@Nullable, but afaik these just create warnings in the IDE. Maybe you can configure IDEA to mark these as compiler errors, but I don't know if my peers using netbeans/sublime/whatever would be able to notice when they write code that IDEA will refuse to compile.
The main issue with non-nullable types in OOP, in my mind, seems to be defaults. Quite simply, when you don't initialize an primitive, you get a 0, and when you don't initialize an object, you get a null. Not all fields must be initialized by the time the constructor ends, so some kind of valid default exists.
Enforcing non-nullability would involve somehow enforcing that the variable is always valid before use some other way, like how "final" is enforced in the constructor, but it should be possible.
Unless you make it default, though, it won't be as "elegant" as the haskell Maybe, and doing so would net you a very very different language.
There are a number of implementations of JSR 305 (https://jcp.org/en/jsr/detail?id=305). Findbugs is one that provides the annotations. You can include the annotations JAR file on your compile path and then use findbugs in your build to enforce them. IntelliJ will still recognize them and flag the warnings/errors.
It's certainly a bit strange, but it's how Scala works as well. I wonder if it's for backwards compatibility reasons, given that everything is nullable already. Have to give it more thought though.
// The type of 'unsafe' is Option[String]
var unsafe = Option("some string")
unsafe = null
unsafe map println
gives
Exception in thread "main" scala.MatchError: null
effectively a NullPointerException. This would be impossible for a true Option (aka Maybe) type. The problem is introduced because Scala, for backwards compatibility reasons, still allows the assignment of null; this lowers the usefulness of pattern matching against Option types.
--
edit: you could object to my use of var (and you should). Ok, let's re-write it to be a val:
def unsafeFunction(x: Option[String]): Option[String] = {
x orElse null
}
...
val unsafe = unsafeFunction(None)
unsafe map println
...and I still get the NPE. Note that in this case you can easily see how I introduced the problem, but the point is that the signature for unsafeFunction should guarantee null is not a possible return value.
// The type of 'unsafe' is Option[String]
var unsafe = Option("some string")
unsafe = null
unsafe map println
Is complete contrived nonsense, var? Seriously, quit trolling, in Scala (immutable) val is king.
Next:
def unsafeFunction(x: Option[String]): Option[String] = {
x orElse null
}
Oh yeah, that's brilliant, let's just try our hardest to come up with scenarios that never occur in the "real" world (unless we try really hard to create nullthing out of nonething).
I'm not trolling. I genuinely want to like Scala, which is why I'm disappointed by some of its design choices.
Yes, in Scala val should be king (unfortunately, it's not -- if you've taken the two Coursera courses by Odersky you'll see some use of var in the exercises, refuting your claim). But it's true val is more common, and the use of var was accidental to my point anyway (mutation wasn't the issue), hence my clarification and second example. Yes, it's pretty obvious where I introduced the mistake, I said as much. In the real world, the mistake might be harder to spot, which is why the type system shouldn't allow it.
If I understand your position correctly, it seems to boil down to "programmers will code correctly, therefore this static check (that Option must not be null) isn't needed". Which is pretty much what dynamic typing proponents have been saying all along. A pretty untenable position if you want to stay on the side of Scala...
I'd much prefer if Option were more like Haskell's Mabye, but then again, I side with static typing. I understand why, given Scala's requirements, this wasn't possible. It's just disappointing.
There's no need to be disappointed in Scala's Option, if used sensibly (i.e. not intentionally trying to break it) Option will work as advertised.
val is indeed king, var is used sparingly, look under the hood of any prominent Scala library and you'll see val-ue of immutability put into practice. Locally scoped vars can be useful, but beyond that dangers waits (not unlike Haskell's unsafePerformIO).
In terms of disappointment, I could say similar things about Haskell: I'm deeply disappointed with the eternal compile times, meaningless stack traces (no line number, heh, nice), non-existent tooling (read: null IDE), etc.
Scala lives on the JVM and has seemless interop with Java; concessions have been made, the type system will never rival that of Haskell, but then again, outside of Haskell no other mainstream language's type system rivals that of Scala.
Fair enough. I don't believe Option is only broken when "intentionally trying to break it". Of course, my example is trivial and the null is explicit. But what if it was a call to a Java method that shouldn't return null, but does because of programmer carelessness?
I agree there are pain points with Haskell as well, no language is perfect. But slow compilation... surely you're kidding when you don't see this as a problem with Scala? The compiler is SLOW. And as for IDEs, which one do you recommend? I heard good things about IntelliJ, but please don't recommend Scala IDE because to say it's inadequate would be a huge understatement. I've cursed too many times with its phantom compilation errors.
When calling a Java method assume a null return and wrap it up in an Option just as you'd do with Haskell when interfacing with the "outside" world.
As for Scala compilation speed, Haskell's not gonna win that battle, ghc is to scalac as scalac is to javac, which is to say, the last is first and the first is last in terms of compilation speed. Also, IIRC only Yesod provides incremental builds, no? With SBT incremental builds most code changes incur a < 1 second recompilation hit.
As for the IDE story, the secret to a performant Scala IDE is to turn off automatic builds in Eclipse and let SBT run the show. With the SBT eclipse plugin there's a setting that allows SBT compilation target and Eclipse target to be shared so you never have to clean/build in Eclipse -- this is a huge win, the difference between standard dog slow Eclipse performance, and snappy, oh this is real nice if only the haters knew, joy ;-)
Exactly, that was my complaint. It makes elegant pattern matching against Option types (the whole point of using them, in fact) less than useful. Now, in Scala-land, you have to check that they aren't null, which sucks.
Can you elaborate? The whole point of Option types is that I can map (for example) over them without explicitly checking what their value is, and it will work without a runtime error. Same with pattern matching.
With the introduction of null, this is no longer possible. I've just shown an example of getting an NPE while mapping over an Option[String]. Now we're back in Java-land, where I must explicitly check for nulls, read the source code of every method or trust some comment that tells me that it will never return null. (Ok, not exactly like Java-land: a Scala programmer who returns a null for a function with type Option is very inexperienced or is doing something naughty. But why does the language even allow it?)
Aside from telling me I'm wrong, can you explain why?
Scala needed to support null somehow in order to interoperate with arbitrary Java code, such as passing null as a parameter to a third-party Java library. So at least some variables should be allowed to have null. Maybe they couldn’t think of a way to prevent Option-typed variables from being null without preventing arbitrary Java interop. Making only Option types reject nulls might have been thought too hacky.
Those are just my guesses of the design rationale, working from the fact that Scala does support nulls. But perhaps Scala could have come up with a better solution that still allows null use when necessary. If you think of some syntax and elegant semantics for allowing you to forget about null for most code, I’d be interested to see your proposal.
Oh, I understand why null was needed (backwards compatibility, like you said), and I'm no language designer, so I don't know what I would have done instead. Maybe mark pieces of code that must interact with Java code with "unsafe" blocks, outside of which no nulls can escape?
unsafe {
...
}
Don't know if this would work. I'm just disappointed because this slightly breaks the Option type, that's all.
> I'm just disappointed because this slightly breaks the Option type, that's all.
I have never ever seen this happening.
The complaint feels a lot like "well, someone could use reflection and change the cached values of Integer, why don't you check that every time something returns an Integer?" to me.
null is the sad fact of running on the JVM, but pretending that it doesn't exist works 99.9999% of the time in Scala.
I know I'm beginning to sound like a broken record, but "I have never seen this happening" is a poor argument when discussing type systems. Please realize that "I've never seen a type bug like this happen" is exactly what proponents of dynamic typing will say when dismissing the burden of static typing: "I've never seen a bug caused by incorrect types. It sounds nice in theory and in your contrived examples, but in practice type errors never happen to me, therefore I don't want a type system that gets in the way."
The fact is that type system should NOT allow an Option val to be null. That's what type systems are there for. If a Scala programmer coming from a Java background wants to use null in Scala programs, the compiler will happily allow it. This is awful practice in Scala, of course, but it's allowed without warning. I've seen this happen with amateur Scala devs (and I'm ready to admit I'm an amateur with Scala too, I don't want to sound condescending).
Your remark that "null is the sad fact of running on the JVM" was what I was saying all along. Am I allowed to express disappointment that Scala's type system is compromised because of this fact?
> Your remark that "null is the sad fact of running on the JVM" was what I was saying all along. Am I allowed to express disappointment that Scala's type system is compromised because of this fact?
What I'm saying is that you are barking up the wrong tree. You need to go to Oracle and complain there if you are unhappy about nulls.
I agree that the design is a result of trading off the desire to do away with nulls vs retaining Java interoperability. Preventing (at compile time) only Options from being null is surely impossible when casting/reflection are available.
It is commonly understood that if an API returns Option[A] then the client can assume it will not return null. Personally I have never experienced a real error from this.
A lot of people love to hate on Java, but it's a surprisingly dynamic language and there is a ton of great testing, networking, and many other libraries available.
One of the things I appreciate about Java is the ability to take large teams and just have their stuff work together, without having unhuman discipline around super subtle rules (eg: C++)
Contrary to popular belief Java is highly dynamic. You can introspect the fields, methods, interfaces of any object at runtime, inject new / redefine classes, methods, fields, etc. The problem is that it's very awkward and unwieldy to do so. Hence the tendency to build new JVM languages rather than attempt to use Java's dynamic features directly.
I think "dynamic platform" would be more accurate. Java has typically been a fairly conservative language sat on a much more interesting VM, a VM which has rather more features in common with dynamic languages like Smalltalk than you'd expect.
Exactly. I'd argue C++ has a lot going for it, and I think the claim that Java's performance is only slightly slower is simply not true for the vast majority of situations where good memory organization can provide significant speedups - which includes any computer graphics, vision or audio application.
I personally find C++11 more high-level than Java and significantly more optimizable for performance.
You can wax poetic about "developer time is more important than processor time" all you like, but when your application runs like a turtle on anything short of server-class hardware, it doesn't mean much.
Performance will always be of primary importance for a large class of applications. For the rest, Java is a good alternative.
Java is fast enough now to compete with C++ in some categories of software traditionally viewed as "high performance" e.g. web-servers or database systems. Applications running like "turtle on anything short of server-class hardware" is a result of bad-coding, not Java itself.
In many others, especially those requiring vector or matrix arithmetic (medical imaging, physical simulations, modeling, graphics, scientific computing, video games), there's simply no competition.
Not sure of that. Some scientists from CERN would certainly disagree... Pure array-based arithmetic in Java is pretty damn fast, especially if you care to avoid dynamic allocations. It can be also very memory/cache friendly.
They do have quite a few projects in Java and they published some of their Java scientific libraries as open source. See Colt project. Also the software processing data from LHC is at least partially Java based.
10 millions element array of doubles/ints/bytes takes almost exactly same amount of bytes in Java as in C++. Java can blow your memory if you do stupid things like wrapping every point 2D into a separate object, but you know, good Java programmers know this. Other than that, its memory usage is quite reasonable, including some room for GC (typically 20-30% of total is enough).
You still have to read Effective C++ to avoid shooting yourself in the foot, but after that C++ isn't much more difficult than Java or C#. The compile times remain annoying, though.
> C++11/14 is in practice not that much more difficult to write well than Java. It's not 1998 anymore.
While I agree with you and C++ belongs to my favorite languages, the truth is that most corporations still use C++98/C++03 and they aren't going to improve their compilers any time soon.
On our Java projects we still get requests for Java 1.4.
Its having the knowledge of what subset of features do you stick too, because C++ is quite large feature rich language. There are often many ways of doings things.
One of the reasons I love programming in Python so much is the focus on idiomatic code and 'one obvious way to do something' means that unfamiliar codebases or APIs are easier to read, and patterns for common tasks are seen again and again.
I love Java, especially Java 8. But as the article points out, what frustrates me is threading. You can't do much without quickly running into threading issues. I played audio files in a game I made and it created up to 2,000 threads and crashed. Once I wrapped audio in an explicitly created thread this issue magically went away. Any kind of UI, timers, file I/O and network activity also involves threads.
The really horrible thing about these threads in Java is how hard it is to not share memory across them, because if you do terrible things happen. In other platforms you don't have to involve threads unless you want to, and you definitely aren't boxed into a situation where it becomes easy to accidentally share memory across theads.
I like Go's way of handling this. node.js is single threaded but the event loop makes it possible to do non-blocking IO without crazy Jave thread issues. Using synchronized, atomic properties and locks is not the right way to do these things as your code gets really complicated when trying to do basic things.
That gets me to my other pet peeve with Java. Just how much boiler plate there is to do basic things like opening up encrypted TLS TCP connections. Tons of cruft.
Anyway, having said that, I love Java and use it, but these things need addressing. I like Scala's Akka, I hope Java comes around and improves the horrible thread situation. I will have to check out Quasar. I know I just need to become more familiar with threading in Java in general. I'm actually pretty new to Java.
Sounds like it's the implementation of the audio library using thread in the wrong way. Has nothing to do with threading in Java. Nodes could have the problem of starving the audio playback if other parts of your code hogging too long of processing time. It's just shifting the problem around.
What's great about java is the number of libs out there for this. You don't have to use native java threads in this day and age with things like akka out there.
I find akka's java interface amazing to work with (yeah it's a bit odd in some parts)
You could also get used to thread pools and executors.
There is nothing wrong with Java Threads, it gives you low-level access which can be complicated and cumbersome but, when mastered, can be powerful. I believe that Akka uses Java Threads underneath the covers.
Using synchronized, atomic properties and locks is not the right way to do these things as your code gets really complicated when trying to do basic things.
One point being made in the op is that you don't have to. Of course, you may be constrained by how the libraries you want to use are structured, but I don't think this is necessarily the case. What if you used the op author's actor framework?
> basic things like opening up encrypted TLS TCP connections
IIRC that's sort of a special-case: It's painful because the designers wanted to weave-in policies and integration with sys-admin stuff on the host OS. There's an impedance mismatch between how Enterprise IT wants to handle that versus what a lone-developer would like to create.
There's plenty of stuff like this, though, in the JDK and in third-party libraries. Think about how much effort it takes to read the contents of a file into a string!
I don't think this is a fatal flaw, just a reflection of the attitudes and priorities the founders of Java. Concision for small tasks just wasn't seen as important. I don't think it was until the generation of scripting languages like Python and Ruby (and that other one, the moustache guy's one) came along that benefits of having a comfortable raft of easy ways to do small things became clear.
Java is far and away my favourite language, but even i'm embarrassed that it took until Java 7 to get a standard way to compare two possibly null variables for equality.
Go makes it even harder not to share mutable memory, as it has no 'final'. But if you read the whole article you'll see that Java now has lightweight threads with cheap blocking - just like Go or Erlang.
Good article, lots of opinions but the title forewarns. For me, Eclipse is still very good and if anything, more stable than in earlier years. I've tried NetBeans and the free IntelliJ but though those are fine, Eclipse is better for me. The real trick is to _not_ store your code in the workspace (which is ironically where the project wizards default to unless you change it). Store your code in as an example, svn for Subversion, git for Git, etc. Use the workspace as just a shell to manage Eclipse preferences and such.
I finally switched off of eclipse for intellij. It's light years ahead of eclipse in terms of speed and response times.
One of the things I liked was how easy it made things by allowing eclipse keybindings to be used. Ever since I enabled those, things have worked exactly the way I would expect.
I also like the work flow with git. A common example I like is the prompt for adding files to your repo automatically upon creation, this way I don't have to think too much about it.
As an eclipse user this suggestion intrigues me, but I'm not sure what the workflow would actually look like. Do you have a pointer to an article or something? Thanks.
Sorry no link, co-workers and as "smrtinsert" said, Git or for me having both Git and Subversion projects makes life easier keeping source separate from the workspace.
Nope, never used that. For Git it's straightforward, I have one Git repo per project I manage with Git. just use Import Project. The code remains where it is at.
For SVN, I use Checkout and uncheck "Use default workspace location" and specify the location of the code.
I do this, or have started to since I've been using git more. I also do it with large projects. Only my truly disposable projects are in the workspace.
The biggest take I have from this post is that apparently they have created go-like lightweight threads for the JVM with Quasar (http://docs.paralleluniverse.co/quasar/) which is really interesting.
If I understand correctly, Quasar uses bytecode instrumentation to enable user-mode threads for the JVM, and they claim they did benchmarks that show X6 to X12 better performance than native JVM threads: http://blog.paralleluniverse.co/2014/02/06/fibers-threads-st...
This is really something that caught my attention.
Something that really resonates with me from the linked PDF ("Blue-collar language") published in 1997:
> What I found most interesting in watching people use Java was that they used it in a way similar to rapid prototyping languages. They just whacked something together. I was initially surprised by that, because Java is a very strongly typed system, and dynamic typing is often considered one of the real requirements of a rapid prototyping environment. [...] you find out fast when something goes wrong.
Despite working in JS and Python, sometimes I feel more comfortable hacking something up in Java, because every missing method or undefined variable is an unavoidable short-term TODO.
I appreciate the modern Java style espoused here, it's much further away from the horrible overdesigned & pointless configuration style I often see with Java.
However, the author doesn't really understand why C++ and dismisses it quickly. The short answer is C++ gives control and abstraction on demand, an unusual combination. Java trades control in exchange for GC.
Well, yes. And more than a few other languages that got left in the dustbin of our history. But as for today...
I actually am personally very keen on seeing where Rust goes here, but it isn't 1.0 yet (which will be the signal for me to start writing in it seriously ).
Ironically the Java ecosystem could stand to use some garbage collection of its own: there's a ton of old, outdated info out there that both colors people's impressions of the language and teaches new players a whole manner of bad habits. I appreciate what this article's going for and hope there'll be follow-ups.
I use Java daily and though there's undoubtedly room for improvement (I'm looking forward to when tooling better supports stuff added in Java 8), I think a lot of the negativity that surrounds it is undeserved. There's definitely bloated XML-infested frameworks out there but the core's a real workhorse.
It's not just the JDK that needs pruning, though. It's the ecosystem of third party libraries, and the millions of pages on blogs and StackOverflow (and shudder JavaRanch) that contain bad, outdated advice, following which will make people hate Java.
I'd love it if the JDK had a "learner mode" that disabled interned string literals. Then newbies experimenting with `assert(str1 == str2)` wouldn't leap to false conclusions.
== should never have been used for that method, which is very rarely what you want. The right thing is probably to deprecate == on nonprimitive types, replacing it with a longer name that's clearer about what it means.
> In this example, Java is rather annoying, especially when it comes to testing the type of a message with instanceof and casting objects from one type to another.
Using instanceof is an antipattern 99% of the time, easily avoided with proper API design. In this case a simple enum type would help with appropriate getType() method on the event; or a polymorphic event API with dedicated method types for each event (LifecycleEvent marker interface with ExitEvent subtype containing onExitEvent(ExitMessage m), etc), or ... or ...
Writing an intro to Java + touting your company's API + blaming Java for yourco's API problems: seems like bad form.
Which reminds me: can someone explain how actors is any different than using messages and queues for concurrent programming? Unless it also implies "magic translation of messages to method calls" which makes me uncomfortable (bad memories of CORBA/Web services)
Agree that instanceof is wrong and discredits the article.
I'm not sure if this is what you meant, but here is how polymorphism along with the double dispatch pattern would work: NaiveActor#handleLifecycleMessage will need to delegate to the event subclass, which will in turn select the appropriate method on NaiveActor.
@Override
protected void handleLifecycleMessage(LifecycleMessage m) {
m.handle(this);
}
@Override
protected void handleExitMessage(ExitMessage m) {
if (Objects.equals(m.getActor(), myBadActor) {
System.out.println("My bad actor has just died of '" + m.getCause() + "'. Restarting.");
spawnBadActor();
}
return super.handleExitMessage(m);
}
It's been my experience that many developers resort to instanceof or enum type flags because they don't believe polymorphism actually works in real world situations such as this.
There's something wrong with this approach, though: it couples ExitMessage and BasicActor, in that BasicActor would have to have a method for each event type, resulting in lots of empty methods, etc.
What I'm describing is a marker interface for eventing, with specific subtype APIs:
The benefits to the client code are numerous: clarity (dedicated methods for events), declarative code ('implements' section documents interactions), performance (no dispatching in client code).
[Note, Disposable here represents a dispose() function to deregister the listener, avoiding the classic pair of void register/deregister methods. Often I find void methods represent a missed opportunity ... wishing Java was more like Smalltalk here]
The service side has to jump through some hoops to efficiently dispatch, using class equality or instanceof at registration time to pre-select listeners. This code could certainly use pattern-matching but personally I think it would look identical. If anything, I'm glad that pattern-matching isn't available in this case, to at least alert framework devs to the problem and not push it off to tons of switching on the client.
I think a lot of programmers aren't totally clear about how dispatch works in Java. I've talked to many who couldn't explain exactly why it doesn't work to overload based on subtype information only known at runtime. Type flags are extremely obvious!
I believe the segment that cast shade on instanceof checks was doing so in the process of mentioning "pattern matching" features from other languages. It would be difficult to suggest the utility of pattern matching without explaining the issue that it addresses.
I agree that you can do this with a boilerplate of `MyEnum getType()` methods, and I admit I often do this so I can use a switch statement in situations like these, but I don't at all resent the suggestion that maybe there's a better way -- this does come up often enough that I would rather appreciate a language feature that helped me deal with it.
It's ironic, I'm slowly trying to move my development over to scala. I'll likely integrate gradle in to my stack (still use maven =/ mainly because I know all of its weird quirks)
What have people's experiences with gradle been? I'm not a huge fan of groovy hence why I stayed away from it.
IMO Gradle has made huge improvements the past couple years (when I first started using it a few years ago it was incredibly unstable) but if you are a semi-power user of Maven I think you're going to find yourself frustrated using gradle still for a couple reasons (I've looked into this for my work recently, moving away from Ivy). Note I haven't extensively used Gradle, this is just from research:
- Intellij has incredible Maven support, and by this point almost all the bugs have been worked out. Gradle support is improving, but our company has dozens of modules, a mix of Java / Clojure source code, and depends heavily on Intellij automatic source linking working correctly, dependency propagation working 100% successfully, etc, and it's really easy for small bugs to become blockers. Last I checked there were still a number of pretty frustrating bugs related to this
- The Jenkins maven plugin is great, and the Gradle one is mediocre. For example, it does not even handle automatic triggering of downstream builds (this is absolutely critical for us https://issues.jenkins-ci.org/browse/JENKINS-19941)
- Gradle pretty decent plugin support by now, but is not yet as exhaustive as what you'll find with Maven (there's a maven plugin for basically everything now)
- This may have been resolved, but I had issues configuring getting Gradle to update snapshot dependencies, which was really important to us.
In the end I decided to migrate to Maven to avoid these headaches. I think I will try to use Gradle for personal projects, but I don't feel comfortable migrating our company stack there yet.
Really appreciate the insight, this is what I have found as well. Especially using intellij, it's still hard to beat. I'm always on the look out to use new stuff, but I'd rather wait a bit..
If I go hybrid JVM, I will likely just use SBT instead.. I think I'll keep an eye on gradle and see if it matures though.
One of the reasons I still use maven is like what you mentioned: the tooling, I don't find myself using xml most of the time (despite knowing it like the back of my hand anyways)
I like Gradle a lot. The build scripts are easy to read, and it's really easy to write nice plugins.
That said, my Scala-using colleagues are unanimously agreed that SBT is the way to build Scala projects. I suspect that some of that is purely about being fashionable, but there are certainly a few things you need to do with Scala (like handling the Scala version as part of artifact coordinates) that SBT does naturally that Gradle doesn't.
The position of things like Netty and Undertow at the top of the techempower benchmarks has me a little intrigued. How much hassle is it to write websites with servlets like that?
A bit of a hassle, but Comsat will make it dead-easy (right now Comsat runs on top of any servlet container, but it will also run directly on top of Netty/Undertow). Take a look at our Comsat web actors: http://blog.paralleluniverse.co/2014/01/28/web-actors-1/
Undertow provides a Servlet container, so if you are already using a Servlet-based framework, the level of effort is fairly minimal. Though, Resin remains a very high-performance Servlet container as well in our benchmarks and if you need a broad set of Servlet features, Resin may be a better fit.
Another option is WildFly, which is the new JBoss application server that uses Undertow below the hood.
We are presently adapting our in-house framework to use Undertow natively (without the Servlet layer) and the effort to do so has been low, all things considered. If you're comfortably working with the internals of your framework, you may be able to do the same without a great deal of pain.
I've had a great experience building web APIs (i.e. returning JSON rather than HTML) in Scala with Spray; it requires you to think a bit more about when things happen (because everything is async), but it's lovely and smooth to use (there's this routing configuration DSL that looks almost like a config file, but then you realize it's all Scala so you can use things like for/yield with it).
In terms of actual websites I understand Play is migrating to run on top of Spray, but I'm not aware of any mature frameworks for doing it right now.
I went from Java to Scala and am back to Java 8, and couldn't be happier with my choice. We are also using the latest Spring 4 framework which plays well with Java 8.
A lot of the Spring + Java haters haven't really looked at
all the improvements have happened to both Spring and Java recently, either that or they just like to bounce off what they read online without any actual experience.
It's a solid stack for a backend, and I have built the whole platform on in without a hitch.
Dagger is definitely more appropriate for Android applications and was developed specifically to address the issues with using something like Guice on mobile. That said, I love Guice and use it exclusively as it has a superset of features and startup performance is irrelevant in my area.
As Christian Gruber from the development team put it:
Dagger is a joint effort by Square, Google, some individual contributors from other places such as Nextflix, and is descended conceptually from Guice - specifically from MiniGuice. It addresses some key challenges our users faced with Guice. From Square’s side (/u/swankjesse can clarify this) it was the need to get high-performance, low-startup dependency injection on Android. From our side, it was that and the desire to trim the API weight of dependency injection, to reduce the user confusion that comes from reflection and bytecode generation in stack traces and debugging environments, and to get early validation of your graph’s wiring.
Dagger is a substantial direction shift for Google, and we are investing time and resources in it. Guice will always have a superset of features compared to Dagger, though we do have projects using Dagger on the server and in stand-alone java apps. But Dagger is not as evolved in terms of the surrounding "scaffolding" code (servlet support, etc.) as Guice, and won’t be for quite some time. Additionally, some teams will need or want some advanced Guice features that will never make it in to Dagger. [1]
If you're planning at least 3 parts, have you considered turning this tutorial into a Leanpub book? It's the perfect start to one... (Disclosure: I'm a Leanpub cofounder)
I try to avoid it as much as possible. It's confusing at least to me and makes maintaining code over a long haul an arduous dull process. I'm getting to the point where I prefer straight JDBC over Hibernate too. It takes longer to code but I've seen speed increases of several times over Hibernate in those situations. JDBC code is just linear but I feel it's easier to maintain in the long run.
Speed is not the only concern when it comes to JDBC vs ORM (JPA/Hibernate).
The more complex the data model, the more one needs to know the inner working of JPA. I've shared my struggle understanding how JPA works even for a medium-level complexity of the JPA entities.
Some of the problems I've encountered using JPA:
- The whole EntityManager act as L1 cache occasionally tripped me when writing Integration-Tests
- The relationship direction (owning, etc) can be confusing to learn
- Reference vs Lazy vs Eager load
Having said that, HBM2DDL is a nice tool that can work as maven plugin such that changes on the JPA entities can resulted the DDL to be updated properly thus maintaining consistency between Java Data Model and the DB schema.
I agree. Hibernate has become a downright liability at times in our codebase. These days I only use it in new code for query parameterization and result row transforms into models.
Speaking of which, if anyone knows of a good library for query parameterization alone, let me know...
We use JDBI @Truecaller together with Metrics library. Not only it is clean and tidy, it also gives you immediate profiling around your database calls. This is priceless in a big service oriented environment. With it, you can exactly see the rate of happening (mean/last 1/5/15 minutes average) and latency (mean/avg/std-dev/75/95/98/99/99,9percentiles) for each database query. I wouldn't want to go back to manual logging and optimization hell. JDBI+Metrics opens a totally new dimension to your monitoring/profiling/optimization!
I agree... can't live without Dependency Injection (one of the reasons I refuse to move off of Java). I've been using CDI and TomEE for small simple stuff (it just works).
Can't stand Spring Framework anymore. It set out to replace the bloatware of Java EE 1.5 but it ended up becoming what it was meant to replace.
It occurs to me that dependency injection has this strange similarity to functional programming. I mean, clearly, you're playing with objects instead of functions, and they can have state, and so on, so it's not functional. But still, there's a similarity in how you're breaking things apart.
Spring: Maybe the problem is that Jave EE 1.5 was a reasonably good solution for the problems it was trying to solve? Maybe you can't do radically better and still actually solve the problems?
Genuinely curious : i've been playing with dependency injection, and really never got to understand the true use of it.
I mean, what's the point of being able to replace an implementation outside the source code itself ? You'd still have to extensively test the thing and recompile it...
Is there more to it than just being able to replace a class by its mock up, for unit testing ?
When you've got a complex graph of objects and dependencies between them, DI can easily take care of instantiating an A and feeding it to a B that requires an A and so on and so on.
In our projects we'll have a DebuggerFooImpl, a MockFooImpl, and a ProdFooImpl. Spring's AppConfig classes then can create the proper object at startup based on environment profiles and no consumers have to do any more than ask for the Foo object to be injected into them, isolating them from any environment awareness/coupling.
There are other benefits from DI as well, but the above at the low hanging fruit, isolating the complexity of object creation from the object's consuming classes.
I think the point is that you don't want to be instantiating (and thus configuring) a dependency at the site where it is used. The code in class Foo should be limited to implementing Foo, not instantiating and configuring its dependency Bar.
However a IoC container can automatically create, and send through the object based convention(IMessageQueue -> MappedTo -> MessageQueue) or configuration (IMessageQueue -> MappedTo -> APMQMessageQueue).
1. Does my class work appropriately? Does it encapsulate/hide/abstract the right behavior? Does it function correctly with other classes that implement certain inferfaces?
2. Is my network of classes correctly defined so that I can use them all together in a particular way?
IMO dependency injection encourages making very deep object graphs. constructor argument passing can be cumbersome, but jumping into new code it is much more clear, and it encourages you to write flatter code structures. i go without.
It depends. One thing that I thought is an interesting feature of Spring, is that it allows the framework to inject code between your dependencies like decorators. This allows them to do aspect-oriented-programming transparently. And I think there's some interesting ideas here. For example, you can mark the interface of a class as @Transactional, and all your implementations will get the behavior.
I had an obscure bug using dynamic proxy (castle dynamic proxy2) a while ago in a WPF application. I was proxying to an interface so it created a proxy object in between that in the actual class so it was eating my C# event. Changing the proxying from an interface to a subclass fixed it.
Not to sound snarky, but you should read any introduction to dependency injection. The benefits are generally covered very thoroughly, and what you said is not usually considered a benefit.
Wikipedia article on dependency injection, section titled "Advantages", _first_ bullet: "The result is more independent clients that are easier to unit test in isolation using stubs or mock objects that simulate other objects not under test."
You should give the latest version a try. Spring implemented JavaConfig, which allows you to avoid XML altogether. Coupled with the ComponentScan annotation, it can't get any simpler.
I have come full circle in a way. I started learning Java in school and built a few, small things for Android and the desktop. Then I was "all like;" I am going to learn the hotness which was(is?) Node. Node is what it is and I didn't really care for it. Then I moved on to Python and I really like it. Python is awesome for many, many things but GUI applications are not one of them. I have since returned to some Android development and I am diving into a CRUD web app in Java. Simple stuff, but it needs to be fast.
Because, particularly in Java-land, if you're not opinionated you end up providing a FactoryFactoryFactory. A beginner is in no position to weigh up the pros and cons of the different build tools available, so it's better for a guide to simply make a recommendation and explain that one than to give the beginner a confusing choice.
Opinionated: conceitedly assertive and dogmatic in one's opinions.
It generally refers to people who assert their opinion without making a sound argument for it. I consider it a huge negative.
Another vice that many consider a virtue is when they consider themselves to be "real" - this is generally code for lacking any self-discipline and being unable to control emotion.
- Java is such a massive ecosystem that you need someone to guide you through the complexity and to show you the diamonds among the piles of dung.
- You're being honest. Really, my impression of Java has been so bad because of people that want "industry standard" and "enterprise" things that I welcome fresh perspectives from people in the field. Ultimately, if someone points out that a certain statement is they own opinion it's easier for you to judge it in a broader context, so even if you still disagree you don't feel like you're being misled.
Its better to have one opinion then ten conflicting ones. Its also easier to learn how to do something from an opinionated source then one that tells you to do "whatever you want", without providing you with good ways of evaluating the choices and intelligent defaults.
>But the modern Java developer uses Gradle...there are quite a few things that are quite, though not very, common, but still require dropping down to imperative Groovy.
This is the first time I have heard of Gradle, but why would I use a build tool that requires me to learn Groovy. If I already know Java I wont be learning something new just to build a Java project.
I find a lot of development tools/frameworks make me learn B just to get started with A, its really frustrating for someone with limited experience IMHO.
I wouldn't say you need to actually learn Groovy to get going with Gradle. The example build.gradle files are fairly self-documenting, and you'll be modifying them more than writing them from scratch.
In that case I will have to check in out on a side project. My current projects at work are using Ant or Maven and I dont really like sorting through the pom.xml especially if someone else set it up.
What if I told you that Java code is perfectly compilable in Groovy and learning the required amount of Groovy isn't that much anyway?
There's even a JavaDoc that you can reference at any time.
And even now in Java 8, you have Lambdas... well guess what? Groovy uses Closures everywhere, and the syntax is similar too. So it really shouldn't be black magic.
I have to agree with the first comment on the blog. Gradle is strictly worse than Maven - it's basically Ant reinvented with Groovy. It leads itself to poorly maintained, complex build files, and the only good parts are the bits that use Maven under the hood (so just use maven ;-)). It's also slow.
Also, if you seriously want to use an Actor framework in Java, you should use Akka - the lead devs really know their stuff, and are active in Java concurrency circles (JSR-166).
I'd like to hear thoughts on CheckedExceptions in part 2. IMO, they are a disaster - most projects degrade into all methods having a "throws Exception" clause. But I'm not sure if there is any consensus on how the CheckedException haters like myself work around them. I use Runtime exceptions everywhere, but it's a pain/boilerplate to convert them.
Not all checked exceptions are bad. The main problem is that the core Java libraries tend to use them too aggressively and now of course cannot be changed. You really have to be sure that the caller MUST handle a particular occurrence and anything else is a bug to make an exception checked. But, I do find it helps me feel more confident in my code. Everyone hates writing error handling code, but at least with checked exceptions you can see whether it's been done properly or not.
But in Java 8 for the times when I want to disable it, I just use the following code:
public interface UncheckedRun<T> {
public T run() throws Throwable;
}
public interface UncheckedRunnable {
public void run() throws Throwable;
}
public static <T> T unchecked(UncheckedRun<T> run) {
try {
return run.run();
} catch (Throwable throwable) {
throw new RuntimeException(throwable);
}
}
public static void uncheck(UncheckedRunnable run) {
try {
run.run();
} catch (Throwable throwable) {
throw new RuntimeException(throwable);
}
}
public static void ignoreAndLog(UncheckedRunnable runnable) {
try {
runnable.run();
} catch (Throwable t) {
log.error("Ignoring error", t);
}
}
Then you can write
Foo result = unchecked(() -> getAndMaybeThrow(a, b));
I think some of the additions in Java7/8 will make them a little easier to work with. The worst thing used to be the necessity to nest multiple try/catch blocks, or repeat identical code between separate catch blocks because different components throw different errors. This is now dramatically helped by the multi-catch and other additions.
Like you, I use a lot of RuntimeExceptions, but I think in it's important not to overlook the benefit of checked exceptions: if you're trying to write reliable software looking up and understanding every possible failure mode of every API you are calling is an almost unbearably tedious and impossibly boring task. In principle, having the compiler check and tell you "Hey, there's this error that could occur and you haven't defined how your code is dealing with that" is a tremendously useful thing. Our human tendency to focus only on the successful path through our code and then ignore all the possible failures is terrible bias if you're trying to make code that behaves the right way under ANY circumstance. So I support checked exceptions, and I hope the new improvements in Java make them more workable and accepted. There probably need to be more improvements, something long the lines of STM type features before we'll get there though, I think.
1) try introducing a Checked Exception in a commonly used method. Soon you'll be updating 100s or 1000s or methods.
2) checked exceptions don't play well with interfaces (APIs) for similar reasons. any interface user must change their code simply because some new checked exception bubbles up now
3) checked exceptions lead to terrible error handling and hiding bugs/system problems. instead of letting exceptions bubble up - java coders almost always write code that either swallows or simply logs the exception and continues along as if nothing happened. If my bank deposit fails, I don't want the failure to just end up in a log file - I want to know it! Exceptions were designed to usually bubble up and be exposed/handled in a standard way at the top level thread. They are usually not recoverable.
4) they lead to bugs. I very rarely see anyone handle the statement/resultset handling of JDBC code correctly.
5) if they are such a good idea, why does no other language ever created has them?
> 1) try introducing a Checked Exception in a commonly used method. Soon you'll be updating 100s or 1000s or methods.
Try doing that in a code base without checked exceptions. You just created 100s or 1000s of unrecognised errors in other code without realising it. The problem is not the checked exception. The problem is you changed something 100s or 1000s of things are relying on to add a new failure mode.
> Checked exceptions lead to terrible error handling and hiding bugs/system problems. instead of letting exceptions bubble up - java coders almost always write code that either swallows or simply logs ....
Well, I agree up to a point. But that is much to do with how tedious and verbose the error handling itself is which is more about the language than the concept of checked exceptions.
> they lead to bugs. I very rarely see anyone handle the statement/resultset handling of JDBC code correctly.
see above
> 5) if they are such a good idea, why does no other language ever created has them?
Well, you can also say, if they are such a bad idea, how come one of the world's most popular and used language builds them into all its core APIs? They can't be that terrible or Java would never have got so popular ....
I think you are falling into the trap of thinking you can usually recover from an exception. Exceptions are usually caused by one of two things:
1) system error (no more DB connections, hard drive full, etc)
2) a bug
neither of these are recoverable, you just need to stop the task at hand and notify someone that the situation needs to be fixed. Trying to handle it and recover is usually a fools errand that results in hiding the problem
There are cases that you do want to handle exceptions. In these cases, yes catch the exception and handle it. But these cases are the 10% case, hence the default behavior of making the caller handle the exception isn't desirable.
If Java forced you to handle the exception that would be convincing, but it doesn't. It merely says, if you don't want to handle it, add to your signature that you throw an exception so that at least someone upstream has a chance to know that the error might occur. I'm not arguing at all btw that the way Java does it is good. Merely that there's a case for checked exceptions, especially if you are actually trying to write "reliable" software.
Well, there's not much to discuss about checked exceptions. The general consensus in the Java community that it was a very good idea in theory, that hasn't worked out well in practice. New API designs usually don't introduce new checked exceptions. Those that are there - are there, and new ones aren't being added, so there is really not much to argue over.
I quite like checked exceptions. They're actually one of the few things that keeps me writing java for more projects instead of switching more of my time to golang -- golang takes the far opposite approach, and with either returning error codes, or using golang's borderline untyped panic (yes, yes, you can panic typed errors... but it's an incredible PITA to try to construct an error type hierarchy and impossible do terse typed catch blocks with it) doesn't scale well for projects more than about 4ksloc in my experience.
Exceptions signatures, like anything else, need aggressive refactoring to remain a useful part of an API. Always remove throw declarations that aren't needed. Always refactor the exception type hierarchy as your project evolves to keep it sensible.
The worst of typed exceptions I've felt recently is the JGit API (don't get me wrong, JGit is an amazing piece of work; but its sharpest parts are the error handling). There's inchoate masses of IOExceptions from some pieces, JGitAPIExceptions in others, and none of them compose nicely so that when I do large amounts of work I can summarize the error handling up to a few types of conceptually similar problem. And several JGit commands throw checked exceptions for what are essentially fuck-ups in builder patterns, which have been compile-time issues every time I run into them, thus a source of huge irritation (these are prime examples of where you should use unchecked exceptions).
On the other hand, the project I was using that same JGit API in has been one of the best examples of why typed exceptions can be a good idea. This project grew out of a python->java rewrite, and so in the original translation used completely unchecked exceptions as a holdover from the python form. (Why rewrite? It needed to go cross-platform and I needed a stable git api; libgit2 still couldn't clone at the time, so it was jgit or gtfo.) And as I kept working on the project and writing test cases... time and time again, converting things to typed exceptions and refactoring the exception hierarchy paid huge dividends in code quality, huge improvements in API consistency, and raised the quality of tests and final product alike because similar error cases ended up with similar exception types, and tended towards similar handling as I refactored similar exceptions types into one... #wining.
tl;dr being irritated by methods that claim to throw too many exception types is good and healthy. The fix isn't to toss checked exceptions out the window: the fix is to take the pain, and use it to fuel a good API with a tightly controlled and easily understandable set of failure modes.
Dependency injection and any othee type of code indirection is evil imo. Anything that breaks the ability to find your way in a codebase with something other than grep brings more pain in the long run than it saves.
It's a tradeoff between two different kinds of clarity. Yes, it's harder to see the "whole wiring" without better tools...
But it makes small, encapsulated classes much easier to reason about and develop! You can focus on assuring: "My `Foo` can interact with a supplied `Bar`" rather than dealing with all sorts of crap about what implementation of `Bar` it gets or how that `Bar` instance is configured.
Spring's DI is terrible but Guice (and on mobile, Dagger) is really easy to work with, statically typed and has increased the maintainability and testability of our code base tremendously.
DI is fine, it's just the way people overuse it that's an abomination. I general inject the most significant pieces, or the pieces that are changed. I won't even introduce DI unless I know I'm going to setup a different config of it. My coworkers (sigh), insist that nearly everything must be injected to "eliminate dependencies". (and because it makes it "easier to test"). YMMV
Dependency injection is an abomination. Working on DI code feels like slogging through the post-processed expansion of some more elegant language. It's hard to understand control flow, and DI adds exciting failure modes to otherwise-correct code. Don't forget that DI also bloats class and method counts.
Substitution for testability should be done at the runtime level, substituting class references as needed, instead of punishing all production code everywhere.
If you have come to this post expecting to read something related to modern Java for the web, and have come back unsatisfied, then here is something to make up for that: yeoman's jhipster generator: http://jhipster.github.io/
Oddly, this resource is blocked in Russia, so I was not able to read the article from my ipad. WTF with this country. Anyone knows if I can penetrate Great Russian Firewall on ios?