What you didn’t think you needed to know about hashCode and equals

This article is a repost of my comments to the question on how to implement hashCode and equals on stackoverflow

There are some issues worth noticing if you’re implementing hashCode and equals for classes that are persisted using an Object-Relationship Mapper (ORM) like Hibernate. If you didn’t think this topic is stupidly overcomplicated already!

Lazy loaded objects are subclasses

If your objects are persisted using an ORM, in many cases you will be dealing with dynamic proxies to avoid loading object too early from the data store. These proxies are implemented as subclasses of your own class. This means that the commonly recommended this.getClass() == o.getClass() will return false. For example:

Person saved = new Person("John Doe");
Long key = dao.save(saved);
dao.flush();
Person retrieved = dao.retrieve(key);
saved.getClass().equals(retrieved.getClass());
    // Will return false if Person is loaded lazy

If you’re dealing with an ORM using o instanceof Person is the only thing that will behave correctly.

Lazy loaded objects have null-fields

ORMs usually use the getters to force loading of lazy loaded objects. This means that person.name will be null if person is lazy loaded, even after person.getName() forces loading and returns “John Doe”. In my experience, this crops up often in hashCode and equals.

If you’re dealing with an ORM, make sure to always use getters, and never field references in hashCode and equals.

Saving an object will change it’s state

Persistent objects often use a id field to hold the key of the object. This field will be automatically updated when an object is first saved. Don’t use an id field in hashCode. But you can use it in equals.

A pattern I often use is

if (this.getId() == null) {
    return this == other;
} else {
    return this.getId() == other.getId();
}

But: You cannot include getId() in hashCode(). If you do, when an object is persisted, it’s hashCode changes. If the object is in a HashSet, you’ll “never” find it again.

In my Person example, I probably would use getName() for hashCode and getId() plus getName() (just for paranoia) for equals. It’s okay if there are some risk of “collisions” for hashCode, but never okay for equals.

hashCode should use the non-changing subset of properties from equals

Comments

Print This Post Print This Post

Toyota Kyushu - En produksjonsballett

This is a rough Norwegian language translation of the article JKE Day 1: Toyota Kyushu - The Manufacturing Ballet by Kevin Meyer (improvements on the language are very welcome, comments on the contents should go to Kevin). The reproduction has been authorized by the author. Unlike the rest of my site, this article is not available under creative commons license.

Jeg kom over en artikkel som demonstrerte hvor bemerkelsesverdig lean production system kan være. Den var så spennende at jeg bestemte meg for å oversette den til norsk:

Read the rest of this entry »

Comments

Print This Post Print This Post

Verbose logging will disturb your sleep

When I encounter a system that has already been in development or production for a while, the first sign of real trouble is always a dirty log. You know what I’m talking about. When clicking a single link on a normal flow on a web page results in a deluge of messages in the only log that the system provides. Too much logging is as useless as none at all.

If your systems are like mine, when your job is done, someone else’s job is just starting. After the system has been developed, it will hopefully live a long and prosperous life serving customers. If you’re lucky. How do you know if something goes wrong when the system is in production, and how will you deal with it?

Maybe someone monitors your system for you, or maybe you will monitor it yourself. Either way, what the system logs is going to be critical to know when you want to be woken up in the middle of the night.

For many systems, the first indication that something is wrong is because a log message of the correct level has been written to a log. Mostly, this will be the error log. So do yourself a favor: Make sure from day one that if something is logged the error log, you’re willing to have someone call and wake you in the middle of the night about it. If you can simulate load on your system during system testing, looking at a well-kept error log is also a good first indication that your system is reasonably robust. Or a first warning if it’s not.

For my systems, the best indication that everything is all right, is that the messages at a lower priority are ticking along happily. I want about one INFO-level log message for every significant event for the application.

A cluttered log is an indication that the system will be hard to control once it reaches production. Like with all problems: If you don’t expect anything to show up in the error log, it will be much easier to know what to do when something does show up.

Comments

Print This Post Print This Post

On the road: Agile development and testing

I’m going on the road again. This time it’s not far, just to Trondheim for a seminar for the Norwegian computer association that I will be giving together with Aslak Hellesøy on agile development and testing.

This will be similar to our line-up at JavaZone: Aslak will cover “how to make the correct software”, and I will cover “how to make the software correct”. Hopefully, we’ll make a few test managers think and a few others angry.

Comments

Print This Post Print This Post

I’m moderating the IfI alumni open source debate

The alumni organization from my old university is arranging a debate about open source, and I’ll be moderating. The debate will be next Wednesday at Scotsman in downtown Oslo.

There will be a four person panel, with two skeptics and two open source fans. So far, the panel looks as follows:

  • Heidi Arnesen Austlid, Friprogsenteret
  • Per Hove, Oracle Norge
  • Shahzad Rana, Questpoint
  • An exciting surprise!

The event will be held in The Scotsman, where they sell beer! And there will be free pizza! Free code, free beer, free pizza!

More information

Hope to see you there.

The text of this blogpost was shamelessly ripped of Ferris’s blog and patched slightly

Comments

Print This Post Print This Post

Smidig 2008 is delivered!

The Norwegian Agile User Group conference, Smidig 2008 was on Thursday and Friday. Both days started with three hour sessions of Lightning Talks, followed by three hours of open space work groups after lunch.

We have been very happy with the format. The lightning talks give people food for thought. The best lightning talks are formulated around a provoking hypothesis. Kai Gilb talked about how we should focus on value instead of function. Kaare Nilsen said that we should really stop saying we’re doing scrum, because nobody is really doing it. Eirik Bjølsnøs said that plugin-architectures will lead to more changeable systems. Olve Maudal said that you should always leave the code a little cleaner than how you found it. Karianne Berg said that throwing away your codebase to start over is a mistake. These were just some of the many provoking ideas people presented.

Some statements you may agree with and some you might disagree with. Some, you want to examine in more depth. That’s why we have set up the open spaces. Norwegians are known as being sort of introvert, but walking around during the open space, you would never guess it.

My only regret is that I could only see one track of lightning talks at a time. The conference has been filmed, and hopefully it will only be a few weeks before all the videos will be available to the public.

Great thanks to everyone who helped make the conference a success: Organizers, volunteers, speakers and especially the participants. An extra big thank you to those who traveled from Bergen, Trondheim, Kristiansand, Florø, Stockholm or elsewhere to attend the conference.

The discussion continues on the Norwegian Agile forum. Why don’t you join in?

Comments

Print This Post Print This Post

Video of my JavaZone talk about Continuous Integration

Comments

Print This Post Print This Post

The Smidig 2008 conference is this week!

Smidig 2008, 9. - 10. oktober, Oslo Kongressenter

In the middle of changing jobs, I have also been quite busy with the last minute preparations for the Smidig 2008 conference for the Oslo Agile user community (”smidig” being the closest Norwegian translation of “agile”).

The conference be two days of lightning talks before lunch and open spaces after lunch. The program is in the final stages of being finalized as we speak.

There are still a few open seats. We’ve structured the price so that we don’t need to sell out to avoid losing money. But we want to make sure that as many people as possible take advantage of the opportunity to learn and discuss with a large number of other practitioners of agile software development.

You can sign up at http://smidig2008.no. Hope I see you there!

Comments

Print This Post Print This Post

Five Unit Test Tips: #2: Change your code to make testing easier

It’s been a while since I promised to write top five unit testing tips, so I guess I should better start writing #2. As with my first example this one is based on a real-life story.

Your code is worth nothing if it can’t be tested. Change your code to make it more testable.

In my last project, we used a pipes and filter architecture, with messages being passed forward through a chain of services. Most services refined the messages or broke them up in smaller services and passed them on to the next service. When they refined the message, they often stored new messages to the data layer as a side effect. To test the results, we read the generated objects back from the data layer. I had code like this:

Before

@Test
public void fileShouldCreateTransactionObject() {
    Reader simulatedFile = new StringReader(createFileContents());
    FileRequest file = new FileRequest(filename, simulatedFile);
 
    TransactionRepository repo = new TestTransactionRepository();
 
    FileService fileService = new FileService();
    TransactionService transService = new TransactionService();
    fileService.setNextStep(transService);
    fileService.setTransactionRepo(repo);
 
    fileService.process(simulatedFile);
 
    Collection<Transaction> transactions = repo.findAll();
    assertEquals(1, transactions.size());
    Transaction transaction = transactions.iterator().next(); // Bleh!
 
    // Here is the real code I wanted
    assertEquals("foo", transaction.getTransactionType()); // Whatever
}

The solution was to change the design away from the pipes-and-filters design. Instead, the process() method returns the newly created Transaction object:

After

@Test
public void fileShouldCreateRequestObject() {
    Reader simulatedFile = new StringReader(createFileContents());
    FileRequest file = new FileRequest(filename, simulatedFile);
 
    FileService fileService = new FileService();
    Transaction transaction = fileService.transform(simulatedFile);
 
    // Here is the real code I wanted
    assertEquals("foo", transaction.getTransactionType()); // Whatever
}

This new design totally violated our architecture, but it’s clearer, it keeps the infrastructure away from the code, and it’s much less brittle. Our test transaction repository used to be vulnerable to being polluted with test data from a previous run. As we no longer use this sort of infrastructure objects, we don’t have to worry about interaction between tests.

If you don’t know how to test your architecture, the problem is not with the testing, but with the architecture.

Until next time: Happy testing.

Comments

Print This Post Print This Post

Link: Waterfall works for risk-free projects

I don’t normally post just a link to another blog, but More thinking about “Agile” vs “Waterfall” by Jason Yip is just too important. It the most well-argued, well-referenced, short post I’ve seen about the subject. Here’s a taste:

Be careful about saying that Waterfall is more disciplined. The waterfall model is simple and structured but the “discipline” is in following prescribed steps as opposed to “discipline” in thinking. The second kind of discipline is by far the more important.

Comments

Print This Post Print This Post
Creative Commons Attribution 3.0 Unported
Creative Commons Attribution 3.0 Unported