6 ms·
Verbosity is not Java’s fault
- kevingadd 17y agoConveniently ignoring the fact that Java, by default, includes lots and lots of unnecessarily verbose APIs, and in many cases you're stuck using them - then yes, verbosity is not Java's fault.
- _delirium 17y agoYeah, a more accurate title could have been: Java's verbosity is due to its API, not the underlying language. It's still somewhat interesting to me to decouple the two, though. There are some things that are verbose and cumbersome in Java due to the way the language fundamentally works: for example, no anonymous functions means that if you want to pass a simple one-time-use function to sort, you have to create a whole new file with your sort functor. But the examples in this blog post could've been fixed by just having designed the API differently, or even had the same underlying API but added a set of convenience wrappers for the common cases.
- pvg 17y agoyou have to create a whole new file with your sort functor. You don't. You can use an inner class. An anonymous one, if you like. It's more verbose than your typical lambda expression but it's not 'a whole new file' by any stretch.
- _delirium 17y agoAh right, I'm not sure why that skipped my mind; I've even done that before. I suppose that adds to the general view of the linked post that Java-the-language isn't actually inherently that verbose, but the JVM APIs are.
- wolfgke 17y ago> for example, no anonymous functions means that if you want to pass a simple one-time-use function to sort, you have to create a whole new file with your sort functor. No you don't have to. Simply create an anonymous class deriving from your sort functor interface. With anonymous functions it would still be shorter, I have to admit. But it is less cumbersome than the way you suggest.
- derefr 17y agoThose aren't specifically Java APIs, though, they're JVM APIs—Scala and Clojure expose them as well. Are Scala and Clojure verbose? If not, why not? And whatever your response to that, can that same response be retroactively applied to Java, now that we know how to do it?
- pvg 17y agoIn many cases, they are the Java APIs, there really aren't 'JVM APIs'. Java the language comes with a standard set of APIs, if they're not there you can't call it 'Java'. If you were writing a nontrivial UI in Swing in Clojure or Scala, it will likely be fairly verbose.
- viraptor 17y agoIsn't it the case, that most places will require an application in java and with most people knowing only the official API, noone will write code for some custom one that is company-specific? IMO yes - it is Java's official API, it is Java's fault.
- InclinedPlane 17y agoResponse myResponse = new Response(); ResponseType myResponseType = responseTypeFactory.CreateNewDisagreementResponseType(); responseManger.SetResponseType(myResponse, myResponseType); return myResponse;
- jrockway 17y agoThe "new Response()" value is unused.
- InclinedPlane 17y agoGood point, I wanted to have that in there because the constant redundancy of that pattern is a slap in the face to most people who've used dynamic languages or languages with type inference. I've updated the example to avoid reassignment to the same variable.
- jrockway 17y agoYou're preaching to the choir :)
- barrkel 17y agoYou're just agreeing with him though - the only bits of Java, as opposed to API, in there are [()=;.], 'new' and 'return'.
- jrockway 17y agoBut of course, you can't actually put just that in a file and expect it to compile. You have to wrap it with class whatever public static void main ....
- mnemonicsloth 17y agoClojure code uses the same APIs all the time, but manages to be much shorter. Java's verbose APIs are Java's fault, because Java doesn't provide metaprogramming tools to make the boilerplate go away.
- j_baker 17y agoIt may just be me, but interfacing with Java in Clojure is still pretty verbose when compared to regular clojure code. I think you at least have to grant the author that API verbosity is a factor.
- pvg 17y agoIt is, to some extent, Java's 'fault' although it's fuel for endless flamage how much that is a fault. Some stuff is just plain verbose, in part due to lack of type inference - EndlessParametrizedType foo = new EndlessParametrizedType() As to the APIs, some of it is due to excessively baroque APIs. But even with a well-designed API, in order to provide a reasonable amount of flexible functionality, a lot of the internal structure of the implementation is often exposed so it can be accessed. This is a consequence of static typing - in a dynamic language, you're more likely to just reach into the bowels of an object and pull out, change or replace bits you want. This isn't an option in Java and a flexible API ends up being a composition of a lot of smaller APIs. In the standard library, it's often left to others to provide a simple layer on top that covers the base cases - for instance, Apache Commons mail for Java Mail.
- deleted 17y ago[deleted]
- blasdel 17y agojavac does do type inference, but it only exposes it to you in error messages!
- jrockway 17y agoLies. Java is intrinsically verbose. Say I want to make a class with a read-only attribute "Foo". CLOS: (defclass class () ((foo :reader get-foo :initarg :foo))) Moose: class Class { has 'foo' => ( is => 'ro' ); } Java: class Class { private String foo; public Class(String foo) { // named initargs are clearly for losers this.foo = foo; } }; Notice how a common high-level task requires a manual error-prone implementation, every single time. Java provides only the concepts of "class", "field" and "constructor", while the other languages provide the high-level concept of an "attribute", which is what the programmer actually wants. (The first concept is easy for the language implementor, the second concept is easy for the practicing programmer.) I should also point out how the verbosity exists only for the sake of being verbose, not for creating more reliable software. Perl and CLOS assume I want named initargs, making use of my class self-documenting: (make-instance 'class :foo 42 :bar 123) Class->new( foo => 42, bar => 123) That's verbose, but it makes the code very easy to read and write. No guessing about what slot is being set to what value. With Java, though, it's anyone's guess as to what's going on: new Class(42, 123); The only way to know which field gets set to which value is to Read The Fine Source: public Class(int bar, int foo){ this.foo = bar; this.bar = foo; System.Utils.delete_users_pr0n_stash(); } foo does get set to 42, but only by accident... and there are unexpected side effects. So much less typing though! cough. Another common programming pattern is reusing code. (I hear people like doing that.) Say you have classes representing numbers, and you want to add a "not equals" method to each type. That's easy, you can just write a generic role like: role Eq { requires 'equal'; method not_equal($a: $b){ return !$a->equal($b); } } Then I can easily reuse that extremely-complex "not_equal" method: class Int with Eq { has value => ( is => 'ro', required => 1 ); method equals($a: $b){ return $a->value == $b->value; } } Int->new( value => 42 )->not_equals( Int->new( value => 123 ) ); # True In Java, I can still maintain a similar interface: interface Eq { public bool equal(Eq that); // Eq is not really the type I want, but whatever. public bool not_equal(Eq that); } But the implementation can't be shared: class Int implements Eq { private int value; public Int(int value){ // didn't we just say "int value" like one line ago? this.value = value; } public bool equal(Int that){ return this.value == that.value; } public bool not_equal(Int that){ return !this.equal(that); } } This is both verbose and error-prone. (I will also point out that Java calls Eq "Comparable" and uses the "implements" keyword instead of "with". But this is petty. I'm surprised they were happy with "implements" and didn't choose the clearer expression "implementsTheInterfaceThatIAmAboutToTypeRightAfterIAmDoneTypingThis". Your editor can type that for you, after all...) But wait, we can use the strategy pattern to save us! class NotEqualStrategy { public bool not_equal(Eq a, Eq b){ return !a.equal(b); } } class Int { private NotEqualStrategy not_equal_strategy; private value; public Int(NotEqualStrategy nes, int value){ this.not_equal_strategy = new; this.value = value; } public bool equal(Int that){ return this.value == that.value; } public bool not_equal(Int that){ return not_equal_strategy.not_equal(this, that); } } At least I don't have to cut-n-paste the logic anymore, but it's still very verbose. Imagine you had to delegate more than one method -- you can do it, but it involves a ton of meaningless code. In Perl, I can just say: class NotEqualsStrategy { method not_equal(Eq $a, Eq $b){ return !$a->equal($b); } } class Int { has 'not_equals_strategy' => ( is => 'ro', isa => 'NotEqualStrategy', required => 1, handles => ['not_equal'], ); has 'value' => ( is => 'ro' ); method equal(Int $a: Int $b){ $a->value == $b->value; } } Notice how I didn't have to type the cut-n-paste delegation; the language did it for me. I didn't have to type it, I don't have to look at it, and I can't accidentally fuck it up. That's what programming languages are supposed to do for you, and that's what Java doesn't do. In conclusion, Java is verbose, and verbosity is harmful.
- bad_user 17y agoOf course it's Java's fault ... sure, you can design clean and easy-to-use APIs but it takes a considerable amount of effort and Java doesn't help you. I simply don't get some of its design choices ... operator overloading is not harmful if implemented right, checked exceptions were a bad idea, and why can't it have local type inference or proper closures and why can't developers define their own stack-allocated primitives? Where these really that hard or dangerous to blend in?
- thomasfl 17y agoYes, it would help a lot if Java at least had a type inference system like scala does. A lot of the time and effort that goes into programming is used to make code more compact and readable. That's hard to accomplish in java.
- radu_floricica 17y agoTrue. Most of the time I end up making a very thing wrapper over the original API, just for the sake of brevity. I honestly thought that's what I was meant to do: the API should be optimized for power, and the local wrapper for usability in the local context. But it's also a matter of style. I just wrote a function the other day to do the equivalent of: Map m = makeMap( "key1", "value1", "key2", "value2", "key3", "value3" ); It's perfectly ok to write something like this in java using varargs, but because of ... I don't really know, habituation I guess, it took me learning Clojure to actually think of writing it.
- fauigerzigerk 17y agoThese attempts to deny the obvious are so futile. The lack of object literals, list comprehensions, parameter default values, keyword parameters, generators (yield), first class functions, property syntax, type inference, macros, etc clearly make Java exceptionally verbose. The author's argument seems to be that Java the language cannot possibly be criticised for being verbose as the verboseness of the language clearly pales in comparison to its outrageously verbose APIs. Not a good line of defense in my view.
- j_baker 17y agoThis post has quite possibly the worst name ever. I mean really: who cares whose fault Java's verbosity is? I think it obscures the author's true intent: to show that Java could be made much less verbose given a less verbose standard library. Note: I'm not necessarily saying that I agree with the author.
- axod 17y agoBad programmers create real verbosity. Language choice is largely irrelevant to that. And by verbosity I mean real verbosity. Not the ill advised measure of 'lines of code' or 'tokens'. A good programmer can write extremely concise well written Java. Don't waste too much time on this sort of fluff, or chasing the next 'hot' language. Spend it learning how to become a better programmer. I'd say the main reason Java is wrongly associated with verbosity is two things - It's widely used in corporate environments, where people are taught to do things inefficiently and in the most number of lines possible, and secondly, the use of IDEs, leading to lots of verbose automatically generated crappy code.
- jrockway 17y agoI would like to read some of this "concise" Java. Don't waste too much time on this sort of fluff, or chasing the next 'hot' language. Spend it learning how to become a better programmer. Bad languages get in the way of becoming a better programmer -- they make you program the language rather than program your program. I contend that Java is one of these bad languages. It is too low-level to really let you focus on programming.
- axod 17y agoI've never 'programmed the language'. In any language I've used. I don't understand how people get this mindset. Languages are a moot point. They're all basically the same give or take a few matters of taste (And as I mentioned the probability of typoing and not being caught by compiler/runtime). >> "It is too low-level to really let you focus on programming." Sad you feel that there is no place for low-level programming, I personally find it the most rewarding and enjoyable. I certainly come from the Assembly world though, so perhaps why I don't see much wrong with Java. But you can't say enough times "Choose the tool that best fits the task at hand". >> "I would like to read some of this "concise" Java." Can't really help you there, I haven't seen much well written Java out there in open source projects etc. A lot of it absolutely stinks. Just one data point though, The webserver I use for Mibbit (http,https,async,comet,websocket,sessions,etc) comes in at 6289 LOC. Functionally it's quite a bit ahead of tornado (5803 LOC). So concise Java certainly exists and can be written by competent programmers.
- raganwald 17y agoThe call to action is worth pondering. Can Java's verbosity be eliminated? Maybe not. Can Java programs be made to be less verbose through better design? Yes! It isn't the author's fault, but reading articles like this make me feel like Java supporters want it both ways. They point to Java's tooling and vast herds of libraries as benefits, but when you point out flaws in some implementation they say the language isn't the fault, it's that particular library. On the other side, when criticizing languages like Ruby they are quick to point to practices like monkey-patching as examples of how Ruby permits abuse in practice. Well, which is it? Do we compare languages on the basis of the actual libraries and programs people write? Or do we compare them on the basis of the libraries and programs they could write if they took advantage of the language's features and also had a keen sense of design?
- chromatic 17y agoWell, which is it? It's both. A Language-with-a-capital-L is the libraries it includes, the libraries it allows, and the libraries it makes unnecessary.
- mark_l_watson 17y agoInteresting points on library design to do the heavy lifting (especially the HTML document regular expression example). Still, the main point of the article is not right: Scala is much more concise than Java (as is Clojure). Article was worth reading however.