When to Use Libraries: The Pragmatic Answer September 23rd, 2003

Tom Klaasen recently suggested using the IOUtil library to ease the work Java developers must do to create a String that contains the entire content of an InputStream. His suggestion looks set to spark some lively discussion.

I believe the discussion is a subtype of a more general argument, one that I don't feel deserves the time it enjoys.

First, there are times when it makes sense to store the entire output of a stream in a String. One very good example is the case where you'd like to execute fairly complex regular expressions over the entire String.

Once you've accepted that there are times when this is a necessary operation, the rest of the argument boils down to whether or not to use APIs. Not a particularly fresh debate, but one we don't seem to have been able to put behind us yet, sadly.

I think it's simple; if an API meets your needs and pays for itself, use it. If not, roll your own.

In this particular example, the conversion requires 7 lines of code:

private String getInputStreamAsString(PlainTextInputStream urlInput)
       throws IOException
{
   // The size of the buffer depends on your application.  Either
   // size it to the typical smallest input size or generalize
   // this method to take the size as an argument.
   //
   int readSize = 512;
   byte[] buffer = new byte[readSize];

   int bytesRead;
   StringBuffer urlContent = new StringBuffer(readSize);
   while ((bytesRead = urlInput.read(buffer)) != -1) {
	urlContent.append(new String(buffer, 0, bytesRead));
   }
   String templateText = urlContent.toString();

   return templateText;
}

I'd say that an API would have to be solving more problems than just this one to pay for itself.

The code fragment above comes from a component I wrote, which has to grab and manipulate content from a remote web page. At first, I home-rolled my 7 lines of code and I believe that I made the right decision.

Then, I realized that getInputStreamAsString() was a necessary artifact of my decision to fetch web page content using the despicable java.net.URL and its nefarious henchmen.

When I decided to use Jakarta Commons httpclient instead, I bade a none-too-fond farewell to not only this little home-rolled carrot, but also a good 20 lines of ugly code surrounding the creation and interaction with the URL connection. I believe that this was also the right decision, and the change was painless because I originally encapsulated the dirty work properly.

My point is that it comes down to whether software pays for itself, and that whether or not it does so may well change through the lifecycle of the system. The important thing is to design your software in a way that allows you to change your mind later.

I think a lot of people don't get this because they have the time to fixate on tiny issues of principle. As you get older, you realize how short life is. That process sharpens your sensitivity to the importance of pay-off.

This reminds me, yet again, that I simply must write a review of Martin Fowler's book, "Refactoring: Improving the design of existing code", soon. Stay tuned.

Leave a Reply