Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Why InputStream Design Is Wrong

DZone's Guide to

Why InputStream Design Is Wrong

Java Object orientation master Yegor256 dissects Java's InputStream and why he feels the design is completely wrong

· Java Zone
Free Resource

Bitbucket is for the code that takes us to Mars, decodes the human genome, or drives your next car. What will your code do? Get started with Bitbucket today, it's free.

It's not just about InputSteam, this class is a good example of a bad design. I'm talking about three overloaded methods read(). I've mentioned this problem in Section 2.9 of Elegant Objects. In a few words, I strongly believe that interfaces must be "functionality poor." InputStream should have been an interface in the first place and it should have had a single method read(byte[]). Then if its authors wanted to give us extra functionality, they should have created supplementary "smart" classes.

   
    A Serious Man (2009) by Coen Brothers   
     A Serious Man (2009) by Coen Brothers    
   
   

This is how it looks now: 

   
abstract class InputStream {
  int read();
  int read(byte[] buffer, int offset, int length);
  int read(byte[] buffer);
}
   
   

What's wrong? It's very convenient to have the ability to read a single byte, an array of bytes or even an array of bytes with a direct positioning into a specific place in the buffer!

However, we are still lacking a few methods: for reading the bytes and immediately saving into a file, converting to a text with a selected encoding, sending them by email and posting on Twitter. It would be great to have the features too, right in the poor InputStream. I hope the Oracle Java team is working on them now.

In the mean time, let's see what exactly is wrong with what these bright engineers designed for us already. Or maybe let me show how I would design InputStream and we'll compare:

   
   
interface InputStream {
  int read(byte[] buffer, int offset, int length);
}
   
   

This is my design. The InputStream is responsible for reading bytes from the stream. There is one single method for this feature. Is it convenient for everybody? Does it read and post on Twitter? Not yet. Do we need that functionality? Of course we do, but it doesn't mean that we will add it to the interface. Instead, we will create supplementary "smart" class:

   
   
interface InputStream {
  int read(byte[] buffer, int offset, int length);
  class Smart {
    private final InputStream origin;
    public Smart(InputStream stream) {
      this.origin = stream;
    }
    public int read() {
      final byte[] buffer = new byte[1];
      final int read = this.origin.read(buffer, 0, 1);
      final int result;
      if (read < 1) {
        result = -1;
      } else {
        result = buffer[0];
      }
      return result;
    }
  }
}
   
   

Now, we want to read a single byte from the stream. Here is how:

   
   
final InputStream input = new FileInputStream("/tmp/a.txt");
final byte b = new InputStream.Smart(input).read();
   
   

The functionality of reading a single byte is outside of InputStream, because this is not its business. The stream doesn't need to know how to manage the data after it is read. All the stream is responsible for is reading, not parsing or manipulating afterwards.

Interfaces must be small.

Obviously, method overloading in interfaces is a code smell. An interface with more than three methods is a good candidate for refactoring. If methods overload each other — it's serious trouble.

Interfaces must be small!

You may say that the creators of InputStream cared about performance, that's why they allowed us to implement read() in three different forms. Then I have to ask again, why not create a method for reading and immediately posting on Twitter? That would be fantastically fast. Isn't it what we all want? A fast software which nobody has any desire to read or maintain.

   


Bitbucket is the Git solution for professional teams who code with a purpose, not just as a hobby. Get started today, it's free.

Topics:
java ,code ,design ,patterns

Published at DZone with permission of Yegor Bugayenko, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

THE DZONE NEWSLETTER

Dev Resources & Solutions Straight to Your Inbox

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.

X

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}