Archive for November, 2004

Exceptions, part 4

Tuesday, November 30th, 2004

Yes, there is even more to say about exceptions. So after part 1, 2, and 3 in the series, here is part four.

Checked vs. Runtime

In Java, there is a distinction between exceptions that need to be caught or declared in a throws clause, and those that do not. The former are named checked exceptions; the latter runtime exception, since they all inherit from the java.lang.RuntimeException class. If you do not catch a checked exception or declare it in the throws clause of the method, you will get a compiler error.

When the specs of the first version of Java were written, this seemed like a very good idea. And, at first sight, it still does. What could be better than to have a compiler error when you forget to include error handling for the methods you use? Actually, there are two things wrong with it.

Too many exceptions

Image that you are integrating four or five systems, and that each system throws about ten different exceptions. When the compiler tells you that there are a gazillion exceptions that need to be handled, what is the quickest (and thus most likely used) way to solve these errors?

  1. Catching java.lang.Exception and ignoring the result. This is not an option, since we just learned that is not a good thing.
  2. Adding throws Exception to the signature. This also is not an option, since it does not offer any specific information. It just says: something could go wrong here. I don’t know what could go wrong, but don’t say I didn’t warn you!
  3. Catching java.lang.Exception and wrapping the result in a runtime exception. This is the best possible solution to this problem.

As it turns out, checked exception become such an nuisance that most developers use one of these three workarounds.

Breaking interface changes

Martin fowler was right when he said that [a published interface] is more public than public.. If you publish an interface, and later on add more exceptions, you break the API and your users do not tend to like that. As an alternative, you could decide to throw only runtime exceptions.

Now, the clever reader has noticed that the common solution to the two issues is to use the runtime exception. Now wonder Anders Hejlsberg, the lead C# architect, decided not to copy this particular feature from Java. He did a pretty good job copying the rest though.

0×1E

Monday, November 29th, 2004

Thirty years ago today, I was born. It has been fun so far, I hope the rest is too…

Why enums are bad for you

Saturday, November 27th, 2004

One of the “improvements” of the .NET framework over Java is the inclusion of enums. In fact, it was such a big improvement that Sun has included it in JDK 1.5 (sorry: Java 5). I’m not a big fan of enums in .NET, and in this post I’ll explain why.

Enums are not limit to members

One reason, which has been pointed out by others is that enums are not limited to the possible values of its members, but to the possible values of its underlying type. This means that you can do the following:

public enum Colors {
  Red,
  Green,
  Blue
}
...
Colors myColor = (Colors)42;

without some kind of exception being thrown. To make it even weirder: the string representation of myColor is 42, though its Type is Colors.

Enums enforce switch statements

One of the symptoms that your code is ready for refactoring (also known as code smell) is the switch statement. If you use an enum, you must either use a switch or a if-then-else statement. And every time you add one member to the enum, you must add another case in every place you use the enum.

The excellent Refactoring to patterns suggests replacing complex and rigid switch statements using the Command pattern, or the Visitor.

You could also use a simple class hierarchy. So instead of the code above, I might define an abstract Color class, with three subclasses: RedColor, GreenColor, and BlueColor. It might seem like a bit of overkill, but it solves the above issues perfectly, and is very object oriented too!

DataSets

Wednesday, November 24th, 2004

The .NET class System.Data.DataSet is an implementation of the Table Module Enterprise Pattern. As such, it represents (part of) an in-memory dump of a database, including tables, rows, relations, etc. The idea is that you manipulate this dump, and send an update to the database using a DataAdapter. Thus, in .NET the classic three tier enterprise application looks something like this:

  1. SQL Server
  2. Business Layer
  3. Web application

The second layer uses stored procedures in the first layer to store data in a dataset, which then gets passed on to the third layer. The data is manipulated, and send back to the second layer, which sends the changes back to the database. Seems to be ok, right?

Not quite. There are two things wrong with this picture. Firstly, the dataset that is being manipulated does not represent the domain of the application at all. Instead, it represents an object-approach to a RDBMS: first, you define a DataSet with DataTable containing DataColumns, then you can add new DataRows to the table, perform a query, or load it with data from the database:

DataSet dataSet = new DataSet("pubs");

DataTable titles = dataSet.Tables.Add("titles"); titles.Columns.Add("titleid", typeof(string)); titles.Columns.Add("title", typeof(string)); titles.Columns.Add("pubid", typeof(int)); titles.Columns.Add("price", typeof(double));

DataTable publishers = dataSet.Tables.Add("publishers"); publishers.Columns.Add("pub_id", typeof(int)); publishers.Columns.Add("name", typeof(string));

dataSet.Relations.Add(titles.Columns["pubid], publishers["pubid"]);

DataRow titleRow = titlesTable.NewRow(); titleRow["titleid"] = "aaop"; titleRow["title"] = "The Ancient Art of Programming"; titleRow["pubid"] = 34; titleRow["price"] = 24.95; ...

You get the idea: tedious and error-prone (though you could replace all literal strings with constants).

The Typed DataSet is a strong-typed version of the above, and improves the situation a bit, though not much. You will end up with something like:

PubsDataSet pubs = new PubsDataSet();
TitleRow titleRow = pubs.Titles.NewTitlesRow();
titleRow.TitleId = "aaop";
titleRow.Title = "The Ancient Art of Programming";
titleRow.PubId = 34;
titleRow.Price = 24.95;
...

Though the string-based indexers are now nice properties, we are still manipulating tables and rows. I don’t want to manipulate rows, I want to manipulate domain objects which are eventually stored in database rows and tables.

Another problem with the dataset is that the layout of the database is not being abstracted; in fact the layout is pushed across all three tiers. This means that, if you change the database, you will have to change the business layer and web layer too.

I guess that these two reasons make me such a big fan of ORM tools such as Neo or NHibernate.

On Equality, part 2

Monday, November 22nd, 2004

This is my second post about equality comparison methods. The first part, which was about Java equality methods, can be found here. This second post covers the .NET side of things.

In .NET, there is a difference between reference types (classes) and value types (structures). This has some implications for equality comparison, so first I will consider the equality comparison for classes, and then structures.

Reference types

The things to watch for in a .NET Equals method are pretty much the same as for Java: the object passed to Equals method can be null or an instance of another class.

My template for an Equals method of a .NET reference type is:

public override bool Equals(object o) {
  if (Object.ReferenceEquals(this, o)) {
    return true;
  }
  <class> other = o as <class>;
  if (other != null) {
    return ( (this.field1.Equals(other.field1) && 
      (this.field2.Equals(other.field2) && 
      // compare every field in <class>
      );
  }
  return false;
}

Since .NET classes can have an overloaded == operator, you cannot use that to check for reference equality as in Java. Instead, you can use Object.ReferenceEquals, which always works. Also note the use of the as operator, so that you check the type and perform a cast in one call.

Value types

With .NET structures, it is a bit of a different story: structures cannot be null, and there is no such thing as reference equality.

My template for an Equals method of a .NET value type is:

public override bool Equals(object o) {
  if (o is <class>) {
    <class> other = (<class>)anObject;
    return ( (this.field1.Equals(other.field1) && 
      (this.field2.Equals(other.field2) && 
      // compare every field in <class>
      );
  }
  return false;
}