I am an architect at Kayak.com working mainly with Java. I focus on performance problems at work and occasionally on computer graphics as a hobby when I find the time. Derek has posted 5 posts at DZone. View Full User Profile

Two Useless Java Customs

09.12.2008
| 8456 views |
  • submit to reddit

A couple common Java practices that annoy me.

Calling super() in a constructor

If you use Eclipse to generate a constructor it will look something like this:

public MyClass(int x) {
super();
this.x = x;
}

Eclipse always adds the call to super(). PMD has a rule for this (in its Controversial Rules category). The explanation is simply “It is a good practice to call super() in a constructor”.

If you omit super() in a constructor the compiler adds the call to super() for you. The compiled code is identical, whether you write the call or not. Effective Java doesn’t seem to address this. Is there any benefit to writing the call in all your constructors?

Supplying messages to JUnit assert calls

JUnit assert methods support a message argument, displayed if the test fails:

assertEquals("a != b", a, b);

This message does make a test failure slightly easier to read but I don’t believe the benefit outweighs the tedious overhead of typing messages for all your asserts. Tests should fail rarely, and when they do they almost always require stepping through or at least looking at the source of the test to figure out why they are failing.

I always omit the message unless it’s explaning something that isn’t obvious when looking at the code.

 

From http://dmy999.com/

Published at DZone with permission of its author, Derek Young.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Comments

Ricky Clarkson replied on Fri, 2008/09/12 - 4:53am

Yes.  People need to stop programming in Useless Java.

Umberto Zappia replied on Fri, 2008/09/12 - 5:01am in response to: Ricky Clarkson

[quote=rickyclarkson]Yes.  People need to stop programming in Useless Java.[/quote]

What would you suggest instead?? 

Alex(JAlexoid) ... replied on Fri, 2008/09/12 - 5:27am in response to: Umberto Zappia

I would suggest Useful Java :)

Ricky Clarkson replied on Fri, 2008/09/12 - 5:30am

Useful Java, or another programming language.

Don't be afraid of using generics to their fullest, or of using anonymous classes as lambdas.  Don't use JavaBeans - find a better abstraction that allows you to keep your objects immutable.  Try to avoid side effects where possible, and control them where you can't avoid them.  Ruthlessly avoid duplication.  Set IDEA's code duplication detector to its most picky settings

Experiment in other languages.  If you're tied to the JVM, look at Scala.  You don't have to give up static typing to use a language with lambdas; so you can safely ignore Groovy.   I wish I could suggest using the BGGA prototype compiler, but perhaps as it's experimental that would be a bit irresponsible.

If you're not tied to the JVM, look at C# - it has very similar syntax to Java but it has some features that Java seems a decade behind - local variable type inference, extension methods, lambdas, a collections library that isn't afraid of lambdas, and LINQ, which thankfully works wonderfully on collections - it has SQL-like syntax but isn't necessarily database-bound.

Also look at Scheme for how simple languages can be, and at Haskell to directly get the results of the latest research (rather than waiting for it to filter into C# or Java).

Don't be afraid of letting go of OOP.  It doesn't really work.  Concurrency highlights to all of us what many knew beforehand - objects promote mutable state, which doesn't scale up well.  Inheritance encourages fragile code that's hard to test.

Use static typing where you can, and testing where static typing doesn't help.  Always look for ways of making tests impossible to write by pushing the errors to compile time.

Back to Java, look at Functional Java and Reductio - FJ is a no-holds-barred functional programming library in Java, but it can be hard to understand at a glance.  Reductio is a testing tool that, given a lambda, generates inputs for it and monitors the outputs.  If a failure is found, it tries to shrink the inputs and tests again so that the failure the developer sees is with as simple test data as possible.

Understand your toolchain.  Don't be afraid to leave Eclipse if it doesn't support something you'd like to do.  I work mainly with Eclipse and emacs, the latter keeps me sane, depending on your viewpoint.

Andrew McVeigh replied on Fri, 2008/09/12 - 1:37pm in response to: Ricky Clarkson

Experiment in other languages. If you're tied to the JVM, look at Scala.

I agree with this wholeheartedly. Scala is great.

Don't be afraid of letting go of OOP. It doesn't really work.

Hmm, now you're on an anti-state rant again. If you are solely picking on class-based inheritance and platonic classification schemes, most people would agree. however, encapsulation, interfaces and polymorphism are pretty good contender concepts for the heart of modern-OO, and it's difficult to argue with those.

Concurrency highlights to all of us what many knew beforehand - objects promote mutable state, which doesn't scale up well.

What exactly do you mean by OO doesn't scale well? System size? I've worked on OO systems that worked very well with many millions of lines. Performance? Surely not. Concurrency? Well, ok, it's not been particularly strong there, but the actor paradigm works out quite well.

So sure, mutable state has its own set of problems, but so does the pure functional paradigm. That's one of the nice things about Scala, Oz and the other mixed paradigm languages. You can use the appropriate paradigm for the given subtask of a problem.

So here is my major beef with your advice -- your observations apply to certain domains and for other domains they just don't make sense. For instance, I find OO to be a superb match for GUI applications. It was the reason it was included in Oz. I find OO be a poor match for mathematical applications, and prefer a functional approach. Horses for courses.

Andrew

Raveman Ravemanus replied on Fri, 2008/09/12 - 2:21pm in response to: Ricky Clarkson

Ricky, are you drunk? there is so many things wrong in your comment that you must be drunk or joking. If its funny and i don't see it I'm sorry.

Ricky Clarkson replied on Fri, 2008/09/12 - 3:33pm

Andrew, 

"Hmm, now you're on an anti-state rant again."

No.  You can have state without OOP.  I'm not sure if you can have OOP without mutable state though - it would be interesting to examine how such a form of OOP would differ from functional programming, as it would by definition be a version of functional programming.

"If you are solely picking on class-based inheritance and platonic classification schemes, most people would agree."

I think I'm 'picking on' all forms of OOP that I've seen, from CLOS through Smalltalk through Ruby through Java and C#. 

"though however, encapsulation, interfaces and polymorphism"

You might want to look at Haskell's typeclasses for a non-OO version of all three of those concepts. 

"What exactly do you mean by OO doesn't scale well? System size? I've worked on OO systems that worked very well with many millions of lines."

People have worked on systems that worked very well with many millions of lines writing gotos, but not many would argue that goto is helpful in scaling.

Mutable objects need managing; you need to make sure that any method that depends upon the consistent state of an object gets that object (or a view of it) in a consistent way.  Java programmers already have some discipline in this; I can't think of any APIs that expose a StringBuffer or StringBuilder, but many will happily expose String, as it's immutable, relegating StringBuffer to the level of implementation detail.  In contrast, most of us will happily expose a List, even though it's immutable, though we might take pains to ensure that mutations will cause runtime errors (Collections.unmodifiableList) or that we copy the List defensively.

In contrast, immutable objects can be reused without worrying about what state they have at a given time.  They are automatically reentrant, they automatically work on multiple threads without problems and if they follow similar interfaces to each other, as in Functional Java, they can easily be composed together to build larger blocks. 

"So sure, mutable state has its own set of problems, but so does the pure functional paradigm"

Technically, mutable state can be done within a pure functional setting, though in quite a different way.  Imagine that java.util.Random's nextInt returned not just an int, but an int plus a Random somehow.  Then Random's implementation would be free to be immutable.  This is only a base example, it's more interesting when applied to files, etc., of course.  The point is that you can manage to do everything you can with mutable state without it, though there are obviously 'more functional' ways of doing that.  For many areas those are well established, for others they're not.

OO for reliable threading means that you need to find a way of losing or emulating mutable state, of losing the OOness, whereas those problems for which functional programming doesn't seem a natural fit are being actively researched, to make programming them in functional ways more attractive.

"For instance, I find OO to be a superb match for GUI applications."

Functional Reactive Programming is the name of the active research area relating to GUI applications.  I've never directly used it for GUIs, but what I've found is that the less mutable state I have throughout my app, the easier GUIs are to write.  It's not necessarily about never having mutable state, but about recognising that there are other options that should come first. 

Raveman, I was not drunk when writing that comment, but your words are driving me to drink now. 

Andrew McVeigh replied on Sat, 2008/09/13 - 12:50pm in response to: Ricky Clarkson

People have worked on systems that worked very well with many millions of lines writing gotos, but not many would argue that goto is helpful in scaling.

I don't know any systems that size that are written in an unstructured/spaghetti way. And this is my point -- objects help (me) enormously with structuring, which leads to good system scaling (millions of lines, advanced systems with many layers). When the classes are further aligned with domain concepts, i find that the learning time and the conceptual clarity are enhanced. this is clearly a double edged sword. (of course, when i speak, i speak for myself and my observations)

Mutable objects need managing; you need to make sure that any method that depends upon the consistent state of an object gets that object (or a view of it) in a consistent way.

Yes, sure, we all agree that mutable state carries a cost. I also am quite happy to agree that Java and possibly every other language with mutable state has an imperfect way of communicating whether an (possibly deep) object is mutable or not from a particular viewpoint. I also understand that pure functions have no such restrictions. I'm happy that those particular aspects are beneficial.

However, to me avoiding state as a starting point seems a bit like a form of denial. For instance, if i put an orange on a desk, and i return to it a day later, unless someone else has moved it, it is still there. I guess I've also seen so much work invested in "remodeling" mutable state in functional languages, that i'm nowhere near convinced that the effort involved is less than the overhead of actually having state. Two of the cleverest guys I know spent 6mths writing a 3d game in haskell. they claimed it took so long because they were recreating the pointer concept as a functional form. another of the guys has just had a paper published recreating linked lists in haskell. i've seen the extreme effort required to create mnesia, and puzzled at the notion that it should involve so much work. To me, this all seems like starting from a good conclusion (e.g. the world is painful) and taking it far too far into a logical absurdity (e.g. i won't get attached to anyone, therefore i won't feel pain).

For instance, what benefits does functional reactive programming have over an oo view with state? Does it make it simpler somehow? Does it make it more reliable? For my part (and I've done a lot of GUIs), the best way i've found of modeling is via finite state machines. I've had hugely good experiences with this technique. And i feel comfortable knowing that the state that i'm modeling in my GUIs maps well onto the statefulness experienced by the user. So, it's not state that bothers me per se, but how that state is managed. And by now we have very powerful ways of managing this state.

Conversely, one place i've found oo techniques to be poor for, is concerning the statelessness of http (i.e. web guis). there's a fundamental mismatch it seems that when oo techniques are used, it always seems to result in more state being synchronised between a client and server.

in conclusion, i'm not doubting the validity of your statements, but perhaps your conclusion from them and the relative weight you place on the pain of mutability. I believe that mutable state is a valuable tool in a toolbox of techniques, rather than an absolute evil that must be avoided. Use it because it is good at modeling things that actually have state. Avoid it when it causes problems, or leads to "scaling" issues. And vice versa, i'm not going to functionally recreate state when i can just use state if it is the simplest representation. And that's why i like mixed paradigm languages, paricularly Oz which merges the approaches in a unified core semantics.

(Don't get me wrong though -- i'm a great believer that being passionate about a paradigm and pushing it in extreme directions can be extremely exciting and beneficial. Just don't expect an easy ride on the way there! I also think that objects have many flaws of their own, but not necessarily the ones you've cited ;-)

Raveman, I was not drunk when writing that comment, but your words are driving me to drink now.

I don't even need that to drink ;-) i'm off to get a beer/wine/assorted liquors.

Andrew

 

 

 

Eyal Golan replied on Mon, 2008/09/15 - 1:10am

As for calling super(), I think it is a good practice.

For me it helps to remember that there is a call to the super's constructor. I call it - Ah, it just jumped to my eye that we call the super's constructor.

For the begining programmer it really helps to understand what happens.

 As for your second comment. I found out that when I have a very big set of unit tests in a single Test, it is very helpful for me to see which test failed by using the JUnit messages.

Doug McCreary replied on Mon, 2008/09/15 - 7:45pm

In the junit example, a != b is useless.  What you want is a string describing why a SHOULD be equal to b.

Tony Morris replied on Mon, 2008/11/03 - 8:51pm

"they claimed it took so long because they were recreating the pointer concept as a functional form."

Yes and they were doing it disastrously wrong.

"another of the guys has just had a paper published recreating linked lists in haskell."

WTF? Do you realise that a linked list is a fundamental data structure of functional programming and more so in a lazy language like Haskell? What paper?

Andrew McVeigh replied on Tue, 2008/11/04 - 6:01am in response to: Tony Morris

"they claimed it took so long because they were recreating the pointer concept as a functional form."

Yes and they were doing it disastrously wrong.

And you know this how? Here's some slides and a talk they did on the stuff. Tristan is now working as an intern with SPJ at MS Research. I'm guessing he knows what he's talking about:

http://www.londonhug.net/downloads/games_in_haskell.pdf

http://www.wellquite.org/non-blog/hug_games.flv

I think the basic problem comes down to aliasing and state management. You need aliasing pointers in some state problems. i.e. this refers to that, and so does that.

(by the way, i've only limited insight into the functional domain. i make observations to start a debate, not to have a fight. to my eyes, they were struggling with basic state management. they would see it differently. as i said, they are *smart* guys ;-)

"another of the guys has just had a paper published recreating linked lists in haskell."

WTF? Do you realise that a linked list is a fundamental data structure of functional programming and more so in a lazy language like Haskell? What paper?

Yes, i know how lists are implemented in functional language (rolls eyes). Again, i believe the problem is to do with the notion of reference to something that may change state, however you model it. i.e. a cursor through the list, or a reference to a part of the list, given the list may change.

http://pubs.doc.ic.ac.uk/clase-cursor-library/

I'd be interested in your opinions.

Andrew

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.