I'm not sure how one framework developer's naming choice (a framework which by the way, needs to do some pretty meta things in regards to creating factories for other factories, and which is using the term "singleton" to mean something different than usual) is a criticism of an entire language.
You can come up with ugly names for classes in any language.
I think it speaks more to the community than the language (and arguably there is also no such thing as a community).
After years of consulting I can't remember how many times I've walked into an Enterprise Java Shop(TM) to find TemporalSystemLoadOrganizers, IntransitPredeterminedApplicationUtilitySources, MetaphysicalManipulatitiveQuantityDisorderRecognizers only to find out that at the end of the day these abstract-factory-driven-decorated-decoupled-dynamically-injected-frameworks tend to do such obscure/complicated things as "Update a user's first name" or "Show the last item the user has purchased"...
Again, not Java's fault and no question you can write very fast, beautiful and clear code in Java. I'm sure every language has specific warts and most of them probably reside more with the community than the syntax.
Right, it's not the fact that you can name things poorly in any language, it's that non-descriptive, overly verbose word-jumble vomit is built and presented seriously and without irony as common practice.
Either it's the people who write Java, or something intrinsic in the design of the language itself that drives people to write code in this extremely verbose way. I've always leaned towards the latter...
A bit of column A and a bit of column B. People who write Java are exposed to rampant overuse of design patterns when looking at examples of a) what the community considers Good Java and b) all over their internal projects. This is partially because Java lives, by design, in a Kingdom of Nouns and partially because there's just no good way in the standard language / library / toolchain to do some things without going really pattern heavy.
For example, assume I've got a list of students, and I want to show all the ones who haven't taken at least one exam, sorted by last name. Here's the relevant pseudocode in Rails:
That just flows from my keyboard as a Ruby/Rails programmer, is pretty much instantly comprehensible to other Rails programmers, and (while others might disagree with stylistic choices, variable names, or whether to use that weird &syntax to do the sort) would be considered "good enough Rails code to ship."
I will take the liberty of pasting my Java implementation into a gist -to avoid breaking HN:
A nice, svelte 38 line method, which will be reused via copy/paste a hundred places in my codebase.
Incidentally, at my previous Big Freaking Enterprise job, the user need "Make a page for a class where we can see all students who haven't..." would get quoted to them as "No problem, that will cost you $1,000. Are we green-lit to implement or do you want docs written first ($250)?", because the core logic I've shown you is the tip of the iceberg of how sucky that experience is going to be. We haven't even started with the XML files and annotations required to hook the new actions together yet. By comparison, as a Rails developer, in lieu of getting you to sign off on a $1,000 line-item to your next invoice I'm inclined to show you a totally working page and ask you "Is this what you wanted?" because implementing it is easier than talking about implementing it.
I don't want to play code golf with you, because I think your point is generally valid, but you can happily and idiomatically reduce the Java method itself to 10 lines with some sympathetic scaffolding from the other classes (this is actually how a lot of code in our game is implemented rather than some theoretical optimum):
public class Student implements Comparable<Student> {
@NotNull public List<Test> getTests() { ... }
@NotNull public String getLastName() { ... }
@Override public int compareTo(Student that) {
return getLastName().compareTo(that.getLastName());
}
}
List<Student> studentsWhoHaveNotTakenAtLeastOneTest() {
TreeSet<Student> studentsMissingAtLeastOneTest = new TreeSet<Student>();
for(Student student : getStudents()) {
boolean allTestsWereTaken = true;
for(Test test : student.getTests()) {
allTestsWereTaken &= test.isTaken();
}
if (!allTestsWereTaken) {
studentsMissingAtLeastOneTest.add(student);
}
}
return new ArrayList<Student>(studentsMissingAtLeastOneTest);
}
The point I'm (perhaps ineptly) making is not that Java isn't all that verbose (because it obviously is) - rather it's that you don't get much of a stack of abstraction by default. If you don't take the time to implement that abstraction, you're going to have a bad time, but if you do, it's not appalling.
It's not really dynamism so much as a functional outlook. Here it is in Scala (probably with a healthy number of syntax errors, and certainly with a whiff of inexperience):
You could get a similar amount of code in Java using something like FunctionalJava but that's not really a fair comparison, because patio11 is illustrating Java as it's spotted in the wild, and thus so am I. But with appropriate libraries and implementation patterns you can certainly write concise Java if you so choose.
But let's be clear - this class isn't a part of the core library that developers would use everyday.
It's a part of a third-party open-source library that implements a "dependency injection container". It's a pretty abstract concept to begin with - of course it's going to need to do high-level, head-in-the-clouds-type stuff that on first glance you think you would never need.
It's not about naming. This class actually does what its name says. That's the best part. The methods and their JavaDoc descriptions are pretty hilarious as well.
And it's not about the language per se. (You can write clean, simple code in Java, but you would have to write it pretty much from scratch.) It's about Java culture, which encourages this kind of stuff.
And yes, I had been a Java programmer for many years. I used to like the language at some point. But several integration projects made me like its culture less and less.
It's the remnants of the late 90's early 2000's software development overengineering disease, so aptly captured in the mess that was J2EE.
Similar to "nobody got fired for buying IBM", the mindset was that "nobody got fired for building layers of abstraction just in case."
It's the culmination of the second system effect.[1] Without a pervasive unit testing culture, the big enterprise answer to "what if" is "let's add a point of flexibility here."
Obviously, people should be held responsible for building unnecessary abstraction layers like that. They waste time and are often wrongly abstracted, so when you do need to go in to refactor, you end up having to fight the pre-existing "what if" abstraction.
Seriously though, if you are going to rehash this tired schtick then at least make intelligent points about the problems with the language. I have been writing Java for over a decade and I can tell you are a number.
Hey now. I find Javadocs to be among the easiest to read formats of all the different documentation styles. Right up there with Python's standard one (or whatever tool python's default library as well as numpy and scipy use), maybe even better.
JavaDocs is one of the earliest (popular) standard tools for documentation, so I'll give it that, but it suffers a number of problems - problems which are partly relics of the Java language, but that's no excuse.
JavaDocs is too focused on documenting classes, rather than documenting functionality (Python docs, by contrast, focus on modules, which are themselves arbitrary chunks of code with connected functionality).
JavaDocs doesn't make the package/class hierarchy terribly clear - this is intrinsically tied to Java's overcomplicated class hierarchy and needlessly complicated package system, but it carries over into poor documentation as well.
JavaDocs also doesn't have a culture of providing complete examples of code, which exacerbates the two aforementioned problems.
That said, JavaDocs has inspired other good tools, so I'll give it some credit for that and write these criticisms off as vestiges from a time long past.
I found Javadoc well better and more informative than Python doc. Python module is nothing but a watered down version of a static class, so whatever applied to a class, you can say the same thing on a module.
If anything, that's an indictment of the Spring framework, which you certainly don't need to write Java. For instance, there are over 500,000 Java apps in Google Play market, and I'm pretty confident most of them don't use Spring.
Now if you wanted to criticize Spring and cargo-cult enterprise Java development, I think that's reasonable.
Good observation, I've read several posts which complain about factories and proxies. With Grails (which can be all Java no Groovy if you want), Zk, GWT, etc. I can do powerful web apps. No EJB and no Spring needed.
Yes but I don't recall having to do anything directly with it so the reference is good for me. If I need logging I expect it to work not worry that some bean config file isn't set up right. If the Grails developers found Spring helped them, cool, as long as I don't have to deal with it.
The thing is, it's not Java's fault. You can write good Java code. It can be small, and easy, and nice. The problem is the word Enterprise and the abusive abstractions that seem to come along for the ride.
Also, many of the abstractions start as good ideas, but they soon become a hammer and everything else becomes an AbstractNailFactoryInterfaceManagerProxy.
As others have pointed out, this really should be titled "Everything that's wrong with Java culture ..."
For a more technically critical look at Java the language, I recently stumbled on this video while watching a Scala talk Martin Odersky recommended in the first few sessions of his new Coursera class... http://www.youtube.com/watch?v=hcY8cYfAEwU
It's pretty meaty, although it looks only at Java 1.0. Many of the criticisms aren't things I would have necessarily thought of first, and it gave me something to think about in terms of what my own priorities are. (For instance, the lack of first-class functions and closures gets no mention at all)
What is the Java culture? I don't think there's anything. There are so many Java programmers that there are bound to be bad ones along with the good ones.
You're right, of course. Programming culture can be hard to nail down, if such a thing even exists. But would it be a stretch to argue that there is a Java community? I don't think so, and I don't think it's much more of a stretch to argue that a community will adopt trappings of culture.
Java the language certainly enforces a certain kind of programming, that Steve Yegge so succinctly identified as a "kingdom of nouns". I'm not sure if that constitutes a culture or not but it does strongly influence the kinds of programs you end up writing in Java. I've experienced some shared technical culture between companies I've worked at that used Java heavily, but of course my experience is just anecdotal.
Here's a blogpost from an HNer that argues there is such a thing as "Java shop politics" and that companies that develop certain kinds of large monolithic software written in Java and C++ tend to share something, which is not desirable. I don't really have enough experience to agree or disagree, but it's an interesting read: http://michaelochurch.wordpress.com/2012/04/13/java-shop-pol...
What is wrong with Java encouraging OO style programming? Some people will do very well with it and some will not. Functional programming is not the holy grail and some people are very bad at it. Do those bad functional programmers invalidate the whole functional programming approach?
I found that the whole notion of finding some bad examples of a practice and then offer that as a proof to invalidate the whole practice very distasteful. The lynching mob incited from the blog post's false information just shows how far it can go.
> What is wrong with Java encouraging OO style programming?
There's nothing wrong with it, if you think OO is a good approach to structuring programs. I happen to think it's not that great an approach. But Java gives you no option, you can't have just "some OO" and some of something else. I think that's a serious mistake. You're welcome to disagree.
I didn't say FP is a holy grail. However in my limited experience, OO is definitely not either.
All that said, there's nothing wrong with constructive criticism, which is all I've been trying to provide. I don't think I've participated in any lynch mob, I'm sorry if you construed my light jab at "Java culture" to be offensive.
Sure. If you don't like OO and not found it to be productive, you don't have to use it. And you are more than welcomed to state OO doesn't work for you. However, blanket statement like Java sucks or OO fails (not directed at you) is not constructive criticism. It's just insecure programmers using other languages trying to justify their insecure language choice.
> As others have pointed out, this really should be titled "Everything that's wrong with Java culture ..."
I think any UI designer would tell you that a culture doesn't happen spontaneously. Why do Quora, StackOverflow, and Yahoo! Answers feel like very different products despite providing essentially the same functionality?
You can say this about any language and its community, too, not just Java. And it works both ways. Perl, for all its faults, provides a very easy way to package libraries and a well-organized repository for doing so, hence the comprehensiveness of CPAN packages[1].
Java's culture is a result of the fact that Java-the-language promotes badly designed pseudoabstractions intended to guard against bad design. Java provides broken abstractions because it is itself a broken abstraction - the class is a very poor abstraction over an object, and an inconsistent one at that (Java supports multiple kinds - in the mathematical sense - a design choice which impacts the way people use it).
[1] This is particularly true if you turn the clock back ten years and compare with the state of programming languages back then.
> As others have pointed out, this really should be titled "Everything that's wrong with Java culture ..."
was that the OP didn't actually have much technical criticism of the language. If anything it's not "everything that's wrong" because it's missing a lot. I wasn't trying to defend Java.
Yes, my comment was meant more to highlight that any constructive criticism should address the design of the language (which is responsible for the culture), rather than complaining about the end result.
Though sometimes amusing examples do help to illustrate, when used carefully to supplement the main point!
Yeah, actually that's a good point, the talk I linked to with Joshua Bloch really doesn't address the core design of the language so much as a lot of fiddly things on the edges.
You'll find this all the time in enterprise software, but not elsewhere from my experience.
This is a result of people reading their design patterns book and thinking they've mastered the world, but in reality it's just papering over the cracks of the deficiencies of Java.
I suspect once Java 8 comes out stuff like this will slowly disappear from the radar.
I've been coding in Java since it came out in 1995 and I never did that, didn't know you could or why you would want to. So what's your point? Java, C, C++, even C# are readable by average people like me. LISP, Haskell, Ruby, Scala, Smalltalk all look like they were written by aliens.
If you really want to see something funny look at JavaScript code which combines integers and strings. Things that Java would complain about immediately, JavaScript tries to actually run with unpredictable results.
Java, C++ and whatnot are imperative languages, of course the syntax is gonna be different to declarative languages such as Haskell or Lisp. They're also only alien at first; once you get used to a declarative syntax you never want to write imperative code again. It would be like going back to monochrome after experiencing color monitors.
We have some programmers at work who can't think outside the C++/Java/C# box. They also tend to be the worst programmers even after decades of experience.
Perhaps this isn't quiet HN quality of a comment, but I'd love to go to a grey scale screen. I've been trying to figure out how to do that for years. Never could. The simplicity of it would be wonderful.
In the same way, Java is noisy, I admit that, but it's fast, powerful and fairly easy to understand when executed correctly. I'm not saying you can do the same thing in other languages, but it's a good language for systems, especially middle-ware/server side development. It's horrible for Web Page development since JSPs suck and custom tags never caught on in most development shops (they're used because the framework provided them, but even when .tag files came out few used them to encapsulate screen behavior). But Web Development has moved on to JS on the client and REST on the back, so again Java is pretty good too.
I tried server-side development in Java, didn't like it at all. I'd pick Haskell or Erlang over it in a heartbeat.
You can't easily build fault-tolerant distributed systems using only classes without concepts such as function purity and data immutability. Java's type system also happens to be neither sound nor correct; casts are everywhere and NullPointerExceptions can fly around. You're constantly working against the language to write safe distributed code. If Java was safe as a language, it wouldn't require so much debugging time. Haskell was an eye opener for this.
For systems programming I now use exclusively C and D. In the end, Java is only a viable option when you don't know any better. Most Javaland programmers I know of also happen to be blub programmers. They don't know unix, regex, functional style, don't write tests and the list goes on. They do, however, know Agile and UML.
Maybe that's what I don't like about Java. It's culture killed technical knowledge and replaced it with bureaucratic management.
Take a look at J2EE 6 - you might find it's Spring which is the heavyweight these days. Although as of 3.1 at least the need to write your programs in XML is going away...
I'd argue that the right time to start writing Java EE applications is right now. With Java EE 6, JBoss AS 7 and frameworks such as Arquillian, Java EE is a pleasure to work with.
I hate this kind of post. It's the tech equivalent of "You're a stupidhead". If you want to criticize Java then at least make some meaningful points. Just off the top of my head:
- Java logging is a clusterfuck
- Something as simple as wanting symbolic links in a Maven build requires a third party plugin, last updated in 2007 (maven-junction-plugin) that requires something no longer in the central repo;
- No lambdas yet;
- Type erasure in generics and the consequences thereof (eg inability to create generics of primitive types unlike C#);
- Checked exceptions;
- No function references, lambdas, etc (still a year+ away);
- Eclipse is a hot mess (IMHO). And, no, for Java at least, vim/emacs simply are no better. IntelliJ is but for some reason they insist on making it hard to make plugins as their API changes every major version. Jetbrains seems to be going out of their way to make it hard;
And as far as Spring goes, it's probably long in the tooth now but people either forget or never knew just how influential Spring was in the early 2000s. Java at that time really was a hotbed for innovation (believe it or not). It may not have invented DI/IoC but it certainly popularized it.
But long class names? Really? Is that all you've got? Who cares?
EDIT: I don't care about the description either. If anything, it's probably poor text from someone who isn't a native English speaker.
As for the layering, it's nit-picking. I had a quick look and found only one use for this: CacheProxyFactoryBean. Perhaps there was more at some point? Who knows? But the subclass seems to be used in the Spring AOP stuff.
The thing that really bothers me about this is the tone. It's a bit like how among a certain set it's popular to deride PHP. In my experience, people who bother to do that (or simply enjoy it when others do) are nearly always closedminded dogmatic fools.
In his defense, I don't think the long class name is the problem he's pointing out.. it's the over-patterned, over-generalized nature of something that barely does anything.
The class's description is "Convenient proxy factory bean superclass for proxy factory beans that create only singletons."
My favorite part is that the first word is "convenient." At the point that you need this class, absolutely nothing about the situation could possibly be considered "convenient."
If you spent your life being inconvenienced by the things you made earlier to make your life convenient, you'll go to extraordinary lengths to make other things that seem to make your life convenient given all the inconveniences you've already created for yourself. It does not really compute that this is another inconvenience you're building for yourself that is going to need another convenient AOP driven bean thing that you will write in a few months to get around the nonsense you burdened yourself with in the first place. It also does not help that everyone (well, at least the people with the money) is buying it and forcing it down their developers throats. If they don't want it, there's always a bunch of guys who are cheaper and will take it....
Yeah, that would be amusing if it was accurate. Only that's not what it does. It is actually a way of extending the bean creation part of the framework that produces singleton scoped proxy objects.
But honestly, I'm kidding around. I'm not arguing the class is silly, or poorly named. I bet it's perfectly named. I'm not arguing the author did a bad thing here, I'm sure he or she did something awesome. All I'm saying is that the context that makes writing that class description necessary is totally hilarious.
Let's just agree on that. It doesn't mean Java sucks or Spring sucks. Big complicated projects sometimes lead to pretty wacky situations and we ought to be able to laugh at them. I'm certainly not suggesting other languages don't have the same culdesacs of lunacy.. they totally all do. Can you imagine the number of times someone's posted "Everything that's wrong with Perl in one line of code" ?
I really don't see any reason to take this stuff so seriously.
The context makes it entirely appropriate. A FactoryBean allows you to construct complex objects, or construct objects Spring can't easily create itself (e.g. JndiFactoryBean). A ProxyFactoryBean builds Spring AOP proxy beans.
As it turns out, there was no need for the class as it has been deprecated. However, providing an abstract singleton scoped proxy factory bean is indeed convenient. If there was a need for a factory that creates AOP proxies then it would be very useful to have an abstract class that implements most of the methods for you, and create them with singleton scope. In that case, AbstractSingletonProxyFactoryBean is sensible.
It's a corner case. It was used by one class, but that was deprecated later, so this was deprecated as there wasn't really a need for the convenience class.
I take this lot of stuff seriously because I see a lot of ignorant pattern bashing by those who haven't taken the time to understand why patterns are very useful and potentially can make OOP code cleaner and easier to maintain.
For the record, I spent 10-12 years coding Java (the last 4 or so w/ Spring). Lots of OOP, lots of pattern based enterprisey big boy stuff. I definitely have a solid (but atrophying) understanding of the concepts. I get that they're the right way to do big Java apps. But Java makes implementing them fucking laborious. Back when that was all I knew, it seemed elegant and I was used to the scaffolding.. but the truth is that in a number of other languages the same patterns require so much less scaffolding and even thought, that we don't even notice them. They're a given.
I give my users vastly more value-per-line-of-code now than I ever did writing Java.
That said, I have nothing against Java or folks that enjoy doing it... but even when it was a language that I was knee deep in and stoked on, I was able to laugh at some of the shark-jumping complexity of these cartesian products of patterns that would arise.
...or it could be a common malady amongst programmer: inability to write clear documentation. I note that it's much clearer in the most recent documentation.
Totally. I've worked on some frameworks, and I get that things get hairy supporting some really crazy general and re-useable concepts. I'm not even saying Spring is shitty, or Java is shitty or anything. I don't really care... but don't you dare tell me that class isn't hilarious, because it is.
Indeed, the class isn't hilarious. Perhaps the class name initially boggles the mind, but when you learn what it does not only does it make sense, but you probably would be hard pressed to find a better name!
Hah. I'm not saying Spring is a good framework, I don't know it that well. But try building an app without any framework at all. Getting frameworks right is hard - they need to be abstract enough to be flexible, but not so abstract that you end up with a "general-purpose tool-building factory factory factory" when you want the framework to give you a hammer.
I guess there's a rule in place that hides the down arrow for comments in reply to my own or something. Anyways. I'd downvote if I could. The guy is almost certainly not an idiot. That's a rude, shitty thing to say.
Further, if you accept that Spring is a good idea (which in my opinion is equivalent to accepting that Java has major shortcomings that require something like Spring to overcome) then this class is likely plenty reasonable. Like other commenters have pointed out, frameworks are hard. Java makes them harder. In the context where Spring and Java are givens, I'm sure the author of the above is a very handy chap to know.
Be nicer.
[Edit: To be clear. I want to make sure there's no confusion that the point of my original comment was that the class is hilarious. Not that it's not justified, or that the author is foolish, or that Java is awful, or that Spring is awful. I don't have very strong opinions about any of those things.. other than assuming a committer on such a huge, demonstrably successful project is plenty smart and did the poor chaps who are in the unfortunate position of needing this class a great service.]
I've used Java for 10 years. I've never used Spring. I've never created an AbstractFactorySingleton. I've never used XML. There's nothing in Java that says you have to use anything in particular, apart from the runtime (Extremely solid), and the basic language syntax (IMHO nice enough).
OK, maybe they're not an idiot. Maybe it's warranted. I'd say it's probably over engineered stupidity though.
Even so, the title is like pointing to a stupidly constructed house and calling it "Everything that is wrong with bricks".
If you don't know what it's used for, or the purpose it was written for, then you aren't in a position to judge if it's stupid or not. I can assure you, it has a purpose, and that purpose is not stupid. The fact that the reason for the class is somewhat obscure and somewhat of a corner case does not make it unnecessary.
well, but all java coders are this way. I'm working on a rails app built by java coders learning rails and it's, sadly, a pain in the ass, it's not that the code is malfunctioning, just that everything looks like it's a quantic mechanics equations when in reality it's just a 10 piece lego. Sure, they're not 100% is this way, but empirically I can state that, I too thought overengineering was beautiful when I was learning it, lame.
Hardly. Firstly, AOP is a very effective and useful programming technique. It's used in a lot of places, and without it OOP would be considerably harder than it necessarily needs to be.
Secondly, this is a class used to extend the Spring framework unobtrusively if it is needed. Most likely you would never need it (if you are even someone who uses Spring, which I somewhat doubt... If you are then you should really learn more about the framework you use) but there are doubtless folks who may need it at some point for some super complex or out of the ordinary project you haven't even dreamed of yet.
Given that Spring is mostly used via annotations or config files, yes this is indeed useful. It helps to know what you are criticising before you show your ignorance.
A factory bean is a class that creates factories. You'll almost never need to create your own as you normally use the ones Spring provide for you. And with annotations, you'll likely never even notice them.
A proxy factory bean is used for Aspect Oriented Programming in the Spring framework. AOP is a fantastic way of doing OOP. Try reading up on it before you knock it. Spring uses AOP via proxies. By using proxies, you don't need to inject bytecode via CGLIB, which while a totally valid way of doing AOP, adds another dependency to your project which you may not want or even need.
Singletons are used by default by Spring, which is an IoC (Inversion Of Control) container. An IoC container is extremely useful as it fully decouples classes from one another - the container handles the coupling and you merely set things such as object creation up via annotations or configuration. One of the considerations needed to be taken into account when using Spring for object creation is to decide whether each object is created once and once only by the factory bean, or if multiple instances should be created. You usually use a singleton bean in Spring - otherwise you have to introduce tighter bean coupling with other beans, which kind of defeats the purpose of an IoC container.
A bean is a JavaBean, which is a very simple but powerful convention used to allow reusable components in Java.
So what does this do? It's a convenience class used to extend the Spring AOP framework should you need to do so without having to make changes within the Spring framework itself. Almost no application programmers will need to use it. However, if you have a very particular requirement for AOP proxy bean creation that is not currently handled by the Spring framework (unlikely) then you will indeed find it useful, and I dare say it is, indeed, convenient.
In short, ignorance is OK. But mocking something in ignorance is pretty foolish, and your foolishness is on full display here.
P.S. incidentally, Spring is now well past v2.5 and in fact the current version is 3.1.x. It helps to read the most up to date documentation when trying to understand something in a framework. The description of the class in the latest documentation now reads:
Convenient superclass for FactoryBean types that produce singleton-scoped
proxy objects
Only if you isolate it from all context. Within the context of how Spring is built and works, it's all perfectly reasonable. As cletus said above, if someone is going to slag Java, they should really pick something to pick on that is actually deserving.
It's not the long name that's being mocked, it's the underlying problem of which the name is a symptom: that Java tends towards too many layers of abstraction, and the strict object-oriented nature means that every one of those layers is expressed as an inheritance level or a Factory object or a Proxy object, all a dozen levels away from where any action and logic is actually happening.
Way, way, way too narrow. The Java standard library design and "framework meta-pattern" is what's being mocked here. It's java-the-community that we are laughing at via the straightforward label "Java". The fact that java-the-syntax or java-the-runtime can be used to code or deploy good software isn't really the point.
Really? Obviously no single class is that ridiculous (hence the title of the linked article). But that nonsense is pervasive in Java, and largely driven by the standard libraries (less so the core stuff as the more peripheral layers). I specifically remembering Swing being introduced with all the MFC goodness and noticing that they'd defined and implemented a "Model" class to track state for ... a button.
You won't find anywhere near this level of abstraction in the standard library, at least not that I am aware. The Java culture is understandably implicated by this though, because Spring is not some niche framework being perpetrated in some fringe corner of the Java-verse. It is very much the mainstream of Enterprise Java. Of course there are lots of Java developers outside of that set who are doing great work. And a lot of Spring makes sense, or at least it did 8 years ago when I last looked it. This class does seem to reference a sort of endless abstraction maze that resonates with people though.
Last I checked, the standard library wasn't trying to implement an IoC container. Your comment is actually fairly amusing, given that Spring was developed originally as an answer to the overly abstract mess that was the original version of Enterprise JavaBeans.
Interestingly, things like @Inject came after Spring, and were inspired by Spring and a number of other containers.
I was just referring to the standard library in J2SE. Of course it isn't trying to do an IoC container - but there was a comment above about whether or not this is a "Java" issue and it really is not. My last contact with this was before EJB 3 so I wouldn't even try to speak to how Spring and J2EE have evolved to help manage complexity.
I found it troubling for someone to equate one class or a few classes to the whole library, the whole language, or the whole community. Those pervasive nonsense you claimed in Java have certainly work very well and been used to build many systems.
I found the Java standard library to be very good. Why do you have to mock something if you don't agree to it? There's a reason to design and build things certain way. If you don't like it, don't use it. You are not the intended audience. What is this imaginative Java community that you are laughing?
Could it be all these mocking are symptom of your insecure language choice or library choice?
I totally agree on java logging. Lambdas would be nice. Checked exceptions? I love them.
Lastly Eclipse is THE best thing since sliced bread. I LOL'ed when you mentioned vim/emacs in the same sentence. Have you actually used Eclipse on a big code base? It's introspection is such a productivity booster. I've not used jetbrains in a decade, but nothing else out there beats it, hands down. Both in terms of speed and quality.
Did you read what I said? "vim/emacs are [for Java] no better". This was in part to head off the predictable chimes from some of "all IDEs are stupid, (vim|emacs) is the best thing since sliced bread".
My tool of choice for Java is however IntelliJ, which is simply light years ahead of Eclipse (IMHO).
> My tool of choice for Java is however IntelliJ, which is simply light years ahead of Eclipse (IMHO).
I agree.
Eclipse seems to always become unstable once enough plugins are installed. After a few updates and removals it ends up tipping over regularly. I suspect the underlying OSGi plugin system is a tricky thing to get right.
Intellij IDEA seems to "just work".
That said, I prefer coding in Clojure with Aquamacs but I've yet to get Clojure into a production system.
If you haven't used IntelliJ in a decade, how can you be so convinced that Eclipse beats it "hands down"? While they offer many of the same capabilities, most people I know who have used both extensively tend to prefer IntelliJ for Java development.
It's not just a long name. The class makes sense in the context of this framework. The core problem (as others here point out) is that the Java flavor of OOP makes writing this sort of code idiomatic.
On the upside, you feel really smart once you grok all these concepts simultaneously. After a couple years this you get to brand yourself a "Java Architect".
Until, of course, you find you need to use it. Of course, you'll probably never need to use it, nor will you ever see it being used in your particular situation. But hey, it's all over-engineered nonsense, right?
This is a great comment. This is what a Java "Engineer" or "Architect" is supposed to understand. It is complex, but seems too abstracted from programming reality that it makes programming simple things more complicated then they have to be.
All of these things are useful and valid techniques for building scalable, maintainable and extensible code.
Abstract is a pretty basic OO concept. You make an abstract class when you want it to be derived and never used directly.
Singleton is where a class can only ever create one object. Harder than it sounds.
Proxy is where the class interfaces with something else. Again, very useful. Proxies are used by Spring to implement AOP.
Factory - abstracts away the creation of objects, in other words the client object does not need to know how to create objects. It's used extensively in the Spring IoC container.
Beans are object that use simple but powerful conventions of creating reusable components in Java.
Interceptors at used by AOP.
If you use these concepts as they are intended to be used then your code will be cleaner, maintainable and a joy to work with.
The title should have been "Everything that is wrong with Spring ... ". Then it would not have been especially accurate, but more accurate. I like Java better than I like Spring. Spring made a framework out of an idea, but not all ideas should be packaged. Ideas can also be embraced. Dependency injection is an idea that should be embraced, but not as a packaged solution. It is a pattern, not a a software project.
Actually, it would then have been entitled "A class that extends the Spring AOP easily and unobtrusively", or probably just as accurately "everything that is right with Spring".
I seriously don't think you understand that at the core of Spring is an IoC container - it just so happens that Spring does a lot of other useful things.
Regardless of this post (which, indeed, has little to do with Java per-se), Java the language might be outdated for many applications. But I believe it's now pretty widely acknowledged that Java's contribution isn't the language, but the platform. The JVM is the best performing, most stable managed runtime in existence. Not to mention the invaluable runtime profiling an monitoring that is years ahead of anything else out there. The platform (possibly used with some other JVM language) still gives the most bang-for-the-buck for performance critical, scalable applications.
I actually really like Java logging (well, I like SLF4J and logback).
On Ruby, I'm constantly at a loss on how to do logging. Sure, in Rails there's the Rails logger available pretty much everywhere. But if I'm writing a reusable library, I can't count on that. So what do I do? Demand every user of my library configure it with a logger?
The stdlib Ruby logger also has no way to fine-tune log levels by class. In a Rails app, sometimes I want debug level, but I rarely care to see each and every SQL statement. (There tend to be hacks to monkey patch around the common cases suggesting others have been similarly frustrated.) Even if I use log4r or some other logger with more fine-grained tuning, within Rails, everything will be using the same logger object, so the typical Java method of tuning by giving each class its own logger doesn't work.
Bleh. Give me SLF4J with logback any day. When writing a reusable Java library, I really have no qualms about using SLF4J.
Care to explain? Logback is easy to configure and extremely efficient
> Something as simple as wanting symbolic links in a Maven build requires a third party plugin, last updated in 2007 (maven-junction-plugin) that requires something no longer in the central repo;
If you are still using Maven it's your problem. Switch to Gradle and your life will be much better.
> No lambdas yet;
True, but if you really need them use Groovy or Scala. Groovy 2.0 is almost as fast as Java and Scala is fun.
> Type erasure in generics and the consequences thereof (eg inability to create generics of primitive types unlike C#);
True, but doesn't this lack of feature harm framework developers mostly? The same people which the article is critiquing.
> Checked exceptions;
You can just ignore them when you write new code. If you have to deal with code that throws them, just deal with them. Most of the modern frameworks nowadays don't use them.
> No function references, lambdas, etc (still a year+ away);
Groovy, Scala and the favorite kid on the block, Clojure
> Eclipse is a hot mess (IMHO). And, no, for Java at least, vim/emacs simply are no better. IntelliJ is but for some reason they insist on making it hard to make plugins as their API changes every major version. Jetbrains seems to be going out of their way to make it hard;
This is the only point for which I tend to agree. Eclipse is difficult to work with. IntelliJ on the other hand is a valid alternative. These days I mostly code in Sublime Text 2 though.
> Care to explain? Logback is easy to configure and extremely efficient
Logback != "java logging". "Java logging" is some messy combination of JDK logging, Logback, Log4j, Commons Logging, SLF4J, some cruft that fell out of Avalon or Fortress or whatever it was, etc. And then you try to use a library that uses Commons logging alongside another library that uses log4j directly, alongside your code, which really wants to use SLF4J... or you deploy your code, which uses log4j, into JBoss, which configures it's own hacked version of logj4 before your code loads, and you run into needing to figure out RepositorySelectors...
You'd be better off reading from Ludvig Prinn's De Vermis Mysteriis, Friedrich von Junzt's Unaussprechlichen Kulten and the Necronomicon. Ia! Ia! Cthulhu fhtagn! Ph'nglui Mglw'nafh Cthulhu R'lyeh wgah'nagl fhtagn!
> True, but if you really need them use Groovy or Scala. Groovy 2.0 is almost as fast as Java and Scala is fun.
> Groovy, Scala and the favorite kid on the block, Clojure
Java's upcoming lambdas will have lazily-evaluated results from its map, filter, reduce, etc lambdas. Both Scala and Clojure already have their lambdas/functions return lazily-evaluated results, but certainly not Groovy, neither version 1.x nor the just-released version 2.0.4. Groovy's closures only return strictly-evaluated results.
In fact, 2.0.4 was released only 2 weeks after 2.0.2 to fix "some important issues with generics with the stub generator, as well as several related to the static type checking and static compilation features". (Version 2.0.3 was skipped because "it was mistakenly built with JDK 6 instead of JDK 7".) It may be "almost as fast as Java and Scala" but it certainly isn't fun or production-ready.
It fascinates me that I also believe that Java has serious issues, but I differ on dimensions.
Well yes, logging. There is slf4j though. I think that works, although the fact that one needs a metaframework is... interesting.
Eclipse? I love eclipse. I used emacs every day for 2 years, IRC in emacs, news in emacs, EVERYTHING in emacs. Eventually I got sick of IMAP blocking and interrupting the world. I grew to love Eclipse because I realised I could not efficiently comprehend Java code any more without it.
Over-layering is a serious, serious problem in Java. I think I understand your point of view, but a big part of my job is performing code reviews. It really sh%ts me every time to have to jump through the Service, the ServiceImpl, then the Repository, the RepositoryImpl, the Dao, the DaoImpl and... oh, there's the fricking query. Thanks guys.
My huge problem in Java is that I always find 8 classes where 2 would do. The extra classes do serve a purpose; they fulfil stereotyped, expected roles. In some ways the boilerplace reduces cognitive overhead. In other ways, it really does not.
Personally as someone who reviews multi-million line codebases regularly for a living, I am actually terrified of hordes of new Java developers discovering lambdas or acquiring advanced generics. These things are tactical nuclear weapons of source code obfuscation in the hands of people whose judgement (through bitter experience) I no longer really trust.
Spring is not evil, but it does make life difficult because it's hard to follow references. Fortunately, whenever you see an interface Foo you normally just have to jump to FooImpl. Because it turns out that 90% of interfaces are actually not needed; except culturally, stylistically or dogmatically. Personally I think they're over-used, but that's because my observation is that most interfaces (seriously, 90% level) are implemented only once.
Agree on the checked exceptions though. That was a mistake.
I think actually there is nothing wrong with Java as a language, but without sane leadership the corporate culture of it becomes uniquely byzantine.
> "it's not java's fault" (from multiple comments)
languages have opinions. Java is designed around the principle of "everything should be a class" which makes everyone's first instinct to have lots of mutable instances with lots of mutable member variables. Turns out this leads to shitty code in the large.
Compare to Clojure, which supports mostly all the same features as Java, but emphasizes them differently. You can use mutable data, but by default everything is immutable. You can have methods and instances, but its easier to just use a function. Java can do higher order functions and closures, but they're so verbose that its better to choose imperative for/while loops over map/reduce/filter, which don't even come in the standard library. Clojure is designed to make higher order functions and expression-oriented thinking idiomatic, java makes this so difficult as to be not worth pursuing even with a team who already understands how to think this way.
Java's design leads people towards code that you're afraid to touch for fear of disturbing state somewhere else which causes failures unrelated to your change. That's why when you need to fix a bug, in Java, people will expose a hook here and there to make a minimum change that they are sure doesn't break code somewhere else. A decade of changes designed to expose little hooks to not break existing code, you end up with a AbstractSingletonProxyFactoryBean with intercepters and proxies and loaders. Nobody is claiming that AbstractSingletonProxyFactoryBean is an abstraction. It came into existence over time because it was the easiest way to fix bugs and adapt to changing requirements while not breaking existing code.
It's definitely java's fault, and all the best language designers know it.
PS Here's a paper that describes a team who migrated a bunch of excel macros to Java, found that they had built an unmaintainable mess, then took the same team and built it in OCaml, and have been using OCaml ever since. http://queue.acm.org/detail.cfm?id=2038036 - OCaml for the masses, Yaron Minsky, Jane Street
Clojure functions are Java classes. It's not much different from using a Java functional libs. Except that Java will probably be faster as Clojure still doesn't do primitives and stuff (not sure about that one, may be it already does)
You can do all the functional stuff in Java, Clojure is doing exactly that. It will be more verbose, but once you learn the ropes it just looks different, it is not different.
it was a method i extracted from some old code somewhere else while i fixed a bug in it. the functional programmer in me sees opportunities to generalize (and prevent future bugs here), so i try to refactor it into a defaultdict and a higher order function, using guava. 20 minutes later I still don't have working code, i revert, curse the gods because this is a 30 second refactor even in python let alone clojure, and move on, i don't have time for this shit.
its not about it looking different. it doesn't matter that closures and objects are turing equivalent. its a syntax problem.writing functional java code has too much friction and is not worth it.
this is not even getting into how any hardcore functional code needs persistent data structures to be fast, which means a) you need to write your code against a 3rd party collections library instead of JDK provided implementations, and b) any interop with 3rd party code will now imply a conversion (copy) at the boundary.
Isn't it exactly why it is not good idea (or at least not convenient) to do so in Java, even if functional approach would be best suited for the task at hand?
Of course you can do everything in Java what you can do in Clojure. You can also manipulate strings and generate reports in an assembler, did you know this? It all boils down to how convenient it is.
Java was not designed for functional stuff, that's all. Saying that you can map a function over collection in Java isn't going to change this.
My comment was about the content or lack thereof of your comment. It wasn't personal. So do down votes indicate people hate people on Hacker News? I don't hate anyone. Is it an attempt at humor to suggest I'm hated? If anyone hates I feel sorry for them, I hate no one.
My opinion goes like this: java is a verbose and hard-to-change language compared to ruby/python/js/etc so people think "I'm going to create this extra layer/abstraction just in case someone needs to change/use it for something else later" while dynamic language guys just solve the problem at hand and then improve it later because it's painless to do so.
Agree. Java coders seem to have a habit of over-solving the problem with useless layers of abstraction. I recall trying to create a silly video editor in Java, using a common vendor framework for media files, simply opening the file then extracting the Nth frame involved instantiating 12 layers of classes, like nested Russian dolls, every layer just as useless as it's parent class. What a waste of time it was to consider Java.
It's more a problem relating to the fact that many projects and their code bases are designed and planned to last for over a decade if not two or more. One simply can't just make drastic changes back and forth, because literally, peoples lives are on the line(let alone how much financial capital is invested...) with lots of written code. I'd grab Java, C++, heck, even C over Python or Ruby, let alone god damn JavaScript for a project which is going to ship after approximated 5 years of development and which has planned maintenance for at least 10 years afterwards. Considering how we miss deadlines, I'd assume such a project would be maintained after 20 or 25 years. Yes, someone would still work with the code base in 2037. Imagine that, and that's not even an unrealistic stretch. Welcome to enterprise software development! Do that with Python, Ruby or JavaScript and I'll give you a cake or two.
"Improve it later because it's painless to do so?" I don't think so. Quick and dirty approach and then fix it later is just the start of future issues, broken designs, infinite refactoring.
I feel java helps a bit more on design scalability. Yes, maybe somewhat overegineered but it certainly does not hurt to think on the future
As one of the commentors pointed out in the original post, that class is helpful for making AOP driven applications. You could also use it in a DSL system if you wanted. Basically with Spring there are a lot of classes, the majority of which you will never use and should probably never use. But if you have the need, you've got a lot of power.
This is truly an issue with Spring, not with Java. An argument could be made that such a class is a symptom of some cultural problem with how Java developers tend to do things, but the OP is not making that point.
The issue with Spring, though, is very real. The key problem that framework authors want to solve is giving programmers the correct slots to place functions in. Oddly, Java is not very good at providing the kinds of slots that seem natural, particularly because of it's lack of lambdas. Plugging a function into a Java project requires that you participate in the inane Type-Name-Game whether you want to or not.
Play this horrible game long enough, and you will get the problematic names that the OP has discovered. And it only gets worse for in-house software.
Similar to the classic dig on C++,
"If you think C++ is not overly complicated, just what is a protected abstract virtual base pure virtual private destructor, and when was the last time you needed one?"
158 comments
[ 3.0 ms ] story [ 220 ms ] threadhttp://news.ycombinator.com/item?id=2807908
A "non-haiku" has been written in its honor:
http://stackoverflow.com/a/891589
You can come up with ugly names for classes in any language.
After years of consulting I can't remember how many times I've walked into an Enterprise Java Shop(TM) to find TemporalSystemLoadOrganizers, IntransitPredeterminedApplicationUtilitySources, MetaphysicalManipulatitiveQuantityDisorderRecognizers only to find out that at the end of the day these abstract-factory-driven-decorated-decoupled-dynamically-injected-frameworks tend to do such obscure/complicated things as "Update a user's first name" or "Show the last item the user has purchased"...
Again, not Java's fault and no question you can write very fast, beautiful and clear code in Java. I'm sure every language has specific warts and most of them probably reside more with the community than the syntax.
For example, assume I've got a list of students, and I want to show all the ones who haven't taken at least one exam, sorted by last name. Here's the relevant pseudocode in Rails:
class.students.select {|student| student.tests.inject(false) {|acc, test| acc || (!test.taken? )}}.sort {|a,b| a.last_name <=> b.last_name}
That just flows from my keyboard as a Ruby/Rails programmer, is pretty much instantly comprehensible to other Rails programmers, and (while others might disagree with stylistic choices, variable names, or whether to use that weird &syntax to do the sort) would be considered "good enough Rails code to ship."
I will take the liberty of pasting my Java implementation into a gist -to avoid breaking HN:
https://gist.github.com/3760402
A nice, svelte 38 line method, which will be reused via copy/paste a hundred places in my codebase.
Incidentally, at my previous Big Freaking Enterprise job, the user need "Make a page for a class where we can see all students who haven't..." would get quoted to them as "No problem, that will cost you $1,000. Are we green-lit to implement or do you want docs written first ($250)?", because the core logic I've shown you is the tip of the iceberg of how sucky that experience is going to be. We haven't even started with the XML files and annotations required to hook the new actions together yet. By comparison, as a Rails developer, in lieu of getting you to sign off on a $1,000 line-item to your next invoice I'm inclined to show you a totally working page and ask you "Is this what you wanted?" because implementing it is easier than talking about implementing it.
can be reduced even further using the all? method
!student.tests.all?(&:taken?)
And that's precisely the issue.
It's a part of a third-party open-source library that implements a "dependency injection container". It's a pretty abstract concept to begin with - of course it's going to need to do high-level, head-in-the-clouds-type stuff that on first glance you think you would never need.
And it's not about the language per se. (You can write clean, simple code in Java, but you would have to write it pretty much from scratch.) It's about Java culture, which encourages this kind of stuff.
And yes, I had been a Java programmer for many years. I used to like the language at some point. But several integration projects made me like its culture less and less.
Similar to "nobody got fired for buying IBM", the mindset was that "nobody got fired for building layers of abstraction just in case."
It's the culmination of the second system effect.[1] Without a pervasive unit testing culture, the big enterprise answer to "what if" is "let's add a point of flexibility here."
Obviously, people should be held responsible for building unnecessary abstraction layers like that. They waste time and are often wrongly abstracted, so when you do need to go in to refactor, you end up having to fight the pre-existing "what if" abstraction.
[1] http://c2.com/cgi/wiki?SecondSystemEffect
Seriously though, if you are going to rehash this tired schtick then at least make intelligent points about the problems with the language. I have been writing Java for over a decade and I can tell you are a number.
JavaDocs is one of the earliest (popular) standard tools for documentation, so I'll give it that, but it suffers a number of problems - problems which are partly relics of the Java language, but that's no excuse.
JavaDocs is too focused on documenting classes, rather than documenting functionality (Python docs, by contrast, focus on modules, which are themselves arbitrary chunks of code with connected functionality).
JavaDocs doesn't make the package/class hierarchy terribly clear - this is intrinsically tied to Java's overcomplicated class hierarchy and needlessly complicated package system, but it carries over into poor documentation as well.
JavaDocs also doesn't have a culture of providing complete examples of code, which exacerbates the two aforementioned problems.
That said, JavaDocs has inspired other good tools, so I'll give it some credit for that and write these criticisms off as vestiges from a time long past.
Now if you wanted to criticize Spring and cargo-cult enterprise Java development, I think that's reasonable.
Also, many of the abstractions start as good ideas, but they soon become a hammer and everything else becomes an AbstractNailFactoryInterfaceManagerProxy.
For a more technically critical look at Java the language, I recently stumbled on this video while watching a Scala talk Martin Odersky recommended in the first few sessions of his new Coursera class... http://www.youtube.com/watch?v=hcY8cYfAEwU
It's pretty meaty, although it looks only at Java 1.0. Many of the criticisms aren't things I would have necessarily thought of first, and it gave me something to think about in terms of what my own priorities are. (For instance, the lack of first-class functions and closures gets no mention at all)
Java the language certainly enforces a certain kind of programming, that Steve Yegge so succinctly identified as a "kingdom of nouns". I'm not sure if that constitutes a culture or not but it does strongly influence the kinds of programs you end up writing in Java. I've experienced some shared technical culture between companies I've worked at that used Java heavily, but of course my experience is just anecdotal.
Here's a blogpost from an HNer that argues there is such a thing as "Java shop politics" and that companies that develop certain kinds of large monolithic software written in Java and C++ tend to share something, which is not desirable. I don't really have enough experience to agree or disagree, but it's an interesting read: http://michaelochurch.wordpress.com/2012/04/13/java-shop-pol...
I found that the whole notion of finding some bad examples of a practice and then offer that as a proof to invalidate the whole practice very distasteful. The lynching mob incited from the blog post's false information just shows how far it can go.
There's nothing wrong with it, if you think OO is a good approach to structuring programs. I happen to think it's not that great an approach. But Java gives you no option, you can't have just "some OO" and some of something else. I think that's a serious mistake. You're welcome to disagree.
I didn't say FP is a holy grail. However in my limited experience, OO is definitely not either.
All that said, there's nothing wrong with constructive criticism, which is all I've been trying to provide. I don't think I've participated in any lynch mob, I'm sorry if you construed my light jab at "Java culture" to be offensive.
I think any UI designer would tell you that a culture doesn't happen spontaneously. Why do Quora, StackOverflow, and Yahoo! Answers feel like very different products despite providing essentially the same functionality?
You can say this about any language and its community, too, not just Java. And it works both ways. Perl, for all its faults, provides a very easy way to package libraries and a well-organized repository for doing so, hence the comprehensiveness of CPAN packages[1].
Java's culture is a result of the fact that Java-the-language promotes badly designed pseudoabstractions intended to guard against bad design. Java provides broken abstractions because it is itself a broken abstraction - the class is a very poor abstraction over an object, and an inconsistent one at that (Java supports multiple kinds - in the mathematical sense - a design choice which impacts the way people use it).
[1] This is particularly true if you turn the clock back ten years and compare with the state of programming languages back then.
> As others have pointed out, this really should be titled "Everything that's wrong with Java culture ..."
was that the OP didn't actually have much technical criticism of the language. If anything it's not "everything that's wrong" because it's missing a lot. I wasn't trying to defend Java.
Though sometimes amusing examples do help to illustrate, when used carefully to supplement the main point!
[1] http://stackoverflow.com/questions/186964/java-core-api-anti...
This is a result of people reading their design patterns book and thinking they've mastered the world, but in reality it's just papering over the cracks of the deficiencies of Java.
I suspect once Java 8 comes out stuff like this will slowly disappear from the radar.
If you really want to see something funny look at JavaScript code which combines integers and strings. Things that Java would complain about immediately, JavaScript tries to actually run with unpredictable results.
Java, C++ and whatnot are imperative languages, of course the syntax is gonna be different to declarative languages such as Haskell or Lisp. They're also only alien at first; once you get used to a declarative syntax you never want to write imperative code again. It would be like going back to monochrome after experiencing color monitors.
We have some programmers at work who can't think outside the C++/Java/C# box. They also tend to be the worst programmers even after decades of experience.
In the same way, Java is noisy, I admit that, but it's fast, powerful and fairly easy to understand when executed correctly. I'm not saying you can do the same thing in other languages, but it's a good language for systems, especially middle-ware/server side development. It's horrible for Web Page development since JSPs suck and custom tags never caught on in most development shops (they're used because the framework provided them, but even when .tag files came out few used them to encapsulate screen behavior). But Web Development has moved on to JS on the client and REST on the back, so again Java is pretty good too.
You can't easily build fault-tolerant distributed systems using only classes without concepts such as function purity and data immutability. Java's type system also happens to be neither sound nor correct; casts are everywhere and NullPointerExceptions can fly around. You're constantly working against the language to write safe distributed code. If Java was safe as a language, it wouldn't require so much debugging time. Haskell was an eye opener for this.
For systems programming I now use exclusively C and D. In the end, Java is only a viable option when you don't know any better. Most Javaland programmers I know of also happen to be blub programmers. They don't know unix, regex, functional style, don't write tests and the list goes on. They do, however, know Agile and UML.
Maybe that's what I don't like about Java. It's culture killed technical knowledge and replaced it with bureaucratic management.
- Java logging is a clusterfuck
- Something as simple as wanting symbolic links in a Maven build requires a third party plugin, last updated in 2007 (maven-junction-plugin) that requires something no longer in the central repo;
- No lambdas yet;
- Type erasure in generics and the consequences thereof (eg inability to create generics of primitive types unlike C#);
- Checked exceptions;
- No function references, lambdas, etc (still a year+ away);
- Eclipse is a hot mess (IMHO). And, no, for Java at least, vim/emacs simply are no better. IntelliJ is but for some reason they insist on making it hard to make plugins as their API changes every major version. Jetbrains seems to be going out of their way to make it hard;
And as far as Spring goes, it's probably long in the tooth now but people either forget or never knew just how influential Spring was in the early 2000s. Java at that time really was a hotbed for innovation (believe it or not). It may not have invented DI/IoC but it certainly popularized it.
But long class names? Really? Is that all you've got? Who cares?
EDIT: I don't care about the description either. If anything, it's probably poor text from someone who isn't a native English speaker.
As for the layering, it's nit-picking. I had a quick look and found only one use for this: CacheProxyFactoryBean. Perhaps there was more at some point? Who knows? But the subclass seems to be used in the Spring AOP stuff.
The thing that really bothers me about this is the tone. It's a bit like how among a certain set it's popular to deride PHP. In my experience, people who bother to do that (or simply enjoy it when others do) are nearly always closedminded dogmatic fools.
The class's description is "Convenient proxy factory bean superclass for proxy factory beans that create only singletons."
Seriously? That's fucking hilarious.
"Added a new superclass because you wouldn't believe how hard it was to to create beans that create beans that create only singletons!"
Turtles all the way down.
I'm curious: what would you name that class?
But honestly, I'm kidding around. I'm not arguing the class is silly, or poorly named. I bet it's perfectly named. I'm not arguing the author did a bad thing here, I'm sure he or she did something awesome. All I'm saying is that the context that makes writing that class description necessary is totally hilarious.
Let's just agree on that. It doesn't mean Java sucks or Spring sucks. Big complicated projects sometimes lead to pretty wacky situations and we ought to be able to laugh at them. I'm certainly not suggesting other languages don't have the same culdesacs of lunacy.. they totally all do. Can you imagine the number of times someone's posted "Everything that's wrong with Perl in one line of code" ?
I really don't see any reason to take this stuff so seriously.
As it turns out, there was no need for the class as it has been deprecated. However, providing an abstract singleton scoped proxy factory bean is indeed convenient. If there was a need for a factory that creates AOP proxies then it would be very useful to have an abstract class that implements most of the methods for you, and create them with singleton scope. In that case, AbstractSingletonProxyFactoryBean is sensible.
It's a corner case. It was used by one class, but that was deprecated later, so this was deprecated as there wasn't really a need for the convenience class.
I take this lot of stuff seriously because I see a lot of ignorant pattern bashing by those who haven't taken the time to understand why patterns are very useful and potentially can make OOP code cleaner and easier to maintain.
I give my users vastly more value-per-line-of-code now than I ever did writing Java.
That said, I have nothing against Java or folks that enjoy doing it... but even when it was a language that I was knee deep in and stoked on, I was able to laugh at some of the shark-jumping complexity of these cartesian products of patterns that would arise.
I don't see anything hilarious about it.
Further, if you accept that Spring is a good idea (which in my opinion is equivalent to accepting that Java has major shortcomings that require something like Spring to overcome) then this class is likely plenty reasonable. Like other commenters have pointed out, frameworks are hard. Java makes them harder. In the context where Spring and Java are givens, I'm sure the author of the above is a very handy chap to know.
Be nicer.
[Edit: To be clear. I want to make sure there's no confusion that the point of my original comment was that the class is hilarious. Not that it's not justified, or that the author is foolish, or that Java is awful, or that Spring is awful. I don't have very strong opinions about any of those things.. other than assuming a committer on such a huge, demonstrably successful project is plenty smart and did the poor chaps who are in the unfortunate position of needing this class a great service.]
OK, maybe they're not an idiot. Maybe it's warranted. I'd say it's probably over engineered stupidity though.
Even so, the title is like pointing to a stupidly constructed house and calling it "Everything that is wrong with bricks".
Secondly, this is a class used to extend the Spring framework unobtrusively if it is needed. Most likely you would never need it (if you are even someone who uses Spring, which I somewhat doubt... If you are then you should really learn more about the framework you use) but there are doubtless folks who may need it at some point for some super complex or out of the ordinary project you haven't even dreamed of yet.
A factory bean is a class that creates factories. You'll almost never need to create your own as you normally use the ones Spring provide for you. And with annotations, you'll likely never even notice them.
A proxy factory bean is used for Aspect Oriented Programming in the Spring framework. AOP is a fantastic way of doing OOP. Try reading up on it before you knock it. Spring uses AOP via proxies. By using proxies, you don't need to inject bytecode via CGLIB, which while a totally valid way of doing AOP, adds another dependency to your project which you may not want or even need.
Singletons are used by default by Spring, which is an IoC (Inversion Of Control) container. An IoC container is extremely useful as it fully decouples classes from one another - the container handles the coupling and you merely set things such as object creation up via annotations or configuration. One of the considerations needed to be taken into account when using Spring for object creation is to decide whether each object is created once and once only by the factory bean, or if multiple instances should be created. You usually use a singleton bean in Spring - otherwise you have to introduce tighter bean coupling with other beans, which kind of defeats the purpose of an IoC container.
A bean is a JavaBean, which is a very simple but powerful convention used to allow reusable components in Java.
So what does this do? It's a convenience class used to extend the Spring AOP framework should you need to do so without having to make changes within the Spring framework itself. Almost no application programmers will need to use it. However, if you have a very particular requirement for AOP proxy bean creation that is not currently handled by the Spring framework (unlikely) then you will indeed find it useful, and I dare say it is, indeed, convenient.
In short, ignorance is OK. But mocking something in ignorance is pretty foolish, and your foolishness is on full display here.
P.S. incidentally, Spring is now well past v2.5 and in fact the current version is 3.1.x. It helps to read the most up to date documentation when trying to understand something in a framework. The description of the class in the latest documentation now reads:
http://static.springsource.org/spring/docs/current/javadoc-a...Only if you isolate it from all context. Within the context of how Spring is built and works, it's all perfectly reasonable. As cletus said above, if someone is going to slag Java, they should really pick something to pick on that is actually deserving.
Interestingly, things like @Inject came after Spring, and were inspired by Spring and a number of other containers.
Could it be all these mocking are symptom of your insecure language choice or library choice?
Lastly Eclipse is THE best thing since sliced bread. I LOL'ed when you mentioned vim/emacs in the same sentence. Have you actually used Eclipse on a big code base? It's introspection is such a productivity booster. I've not used jetbrains in a decade, but nothing else out there beats it, hands down. Both in terms of speed and quality.
My tool of choice for Java is however IntelliJ, which is simply light years ahead of Eclipse (IMHO).
I agree.
Eclipse seems to always become unstable once enough plugins are installed. After a few updates and removals it ends up tipping over regularly. I suspect the underlying OSGi plugin system is a tricky thing to get right.
Intellij IDEA seems to "just work".
That said, I prefer coding in Clojure with Aquamacs but I've yet to get Clojure into a production system.
Yoxos allows the creation of eclipse profile that make it easier to have stable eclipse.
If you have a lot of eclipse users, I think yoxos is the way to go.
But I still use IntelliJ at home :)
NB: I m talking about this yoxos: https://yoxos.eclipsesource.com/
On the upside, you feel really smart once you grok all these concepts simultaneously. After a couple years this you get to brand yourself a "Java Architect".
Abstract is a pretty basic OO concept. You make an abstract class when you want it to be derived and never used directly.
Singleton is where a class can only ever create one object. Harder than it sounds.
Proxy is where the class interfaces with something else. Again, very useful. Proxies are used by Spring to implement AOP.
Factory - abstracts away the creation of objects, in other words the client object does not need to know how to create objects. It's used extensively in the Spring IoC container.
Beans are object that use simple but powerful conventions of creating reusable components in Java.
Interceptors at used by AOP.
If you use these concepts as they are intended to be used then your code will be cleaner, maintainable and a joy to work with.
I seriously don't think you understand that at the core of Spring is an IoC container - it just so happens that Spring does a lot of other useful things.
So you'd rather see every project that wants to use DI, roll their own DI implementation?
On Ruby, I'm constantly at a loss on how to do logging. Sure, in Rails there's the Rails logger available pretty much everywhere. But if I'm writing a reusable library, I can't count on that. So what do I do? Demand every user of my library configure it with a logger?
The stdlib Ruby logger also has no way to fine-tune log levels by class. In a Rails app, sometimes I want debug level, but I rarely care to see each and every SQL statement. (There tend to be hacks to monkey patch around the common cases suggesting others have been similarly frustrated.) Even if I use log4r or some other logger with more fine-grained tuning, within Rails, everything will be using the same logger object, so the typical Java method of tuning by giving each class its own logger doesn't work.
Bleh. Give me SLF4J with logback any day. When writing a reusable Java library, I really have no qualms about using SLF4J.
Care to explain? Logback is easy to configure and extremely efficient
> Something as simple as wanting symbolic links in a Maven build requires a third party plugin, last updated in 2007 (maven-junction-plugin) that requires something no longer in the central repo;
If you are still using Maven it's your problem. Switch to Gradle and your life will be much better.
> No lambdas yet;
True, but if you really need them use Groovy or Scala. Groovy 2.0 is almost as fast as Java and Scala is fun.
> Type erasure in generics and the consequences thereof (eg inability to create generics of primitive types unlike C#);
True, but doesn't this lack of feature harm framework developers mostly? The same people which the article is critiquing.
> Checked exceptions;
You can just ignore them when you write new code. If you have to deal with code that throws them, just deal with them. Most of the modern frameworks nowadays don't use them.
> No function references, lambdas, etc (still a year+ away);
Groovy, Scala and the favorite kid on the block, Clojure
> Eclipse is a hot mess (IMHO). And, no, for Java at least, vim/emacs simply are no better. IntelliJ is but for some reason they insist on making it hard to make plugins as their API changes every major version. Jetbrains seems to be going out of their way to make it hard;
This is the only point for which I tend to agree. Eclipse is difficult to work with. IntelliJ on the other hand is a valid alternative. These days I mostly code in Sublime Text 2 though.
Logback != "java logging". "Java logging" is some messy combination of JDK logging, Logback, Log4j, Commons Logging, SLF4J, some cruft that fell out of Avalon or Fortress or whatever it was, etc. And then you try to use a library that uses Commons logging alongside another library that uses log4j directly, alongside your code, which really wants to use SLF4J... or you deploy your code, which uses log4j, into JBoss, which configures it's own hacked version of logj4 before your code loads, and you run into needing to figure out RepositorySelectors...
You'd be better off reading from Ludvig Prinn's De Vermis Mysteriis, Friedrich von Junzt's Unaussprechlichen Kulten and the Necronomicon. Ia! Ia! Cthulhu fhtagn! Ph'nglui Mglw'nafh Cthulhu R'lyeh wgah'nagl fhtagn!
> True, but if you really need them use Groovy or Scala. Groovy 2.0 is almost as fast as Java and Scala is fun.
> Groovy, Scala and the favorite kid on the block, Clojure
Java's upcoming lambdas will have lazily-evaluated results from its map, filter, reduce, etc lambdas. Both Scala and Clojure already have their lambdas/functions return lazily-evaluated results, but certainly not Groovy, neither version 1.x nor the just-released version 2.0.4. Groovy's closures only return strictly-evaluated results.
In fact, 2.0.4 was released only 2 weeks after 2.0.2 to fix "some important issues with generics with the stub generator, as well as several related to the static type checking and static compilation features". (Version 2.0.3 was skipped because "it was mistakenly built with JDK 6 instead of JDK 7".) It may be "almost as fast as Java and Scala" but it certainly isn't fun or production-ready.
Is that the only thing you think is wrong?
Well yes, logging. There is slf4j though. I think that works, although the fact that one needs a metaframework is... interesting.
Eclipse? I love eclipse. I used emacs every day for 2 years, IRC in emacs, news in emacs, EVERYTHING in emacs. Eventually I got sick of IMAP blocking and interrupting the world. I grew to love Eclipse because I realised I could not efficiently comprehend Java code any more without it.
Over-layering is a serious, serious problem in Java. I think I understand your point of view, but a big part of my job is performing code reviews. It really sh%ts me every time to have to jump through the Service, the ServiceImpl, then the Repository, the RepositoryImpl, the Dao, the DaoImpl and... oh, there's the fricking query. Thanks guys.
My huge problem in Java is that I always find 8 classes where 2 would do. The extra classes do serve a purpose; they fulfil stereotyped, expected roles. In some ways the boilerplace reduces cognitive overhead. In other ways, it really does not.
Personally as someone who reviews multi-million line codebases regularly for a living, I am actually terrified of hordes of new Java developers discovering lambdas or acquiring advanced generics. These things are tactical nuclear weapons of source code obfuscation in the hands of people whose judgement (through bitter experience) I no longer really trust.
Spring is not evil, but it does make life difficult because it's hard to follow references. Fortunately, whenever you see an interface Foo you normally just have to jump to FooImpl. Because it turns out that 90% of interfaces are actually not needed; except culturally, stylistically or dogmatically. Personally I think they're over-used, but that's because my observation is that most interfaces (seriously, 90% level) are implemented only once.
Agree on the checked exceptions though. That was a mistake.
I think actually there is nothing wrong with Java as a language, but without sane leadership the corporate culture of it becomes uniquely byzantine.
languages have opinions. Java is designed around the principle of "everything should be a class" which makes everyone's first instinct to have lots of mutable instances with lots of mutable member variables. Turns out this leads to shitty code in the large.
Compare to Clojure, which supports mostly all the same features as Java, but emphasizes them differently. You can use mutable data, but by default everything is immutable. You can have methods and instances, but its easier to just use a function. Java can do higher order functions and closures, but they're so verbose that its better to choose imperative for/while loops over map/reduce/filter, which don't even come in the standard library. Clojure is designed to make higher order functions and expression-oriented thinking idiomatic, java makes this so difficult as to be not worth pursuing even with a team who already understands how to think this way.
Java's design leads people towards code that you're afraid to touch for fear of disturbing state somewhere else which causes failures unrelated to your change. That's why when you need to fix a bug, in Java, people will expose a hook here and there to make a minimum change that they are sure doesn't break code somewhere else. A decade of changes designed to expose little hooks to not break existing code, you end up with a AbstractSingletonProxyFactoryBean with intercepters and proxies and loaders. Nobody is claiming that AbstractSingletonProxyFactoryBean is an abstraction. It came into existence over time because it was the easiest way to fix bugs and adapt to changing requirements while not breaking existing code.
It's definitely java's fault, and all the best language designers know it.
PS Here's a paper that describes a team who migrated a bunch of excel macros to Java, found that they had built an unmaintainable mess, then took the same team and built it in OCaml, and have been using OCaml ever since. http://queue.acm.org/detail.cfm?id=2038036 - OCaml for the masses, Yaron Minsky, Jane Street
You can do all the functional stuff in Java, Clojure is doing exactly that. It will be more verbose, but once you learn the ropes it just looks different, it is not different.
it was a method i extracted from some old code somewhere else while i fixed a bug in it. the functional programmer in me sees opportunities to generalize (and prevent future bugs here), so i try to refactor it into a defaultdict and a higher order function, using guava. 20 minutes later I still don't have working code, i revert, curse the gods because this is a 30 second refactor even in python let alone clojure, and move on, i don't have time for this shit.
its not about it looking different. it doesn't matter that closures and objects are turing equivalent. its a syntax problem.writing functional java code has too much friction and is not worth it.
this is not even getting into how any hardcore functional code needs persistent data structures to be fast, which means a) you need to write your code against a 3rd party collections library instead of JDK provided implementations, and b) any interop with 3rd party code will now imply a conversion (copy) at the boundary.
Still, in case you were interested, I commented on your gist with a potential solution.
Isn't it exactly why it is not good idea (or at least not convenient) to do so in Java, even if functional approach would be best suited for the task at hand?
Of course you can do everything in Java what you can do in Clojure. You can also manipulate strings and generate reports in an assembler, did you know this? It all boils down to how convenient it is.
Java was not designed for functional stuff, that's all. Saying that you can map a function over collection in Java isn't going to change this.
I dare you to find this kind of atrocity in Play Framework 1 (written fully in Java) or in Play 2's Java code.
"I had a problem and thought to use Java - now I have a ProblemFactory"
.. and thats WRONG!
The issue with Spring, though, is very real. The key problem that framework authors want to solve is giving programmers the correct slots to place functions in. Oddly, Java is not very good at providing the kinds of slots that seem natural, particularly because of it's lack of lambdas. Plugging a function into a Java project requires that you participate in the inane Type-Name-Game whether you want to or not.
Play this horrible game long enough, and you will get the problematic names that the OP has discovered. And it only gets worse for in-house software.
It's concise, precise, clear functional description of the class. It's also a profound commentary on the shortcomings of the Java ecosystem.
If you enjoyed this, recommended reading:
http://steve-yegge.blogspot.com/2006/03/execution-in-kingdom...
This is common stuff in enterprise software world.