Archive for November, 2004

On Equality, part 1

If you write a class, you will probably end up writing an equality comparison method for it. In this post, I will give you my method for writing an equals method in Java. This next post considers the .NET side of things.

One of the most important things you have to consider is that the Object passed to equals method can be anything, not just an instance of the current class. Also, it could be null, so you have to watch for that.

My template for equals is:

public boolean equals(Object anObject) {
  if (this == anObject) {
    return true;
  }
  if ( (anObject != null) &&
    (anObject instanceof <class>) {
      <class> other = (<class>)anObject;
      return ( (this.field1.equals(other.field1) && 
        (this.field2.equals(other.field2) && 
        // compare every field in <class>
        );
  }
  return false;
}

28-12-2004: changed Equals to equals.

Note that I check for reference equality first, so that if it is the same reference, the field-by-field comparison is not required. Next, I check for null, and whether the given object has the same class. Then I cast the object, and finally I return the result of the field-by-field comparison.

Comments off

Primitives vs. Real-world objects

Throughout both the .NET and Java frameworks, there are beautiful object which represents real world things like languages (java.util.Locale or System.Globalization.CultureInfo), files (java.io.File and System.IO.FileInfo), dates (java.util.DateSystem.DateTime), et cetera.

However, nobody tends to use them, especially not in enterprise software. It’s a bit more difficult to store a Locale in the database than a string. In some cases, you will have to do some processing to do so, but I think this processing is worth it, because the classes are much clearer and less error-prone than primitives. If you use a primitive to represents a real-world thing, you always have to determine how to store it in the primitive. If you work in a team, every person working on this code has to know, honor, and remember this format.

For instance, if an integer represents a date, everybody who uses the code will have to agree on the specific way the integer represents a date. It could be the number of seconds since 1970, or it could be the number of days since 1980. Basically it could be anything, and the only guard you have against someone storing anything in the integer is a manual agreement.

Addititonally, the classes give you functionality that the primitives do not offer. Like determining the display name of a language, or checking whether a file already exists.

Comments off

Exceptions, part 3

This is part three in a series about using exceptions in both Java and .NET. You can find part one here, and part two here.

When to catch exceptions

In part two of this series, we covered the right conditions for throwing exceptions. In this article, I would like to cover the other end of the spectrum: catching exceptions.

It turns out there is just one simple rules to catching exceptions:

  • Never, ever, ever-ever catch the base exception class.

Like many of my rules, the rationale behind this rule comes from experience. And like most bad experiences, it was caused by other people’s code ;-).

A few years ago, I was debugging a piece of Java code of a colleague that did not work right. The code was supposed to generate a file somewhere on the filesystem, but it did not do so. But no exception was thrown; everything seemed to work OK. As it turned out, he did the following somewhere deep in the code:

try {
  doSomething();
  doAnotherThing();
  andAnotherThing();
} catch (Exception e) { 
}

And that is just a bug waiting to rear it’s ugly head.

All this because, and I quote: All those methods are mine and should not have caused exceptions anyway. And besides, those throws declarations exceptions are driving me nuts. Right.

However, like all rules, it comes with an exception:

  • Except when wrapping it in another exception.

Wrapping an exception in another exception is possible in both .NET and Java (since JDK 1.4). You can add more information to the wrapper with a message, but you can also use a wrapper exception to limit the types of exceptions a methods throws.

Comments off

Exceptions, part 2

This is part two in a series about using exceptions in both Java and .NET. You can find part one here.

When to throw exceptions

There are a lot of different opinions about using exceptions. Joel, of Joel on Software fame, thinks there are as evil as a goto. I disagree with Joel, but I do have two rules of thumb when it comes to throwing exceptions:

  1. Only throw an exception in exceptional cases.
  2. Make it possible to check for errors without necessarily catching an exception.
  3. Never throw an exception in a constructor.
Let’s go over these one by one.

Exceptional cases

I know that exceptional cases sounds kind of vague, but-to me-an exceptional case is a case that normally does not occur, and if it occurs, you’re pretty much screwed. For instance, when the computer runs out of memory, when a database connection drops underneath of you, or or when the filesystem is borked. In these cases, an exception is in place, because there is not much you can do anyway. It is not like you can force someone to purchase new memory chips if your malloc fails:

char* buf = (char*)malloc(100 * sizeof(char));
if (buf == NULL)
  GoBuyMoreMemoryNow();

Checking for errors without exceptions

The implication of the above is that it should never be required to catch an exception when you’re doing something normal. Suppose you have a user-provided string that should contains a date. In .NET, there is no easy way to check whether it really is a date, except for catching exceptions. So to check whether it’s a valid date, I have to do the following:

bool isValidDateTime = true;
try {
  DateTime dateTime = DateTime.Parse(someString);
} catch (FormatException fe) {
  isValidDateTime = false;
}

It turns out that the next version of the .NET framework will fix this, but until then, the only way to check for a valid string representation of a date is the above. Java does not have this specific issue, because its DateFormat class can return null as an error indicator.

Never in a constructor

Usually you don’t want to do anything that can fail in the constructor of a class. Instead, use a factory method, or an initialization method.

Comments off

Exceptions, part 1

Exceptions are amongst the least understood functionality in both the .NET and Java world. This is the first article in a series of articles about exception. In this series, I will give my opinion about them.

Subclassing the base Exception

If I create a library or a piece of business logic, one of the first things I do is to create my own subclass of exception. Why do I do that? Why not simply use the exception classes provided by the framework (java.lang.Exception or System.Exception) with a descriptive string message?

Actually, there is a very good reason, which only showed itself a short while ago: I was evaluating a java library, and I got a IOExceptions from using it. Since it was an IOException, I assumed that the errors had something to do with the FileInputStream I constructed: an invalid filename, perhaps? As it turned out (the description of the exception didn’t help me much in this specific case), the exception had nothing to do with my stream, or even with I/O: the library simply threw IOExceptions everywhere, both in places related and not relation to I/O.

If a custom exception (or even a custom subclass of IOException) was thrown, I would have known instantly not to search for my error in the stream, but in the library.

Also, I could have separated my java I/O error handling code from the error handling code of this library by writing something like:

try {
...
} catch (IOException ioe) {
  // do i/o related error handling
} catch (LibraryException le) {
  // do library related error handling
}

Instead, my error-handling code will look like this:

try {
...
} catch (IOException e) {
  if (e.getMessage().equals("something") {
     // do i/o related error handling
  } else {
     // do library related error handling
  }
}

Which is both ugly and error-prone.

Comments off

· Next entries »