An Opinionated Guide to Modern Java Development, Part 1
blog.paralleluniverse.co
blog.paralleluniverse.co
Lots of embedded devices make use of J2ME, e.g. cars, manufacturing, electricity monitoring...
Google did indeed managed to pull a Microsoft and now we have a forked Java implementation getting steady behind the standard Java implementations.
Even J2ME is more compatible with its big brother than Android.
KitKat has now partial support for Java 7, with libraries still missing some pieces. Dalvik and ART still don't support invokedynamic bytecode.
And since almost no one has KitKat, one cannot use try-with-resources anyway.
Late edit: perhaps Oracle should make a phone ;)
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.
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?
They did an open spec tablet with a raspberry pi tough.
Try Intellij IDEA / Android Studio. I find them quite reliable.
Android Studio seems to still have performance issues with Gradle on Windows, specially when indexing stuff.
Eclipse
/shudder
Are you serious?
J2ME is even more crippled than Android's Java (no reflection, no Swing, no AWT and stuck in Java 1.4).
J2ME has been dead for more than half a decade and we have Android to thank for that. Good riddance.
http://www.oracle.com/technetwork/java/embedded/overview/jav...
Also missing:
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)
Source: http://docs.oracle.com/javame/config/cldc/opt-pkgs/api/cldc/...If you think that's wrong, fine but that lawsuit had nothing to do with bytecode.
I'm not aware of any plans to support Java 8 yet, but I haven't been looking.
Android does not have any of this (http://developer.android.com/reference/packages.html) because the Apache Harmony project died before it could implement Java 7 API changes.
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.
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.
I doubt it will ever happen.
Dalvik is dead. It has been already fully replaced on the latest AOSP code drops. Plus SL4A was left to rotten.
As for Go, lets see. My ticket is now two years old.
Yes it has. They recently added Java 7 language support.
http://tools.android.com/tech-docs/new-build-system/user-gui...
I assume other certified JVMs would follow similar design approaches.
"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."
So unless I'm missing something, please be specific.
http://cr.openjdk.java.net/~briangoetz/lambda/lambda-transla...
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.
Have you checked this talk at Java ONE?
http://parleys.com/play/5251c164e4b0a43ac1212459/about
Some older slides also available
http://www.slideshare.net/jaxlondon2012/lambda-a-peek-under-...
The implementation can be optimised at any point.
Default support of ART or Java 8?
If Java 8, how do you know this? Citation needed ;)
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.
Having a different implementation doesn't change the limitations imposed by out of date VM running on a device.
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 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.
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.
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.
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.
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).
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.
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).
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.
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.
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.
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.
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. :)
For a really quick start I would recommend https://github.com/spring-guides/gs-spring-boot/tree/master/.... 2 classes and you don't even need an external servlet container.
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?
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.
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.
EDIT: Comments are useful for explaining things like:
1. Non-obvious side effects
2. Code that's working around a bug in a 3rd party library
3. Code that calls into some non-intuitive 3rd party API
4. Citing your work (e.g. "adapted from stackoverflow.com/blah123")
5. Why you used pattern A instead of the more standard pattern B
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.
"checked in abstract_class.cpp"
Duh!
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.
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.
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 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 also know that Netflix use Gradle for pretty much all their Java stuff.
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).
[1] http://blog.lunatech.com/2011/08/24/scala-ceylon-kotlin-goal...
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 that a typo? I'd say Ant is the opposite of declarative.
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.
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.
[0] - http://www.scala-sbt.org/ [1] - https://github.com/sbt/sbt/wiki/Client-server-split
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.
PS - You may already know this, but you can change IntelliJ's compile output directory [0].
[0] - http://www.jetbrains.com/idea/webhelp/configuring-module-com...
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.
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.
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....
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....
Such as?
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...
I stand corrected. That would be extremely useful. Maven is really awkard about these things. EG: "I want to run integration tests but not unit tests". Here's how: http://stackoverflow.com/questions/6612344/prevent-unit-test... Pretty lame.
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.
dependencies { compile group: 'commons-collections', name: 'commons-collections', version: '3.2' testCompile group: 'junit', name: 'junit', version: '4.+' }
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....
* 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
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.
There was a Grails wave here in Germany, but now I seldom see anything related to it.
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.
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.
IntelliJ makes this a breeze. I'm sorry you aren't using it, that must make life really hard :-(
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.
After all you can do functional programming in any language. Why do you need another.
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'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.
public final Date date;
date.setTime(1);
That's not immutable.
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?
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).
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
}You only need XML if you're deploying to heavyweight servlet containers (standalone Tomcat, e.g.). Even embedded Tomcat doesn't use XML.
http://svn.codehaus.org/groovy/eclipse/trunk/base/org.codeha...
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.
I see it as "Java without types", myself.
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".
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.
Looking forward to the day the reference JVM becomes a meta-circular one.
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.
I want compilation to FAIL in these cases.
eh?
scala> val safe = Option(null)
safe: Option[Null] = None scala> val x = Some(null)
x: Some[Null] = Some(null)Even so, to continue with your example:
scala> x foreach println
null
x.get
res2: Null = null
Hey, what do you know, no NPE.Try harder ;-)
Although (having just re-read it), the original post's complaint was actually that:
> the compiler (afaik) doesn't prevent you from setting an Optional field to null
ie
scala> val option: Option[Any] = null
option: Option[Any] = nullWith 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?
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.
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.
unsafe {
...
}
Don't know if this would work. 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.
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?
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.
// 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).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.
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.
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 ;-)
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.
In the JVM world, Kotlin and Ceylon do it as well.
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++)
Also, IntelliJ is a must have!
C++11/14 is in practice not that much more difficult to write well than Java. It's not 1998 anymore.
The language is larger and more complex than Java, but it's also a lot more expressive and powerful, not to mention faster.
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.
The enterprise is a very slow moving snail.
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.
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.
All that shit that sucked in 2005 about C++ is still in there. It's just up to your discipline to not use it.
Do you trust your coworkers enough?
Source: have spent 5 years doing production C++
So even though java the language isnt dynamic, you can do a lot more at runtime, than with these new-fangled languages like Go and Rust.
As a result, you see things in Java that are more typical of dynamic languages, rather than C++ for example.
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.
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?
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.
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.
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.
For SVN, I use Checkout and uncheck "Use default workspace location" and specify the location of the code.
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.
Just my 2c as an eclipse user converted.
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.
The language specification does not require a specific implementation and with time all JVMs moved to red threads.
There are a few JVMs around that still support green threads as threading model.
> 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.
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.
Ada, Modula-3, the Oberon language family as well.
But they lacked a proper OS vendor support and faded away.
Ada seems to be raising up, thanks to GNAT and continuous security issues with C and C++. At least from its increasing presence at FOSDEM.
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 ).
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.
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.
This is what Scala and C# do.
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)
Exactly!
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.
Example of subclass of LifecycleMessage:
class ExitMessage implements LifecycleMessage {
@Override
void handle(BasicActor actor) {
actor.handleExitMessage(this);
}
}
In 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.What I'm describing is a marker interface for eventing, with specific subtype APIs:
interface LifecycleListener { }
interface StartListener extends LifecycleListener {
void onStart(Foo f);
}
interface ExitListener extends LifecycleListener {
void onEnd(Foo f);
}
along with a single registration method (perhaps a LifecycleObservable API, or in a class also offering event-firing methods): Disposable addLifecycleListener(LifecycleListener l)
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 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.
What have people's experiences with gradle been? I'm not a huge fan of groovy hence why I stayed away from it.
- 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.
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)
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.
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.
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.
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.
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.
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 ?
http://en.wikipedia.org/wiki/Dependency_injection#Constructo...
However a IoC container can automatically create, and send through the object based convention(IMessageQueue -> MappedTo -> MessageQueue) or configuration (IMessageQueue -> MappedTo -> APMQMessageQueue).
Would you like to try again?
Where, in what you posted, does it reference being able to replace implementations outside of the source code itself?
Would you like to try again?
The IoC container will return transparent proxy(Not the original object), which then calls the underlying method(after doing the AOP behaviour).
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.
Boy that was a fun one to figure out.
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.
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?
http://programmers.stackexchange.com/questions/92393/what-do...
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?
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]
[1] http://www.reddit.com/r/java/comments/1y9e6t/ama_were_the_go...
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.
Speaking of which, if anyone knows of a good library for query parameterization alone, let me know...
It's our in-house jdbc library, and has IDEA plugin. We use it in many small projects, and in one major.
The modified code ran in a fraction of the time the pure architecture was running.
Looking forward to part 2 and more!
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.
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.
Easier to read than a pom.xml, for sure.
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.
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.
That and my employer uses Java and randomly chooses PHP sometimes for no apparent reason.
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).
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 writeFoo result = unchecked(() -> getAndMaybeThrow(a, b));
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.
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.
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?
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 ....
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.
This link from 2003 articulates the point better than I can: http://www.artima.com/intv/handcuffs.html
Seems like a gaping omission in a guide that claims to be about "modern" Java.
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.
I'm looking at you, Spring.
Most DI frameworks automatically configure, and register objects. So literally all you need to add is the annotation.
Then you can override the automatic registration with you own, with different implementation when required.
Substitution for testability should be done at the runtime level, substituting class references as needed, instead of punishing all production code everywhere.
That would require a Java agent. And that's a smell it its own right. (Cf JMockit)
Did I read that right?
Presentation: http://jhipster.github.io/presentation/
Also, what are Maven's fatal flaws? I don't consider XML a flaw.
This is probably true but…
Does anyone here have any data to back that up?
Nice
Quite enjoyed the article until that got jammed in there.
A simple, obvious, useful idea I hadn't seen before.