3

Preamble: Let's say I aim to cover all my classes with test coverage.

Despite the common opinion (expecially in Java community) to "not pay too much attention to Cyclomatic Complexity (CC) and code coverage", I really think that these information are extremely useful: When you have a very high CC, or an uncovered zone in your code, very likely you wrote a dead code, or either is a smell that you have problems in design. In my personal experience I can say that many time dead code is code smell.

This problem become a little tricky when you have to deal with auto-generated code, and that's the point, how can I easily deal with hashcode and equals autogenerated methods? I came across this question in StackOverflow and I realized some very good point:

https://stackoverflow.com/questions/5764380/unit-testing-equals-and-hashcode-a-complexity-story

But this question is not a duplicate because I want to use a different approach:

The best options available in the answers of that question are, as far as I can see, EqualsBuilder of Apache Commons Lang or Guava. Both uses reflection (correct me if I'm wrong) and that could be a problem for performance in some situations.

But my actual question is: Since most of the times both equals and hashcode methods are not covered, is that a hint that this particular class does not need those 2 methods? Since many Java developers a lot of time generate equals and hashcode even when not needed, what am I missing? Shouldn't be a better solution to generate those methods only when you need, for instance, to sort objects of that class, to use that objects as an Hashtable key, and so on?

As I said, I think that goals of low complexity and high coverage are admirable, but the solution of using EqualsTester , seems to me like "Force to cover code that you don't actually need in your program".

  • 2
    Thankfully, Apache commons at least also exposes a manual interface. Beyond that, even if you don't use the classes that way somebody else might - anything that might conceivably be a value type should have those methods (plus toString()). There are a number of things that don't need them, often cases where you only need one instance period. Perhaps you could give a specific example? – Clockwork-Muse Feb 10 '14 at 14:45
4

The story of equals() combines several unfortunate design decisions that are now impossible to change, and that every Java user just has to live with one way or another: it is deeply woven into the semantics of the standard container types, it is automatically inherited by every user-defined class but with a behaviour that is usually not what you want, and defining it without also defining hashCode() silently results in undefined behaviour (i.e. the language imposes certain requirements on you but has no way of warning you if they are unsatisfied.)

You can get along by simply never defining the method IF you never use such objects anywhere that would expose the unwanted behaviour. But since software development is a cooperative game, this requires an iron-clad, no-exceptions, disciplined rule of "Absolutely no Foo widgets in Sets, ever!!" that everyone involved with the code must know and follow 100%.

It can be worthwhile to impose such a rule in order to gain some performance, just as with other very fundamental principles of coding - e.g. "No null return values, ever!" is a common strategy to save a lot of checking for null. But this depends on how much you really profit from the small simplification for each class. The downside is that you have added another unspoken assumption that all users of your class must know and follow, or silently suffer from undefined behaviour.

  • 3
    Unless a class clearly documents what its equals and hashcode methods do, I would not assume anything about how instances of that class would behave in a hashset/hashmap. – assylias Feb 10 '14 at 15:13
  • Very very very good answer! I get that, In the moment I want expose my classes as a Library or an external dependency I have no control on how my classes are used, so it is a good idea to expose an overrided equals and hashcode methods. It's ok to not define them "IF you never use such objects anywhere that would expose the unwanted behaviour" – thermz Feb 10 '14 at 15:16
  • Hopefully over the course of Java 9/10 this will get tidied up with the addition of Collection Literals and Value Types.. – Martijn Verburg Feb 10 '14 at 15:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.