> I can agree that Java is a verbose language, and sometimes it's really difficult to express an abstraction succinctly as compared to some other languages. I can agree that it's also easy for people to run wild and over abstract. However, I think it's just as likely for people to mistake well abstracted code for needlessly verbose code.
See, this is a mistake. Abstraction is not an end in itself; it's there to make life easier and to make things easier to undestand.
Bloat is one of the many things abstraction is supposed to reduce; if an abstraction is increasing cognitive overhead and reducing the signal-to-noise ratio, then we've got ourselves a problem.
For reasons that I cannot comprehend, Java seems to be the only language that seems to have excessive abstraction as a requirement. Not as a convenience, not as a nicety, but as a requirement to do things like Dependency Injection, Inversion of Control, Unit Testing, Mocks, logging, etc. The fact that you need to use entire frameworks to accomplish the functionality that in many languages is covered by a couple functions in a built-in module is a mystery to me.
I'm not the wisest expert, but I have over a decade in a field and I've worked in all sorts of different software, and Java (along with some very badly written .NET systems) seems to be the only technology that requires me to grok a dozen files to understand basic workings of MVC systems with the most elementary of logic. And the thing is, 90% of that code is absolutely useless to the extent of the use cases proposed by the system, and none of its potential extensibility is actually used. You have to ask yourself how come neither Python nor Haskell have these monstruous frameworks.
Sure, it's a lot better now, after having caught up 8 years behind the rest of technologies, but the foundations are notoriously complicated for things that are effortless with other tools.
This points to me towards the idea that Java abstractions have simply been poorly chosen.
> See, this is a mistake. Abstraction is not an end in itself; it's there to make life easier and to make things easier to undestand.
This idea is often repeated in programmer's forums, yet I think it's simply not true. Abstraction is not there to make things easier to understand, it is there to empower you _after_ you understand the abstraction. It is there to pack the knowledge you _already have_ after working with some system, and being able to port it to similar systems.
Let's take math as an example. Understanding the "+" operator is much harder than understanding that if you have two apples and you get another one, then you have three apples. However, once you grasp the "+" operator, you can quickly solve a bunch of related problems where the "+" operator applies.
This does not mean that I disagree with the rest of your comment though. Java's (classical) means of expressing abstractions are fairly limited - basically, you need _interfaces_ for everything. In most cases, this leads to a lot of cognitive overhead that obscures the essence of the abstraction being used.
A simple example of this problem is the lack of function values and lambda types (pre jdk8). Due to these missing features, people expressed the same abstractions by defining interfaces that define some method, and then providing implementations as anonymous classes. That is, instead of defining a function type and then just implementing it, you now have an interface and weird class declarations in your code. To the untrained eye, this is much harder to understand. As a result, some of the programmer's cognitive effort is now spent on this, and hence it becomes harder to understand the more useful part of the code (which is likely some kind of abstraction).
Just to shed some more light into this, consider Haskell's _monads_. Monads are very hard abstractions to grasp. They are much harder to understand than just "doing whatever you want to do and call it a day". However, they become extremely useful once you understand the abstraction and become available to use it without the cognitive overhead.
> Abstraction is not there to make things easier to understand, it is there to empower you _after_ you understand the abstraction. It is there to pack the knowledge you _already have_ after working with some system, and being able to port it to similar systems.
I think some abstractions exist for either reason, and some for both reasons, but either way thanks for saying it this way - you definitely put it better than I did.
In Python there simply doesn't seem to be a DI/IoC container available. So you end up half-assedly writing your own, or just using spaghetti code. I'm tempted to suggest that Python doesn't have these frameworks because it doesn't bother to support writing large programs. Likewise with testing, there's the unittest module but it's not really integrated with a build system or anything else. Java does in fact have some standard library functions for logging, but no-one wastes their time learning them - if all your real projects are going to use log4j, why not just use log4j all the time?
There are certainly unnecessary parts - there's a hell of a lot of bloat in spring - but just doing without frameworks entirely is not the answer.
> In Python there simply doesn't seem to be a DI/IoC container available. So you end up half-assedly writing your own, or just using spaghetti code.
There are plenty available, just not one dominant one.
> I'm tempted to suggest that Python doesn't have these frameworks because it doesn't bother to support writing large programs.
That probably approximate the truth, in that the brittle "large program" architectural style that IoC/DI approaches seek to mitigate the harms of is probably less popular for large systems where Python is used (or at least the Python parts) which favor smaller programs interacting through standardized communication protocols for constructing large systems.
> Likewise with testing, there's the unittest module but it's not really integrated with a build system or anything else.
Since there is no "build" with python, the fact that its unittest module is not integrated with a build system isn't surprising. There are plenty of tools that support integrating unittest (or other python testing frameworks) in workflows, including utilities that do testing on every file save (similar to autotest in Ruby). Obviously, in the absence of a build step, they aren't integrated into a build system, but the workflows are often better because of the absence of a build step.
> In Python there simply doesn't seem to be a DI/IoC container available.
Well, last time I needed something similar on Python, I just loaded the settings from the database, included the wanted code at runtime, and inserted the desired symbols at the local context. Took a bit more than a day to write, and was very appliction specific, but saved a lot of trouble with those crazy constructors that appear on Java.
I am no Python expert, but there must be modules (easyinstall etc) for inversion of control etc in Python too, as there should be in all scripting languages. (Is it really in the std lib of Java?! Ah, maybe I'm not that surprised...)
(I am from a Perl environment which have a bit emphasis on tools/libraries and language extensions, because it is easy to do with automatical tests on most every platform/Perl version.)
Well, it is quite natural that the tools for large code bases are more common in Java. Not only because Java is traditionally used on conceptually larger projects... :-)
Anyway, as a Perl guy I can tell you that DI is commonly used in Perl, if nothing so because of the testing culture.
> For reasons that I cannot comprehend, Java seems to be the only language that seems to have excessive abstraction as a requirement. Not as a convenience, not as a nicety, but as a requirement to do things like Dependency Injection, Inversion of Control, Unit Testing, Mocks, logging, etc. The fact that you need to use entire frameworks to accomplish the functionality that in many languages is covered by a couple functions in a built-in module is a mystery to me.
Modern PHP has cloned that. See for instance the Symfony 2 framework.
> For reasons that I cannot comprehend, Java seems to be the only language that seems to have excessive abstraction as a requirement. Not as a convenience, not as a nicety, but as a requirement to do things like Dependency Injection, Inversion of Control, Unit Testing, Mocks, logging, etc. The fact that you need to use entire frameworks to accomplish the functionality that in many languages is covered by a couple functions in a built-in module is a mystery to me.
So what are you proposing? That everything has to be built in into the platform itself, hidden away from me? In fact, Java not doing so is a big advantage, because it allows me to change the implementation. Otherwise, everything has to be done by the platform developers. I would depend on their resources.
In the Java world, if something is worth to become part of the platform (either a new language feature such as try-with or a new core API or runtime library like Joda Time), it is discussed within the JCP. This created an ecosystem, where I can plan for the next 10 years and not just for the next it-does-everything-dynamic-language cycle-jerk.
BTW. If you want to reduce repetitve tasks, you should use code generation. That's the best abstraction and Java is a nice simple language to generate.
> See, this is a mistake. Abstraction is not an end in itself; it's there to make life easier and to make things easier to undestand.
> Bloat is one of the many things abstraction is supposed to reduce; if an abstraction is increasing cognitive overhead and reducing the signal-to-noise ratio, then we've got ourselves a problem.
I whole-heartedly agree, but I'd caution readers not to conflate abstraction with bloat. If it's bloat, chances are you're abstracting the wrong details, and working on a system suffering from poor cohesion.
> For reasons that I cannot comprehend, Java seems to be the only language that seems to have excessive abstraction as a requirement. Not as a convenience, not as a nicety, but as a requirement to do things like Dependency Injection, Inversion of Control, Unit Testing, Mocks, logging, etc. The fact that you need to use entire frameworks to accomplish the functionality that in many languages is covered by a couple functions in a built-in module is a mystery to me.
I'm not sure I follow. Are you saying that you think it's wrong or inconvenient that these features aren't somehow natively supported by the language? That is, that you'd like to have a grammar/syntax around each one of these things which ultimately boils down to a bunch of hidden runtime anyway?
Maybe it might help to clarify that I'm defending Java the language, not Java the runtime library.
> Java ... seems to be the only technology that requires me to grok a dozen files to understand basic workings of MVC systems with the most elementary of logic
I do agree that web frameworks in Java are one area where there's just tons of bloat, but I still don't think that has anything to do with how the language is designed. My advice: get a better MVC. There's nothing about MVC that says you must use a framework. (Edit: if it's the container that you're fighting with, there are tons of other options out there aside from the mainstream few).
Also, check out the network code in the Linux kernel sometime. Beautiful code, but holy shit do you need to shave a whole heard of yaks the first time you go to read it. The cognitive overhead is high, but each one of those abstractions is there for a reason.
> This points to me towards the idea that Java abstractions have simply been poorly chosen.
Again, given that I'm talking about the language alone, not the runtime library, if you still uphold your response I'd ask you to consider who's fault it might be that the abstractions used in your program(s) are poorly chosen. It's quite rare that it's the fault of the language.
See, this is a mistake. Abstraction is not an end in itself; it's there to make life easier and to make things easier to undestand.
Bloat is one of the many things abstraction is supposed to reduce; if an abstraction is increasing cognitive overhead and reducing the signal-to-noise ratio, then we've got ourselves a problem.
For reasons that I cannot comprehend, Java seems to be the only language that seems to have excessive abstraction as a requirement. Not as a convenience, not as a nicety, but as a requirement to do things like Dependency Injection, Inversion of Control, Unit Testing, Mocks, logging, etc. The fact that you need to use entire frameworks to accomplish the functionality that in many languages is covered by a couple functions in a built-in module is a mystery to me.
I'm not the wisest expert, but I have over a decade in a field and I've worked in all sorts of different software, and Java (along with some very badly written .NET systems) seems to be the only technology that requires me to grok a dozen files to understand basic workings of MVC systems with the most elementary of logic. And the thing is, 90% of that code is absolutely useless to the extent of the use cases proposed by the system, and none of its potential extensibility is actually used. You have to ask yourself how come neither Python nor Haskell have these monstruous frameworks.
Sure, it's a lot better now, after having caught up 8 years behind the rest of technologies, but the foundations are notoriously complicated for things that are effortless with other tools.
This points to me towards the idea that Java abstractions have simply been poorly chosen.