Archive for September, 2007

Maybe Tests Don’t Belong in Your Project

Maybe unit tests don’t belong in our projects. Perhaps by moving tests to a standalone project, separated from application code, we can improve backwards compatibility and provide better regression testing. Read on….

First, Some Background

Some people put tests right next to source code:

[proj]
+--src
     +--com/acme/killerapp/
                       Customer.java
                       CustomerTest.java
                       etc...

I do not like this because it makes it harder to separate test code from application code. The “*Test.java” sources are easy to filter out, but sometimes you have helper classes that are used by tests, but are not tests themselves. These helper classes may not follow an easily filtered naming convention.

Separate Test Directories

I prefer to structure my projects like this:

[proj]
+--src
    +--main
    |   +--com/acme/killerapp/
    |                     Customer.java
    +--unittests
    |   +--com/acme/killerapp/
    |                     CustomerTest.java
    |                     TestUtils.java
    |                     etc...
    +--integrationtests (optional)
        +--com/acme/killerapp/

With any IDE, multiple source trees are virtually transparent to developers. Isolated source directories make it really easy to create Ant buildfiles that keep test code and application code separate, and even let you define a boundary between unit tests and integration tests.

Is More Separation Valuable?

Let’s start with a question:

Is version 2.2 of your API compatible with version 2.1?

Do your tests help answer this question? I bet not. You see, most of us store our unit tests in the same project as our application code. We may break out tests into their own source tree, but in the end, it’s all lumped together in the same project.

As we add features and fix bugs for version 2.2, we hope to continually maintain the test suite in unison. We know that version 2.2 compiles against itself, but what about customers who have application code using version 2.1, and now wish to upgrade to version 2.2 of your product?

Cockroach

A New Proposal

What if we put application code into one project and all tests into a completely different project? To compile tests, you need to first build the application code. The tests should then compile and run against a JAR file from the core application.

Because of this extreme separation, we can now easily compile and run the version 2.2 unit tests against version 2.1 of the application. Or, we can compile and run version 2.1 unit tests against version 2.2 of the application. Mixing application code and test code into the same project makes this kind of cross-version testing harder.

How Might This Help?

I suppose I originally thought of this because of a recent experience upgrading an open source library. This upgrade was supposedly a “minor bug fix” release, but my application code would not compile against the new release.

If they had attempted compiling their old tests against their new software, they would have discovered this problem and could have taken one of these actions:

  • Inform customers of the issue
  • Back out the incompatible change
  • Choose to call this a “feature release” instead of a “bug fix release”

But I’ll bet they didn’t even realize they were breaking code.

What do you think?

404

Does your blog have a decent 404 error page?

Car Crashing into Water

I’m sure you can find mine all by yourself.

Let me know if you can think of other famous things we’ve never found.

JUnit 3.x and the Event Dispatch Thread

This is a recycled post from version 1 of this blog.

public abstract class EdtTestCase extends TestCase {

  /**
   * Overriding this method guarantees that setUp(), tearDown(), and all
   * tests run on the EDT.
   */
  @Override
  public void runBare() throws Throwable {
    final AtomicReference<Throwable> problem = new AtomicReference<Throwable>();
    if (!SwingUtilities.isEventDispatchThread()) {
      SwingUtilities.invokeAndWait(new Runnable() {
        public void run() {
          try {
            runBare();
          } catch (Throwable throwable) {
            problem.set(throwable);
          }
        }
      });
      if (problem.get() != null) {
        throw problem.get();
      }
    } else {
      super.runBare();
    }
  }
}

Does anyone have a comparable JUnit 4 example?

High Scalability Irony

I encountered this today while trying to read an article describing Twitter scalability:

Not Scalable

Enjoy your weekend!

Let’s Fix Some Crap Code

Let’s suppose we have a database where customers are identified by a composite key. This key contains two integers, a customer ID and district ID. Thankfully, both fields have NOT NULL constraints in the database.

Throughout the Java code people pass multiple parameters, the customerId and districtId, whenever they wish to identify a customer. To fix this problem, some clever programmer writes a CustomerKey class that combines both fields. The code looks something like this:

public class CustomerKey {
    private Integer customerId;
    private Integer districtId;

    public CustomerKey() {
        this(0,0);
    }

    public CustomerKey(Integer customerId, Integer districtId) {
        setCustomerId(customerId);
        setDistrictId(districtId);
    }

    public Integer getCustomerId() {
        return customerId;
    }

    public void setCustomerId(Integer customerId) {
        if (customerId == null) {
            this.customerId = 0;
        } else {
            this.customerId = customerId;
        }
    }

    public Integer getDistrictId() {
        return districtId;
    }

    public void setDistrictId(Integer districtId) {
        if (districtId == null) {
            this.districtId = 0;
        } else {
            this.districtId = districtId;
        }
    }

    public boolean equals(Object o) {
        ...
    }

    public int hashCode() {
        ...
    }
}

Eric Burke’s Code Review

The Scream

Here are my observations on this class:

  1. Using Integer instead of int makes no sense in this case.
  2. Silently converting null to 0 is a really bad idea.
  3. Because this class is mutable, it is not thread-safe

Why Type Wrappers?

Type wrappers can contain numeric and null values. Primitives can only contain numeric values. Since our database has NOT NULL constraints, there is no reason to allow null in the Java-side.

By allowing null, particularly in a fundamental class like this, you introduce bad code to every piece of application logic that uses this class. Because type wrappers might be null, every programmer utilizing the CustomerKey must guard against NullPointerException.

In this case, use primitives.

The Silent Conversion

The programmer attempts to mask null values like this:

public void setCustomerId(Integer customerId) {
  if (customerId == null) {
    this.customerId = 0;
  } else {
    this.customerId = customerId;
  }
}
Another Happy Customer
Do you like my blog? If so, why not subscribe?

I am guilty of a similar sin several years ago. In a very fundamental piece of framework code that converts values to/from strings, I made the mistake of silently converting null to zero. Now, as many as seven years later, we still see artifacts from this bad design decision. It is very low-level and is deeply intertwined in code that cannot be changed. This is one of my biggest programming mistakes, ever.

Silent data conversions like this are a bad, bad mistake.

This Class Should Be Immutable

Since this class has both getters and setters, it is not thread-safe. Additionally, if you use instances of this class as keys in a Map or as values in a Set, you risk corrupting the data structure if someone modifies the objects after adding them to the collection.

In classes intended to serve as composite keys, it is far better to simply make the class immutable. This reduces many types of errors and further simplifies the code.

A Better Implementation

Here is how I’d write the class:

public class CustomerKey2 {
    private final int customerId;
    private final int districtId;

    public CustomerKey2(int customerId, int districtId) {
        this.customerId = customerId;
        this.districtId = districtId;
    }

    public int getCustomerId() {
        return customerId;
    }

    public int getDistrictId() {
        return districtId;
    }

    public boolean equals(Object o) {
        ...
    }

    public int hashCode() {
        ...
    }
}

Now the class:

  • Is more concise and thus easier to read and maintain
  • Is immutable and thread-safe
  • Cannot contain illegal null values
  • Does not do any automatic conversions from null to zero.

What are your thoughts?

IE and the CSS Box Model: Wronger than Wrong

A few days ago I posted a little diagram illustrating the CSS box model:

CSS Box Model

I then set out to produce a few simple web pages to further illustrate the concept. In Firefox 2.0, my experiment looks like this:

CSS Box Model in Firefox 2.0

That’s exactly what I wanted. The HTML is really simple:

<div class="outerbox">
  <div class="innerbox">
     blah blah blah
  </div>
</div>

The 100×100 pixel box is a simple GIF with a red border that is part of the image itself, rather than applied via CSS. All of the other colors and borders come from the CSS:

.outerbox {
  background: yellow;
  border: 10px solid black;
}

.innerbox {
  margin: 10px;
  padding: 10px;
  border: 10px solid green;
  background: #cccccc url('100x100square.gif') no-repeat left;
  height: 100px;

  /* this padding pushes the text to the right of the image */
  padding-left: 120px;
}

Bring on IE 7

The exact same page looks like crap in IE 7:

IE 7 Box Model in Quirks Mode

You don’t see any yellow on the top and bottom because the inner box’s margin is ignored. Even worse, the image is clipped on the top and bottom. This is a manifestation of a well known IE bug: the infamous Internet Explorer box model bug.

This is the default behavior of IE 7, known as “quirks mode”.

Standards Mode

To trigger standards mode, add a doctype to the top of the page:

<!DOCTYPE html PUBLIC "-//W3C/DTD HTML 4.01//EN"
  "http://www.w3.org/TR/html4/DTD/strict.dtd">

The Wikipedia Quirks mode article lists many other doctype variations. With this simple addition to the very first line of the web page, IE 7 is a little closer, but still wrong:

IE 7 Box Model in Standards Mode

A Workaround is Possible

Even in standards mode, IE 7 renders my page incorrectly. Through trial-and-error, I determined that IE 7 ignores the inner box margin. To fix the problem, I removed the margin and replaced it with padding on the outer box:

.outerbox {
  background: yellow;
  border: 10px solid black;

  /* Use this padding instead of an .innerbox margin to work in IE 7 */
  padding: 10px;
}

.innerbox {
  /* no more margin here! */

  padding: 10px;
  border: 10px solid green;
  background: #cccccc url('100x100square.gif') no-repeat left;
  height: 100px;

  padding-left: 120px;
}

With this change in place, the page renders correctly in IE 7:

IE 7 Finally Renders Correctly

Summary

You can see all of these examples on my CSS Box Model Experiments page.

Imagine…all of this effort simply to make this HTML render consistently:

<div class="outerbox">
  <div class="innerbox">
     blah blah blah
  </div>
</div>

It’s really pathetic.

What is Shadenvista?

You heard it here first: “Shadenvista”.

…pleasure taken from watching the misfortunes of Vista users.

Here are some random observations after more than 6 months hands-on usage with Vista.

Notepad

Notepad is unchanged in Vista. Unbelievable. All we really need is an editor that can open any type of text file correctly. But open up a file containing “LF” instead of “CRLF” endings, and you get rubbish:

Notepad Requires CRLF

VIM shows how this file should look:

VIM Handles Unix Filetypes

I don’t get it.

Editing System Variables

All we really need is the ability to resize this dialog:

Edit System Variable Dialog

You cannot resize it. Another Vista failure.

Paint

What decade is this? Why hasn’t Paint changed?

Paint Still Sucks in Vista

Searching File Contents

I stumbled upon this while editing my WordPress custom theme. I needed to search for PHP files containing a certain snippet of text. For example, let’s search for files containing “true”:

Search is Still Broken

First, the search screen is incredibly complex. But even worse, the results are WRONG. While the results show numerous .js files, all .php files are ignored.

Just like the failed Windows XP search, Vista only searches through a pre-configured list of file extensions. Since PHP is not on the list, you cannot search these files.

There is a workaround described here. Shouldn’t a modern operating system just let you “search” for text without worrying about these technical details?

URL.openStream() Might Leave You Hanging

The java.net.URL class provides the openStream() method to open an InputStream:

URL myUrl = new URL("http://myhost:port/path/to/something/");
InputStream in = myUrl.openStream();
...
// now use the InputStream to read data

The openStream() method is actually just a shortcut for openConnection().getInputStream(). Here is the code from the URL class:

public final InputStream openStream() throws java.io.IOException {
  return openConnection().getInputStream();
}
Frustrated Computer User

The Problem

You can probably guess that I encountered this issue recently. My client GUI used URL.openStream() to download XML from a REST service. This REST service is just a simple servlet that eventually connects to an Oracle instance.

When the client invoked openStream(), however, the request blocked forever. The client was deadlocked, forcing users to kill the process via task manager. Ouch.

It turns out that Oracle was in a bad state, so the server-side database connection was locked up. One layer up, in the Servlet, the request was blocked. As we continue up the food chain to the client GUI, we find the client blocked on the HTTP request to the servlet.

The Fix

I fixed the problem by adjusting the timeout settings in the client code. The new code looks something like this:

URLConnection conn = url.openConnection();
// setting these timeouts ensures the client does not deadlock indefinitely
// when the server has problems.
conn.setConnectTimeout(timeoutMs);
conn.setReadTimeout(timeoutMs);
in = conn.getInputStream();
...etc

Now, when the same situation occurs (hopefully rarely), the client times out and throws an exception rather than blocking forever. The user sees an error message, but that is a whole lot better than deadlock.

Other Observations

  • The default timeout is 0, which means calls like openStream() block indefinitely. There are cases when you might want this.
  • The fact that my client GUI locked up is a symptom of another bug. Never call methods like this from the event dispatch thread. Alas, we don’t have time to fix everything.
  • I also need to put some timeout logic into the server-side JDBC code.

Google Code Prettify

I just installed google-code-prettify. It only takes a few minutes and the results are really cool:

import java.util.*;

public class Foo {
  private String firstName;

  public Foo(String firstName) {
    this.firstName = firstName;

    // some other junk
  }

  /**
   * Comment here.
   */
  public int getSomething() { ... }
}

Thank you again, Google.

CSS Margins, Borders, and Padding

This is not very original, but I created my own little diagram to illustrate the CSS box model:

CSS Box Model

I found that keeping a printed copy of this diagram helps me when fighting CSS layout issues.

With CSS and HTML, feedback is instant. Edit the file, save it, then hit Refresh in the browser. Perhaps this led to laziness on my part. Rather than taking the time to really understand what was going on, I’d randomly tweak values until I got the layout I wanted.

In the end, however, taking the time to understand this aspect of CSS more deeply has made me a more effective developer.

Now if CSS only worked consistently in every browser…