3

How to handle error conditions when writing a Java API/Utility

This is my Implementation for my API interface

public void bin2zip(InputStream[] is,OuputStream os, String[] names)
{
   //if number of streams and number of names do not match do something 
}

What I am trying to do is handling a case when the length of the is != length of name.

How do i handle this. I dont want my API to do some work until ArrayOutOfBound exception to be thrown. I want to catch this early.

One solution is something like this:

if it does not match I throw

if(is.length==names.length)
            throws new Exception("ParemeterValidationException: The inputstream array and name array length should match");
if(containsInvalidFileName(names))
            throws new Exception("ParemeterValidationException: The names array length should contain valid filenames");

Also, can this be done compile time using DataDependency (I can make ValidationClass for the API and make sure the developer get hold of this object to pass on to this conversion API) or the runtime exception is the best way?

I believe doing a ValidationClass will make API use complicated

I did go through some materials (if anyone interested), but need some directions.

  1. http://lcsd05.cs.tamu.edu/slides/keynote.pdf
  2. Java: checked vs unchecked exception explanation
  3. http://docs.oracle.com/javase/tutorial/collections/interoperability/api-design.html
Community
  • 1
  • 1
Dexters
  • 2,419
  • 6
  • 37
  • 57
  • 1
    If you don't want to wait to manually catch an `ArrayIndexOutOfBounds`, I would perdonally throw an `IllegalArgumentException`, since you alreasy know the value range of which the argument should lie within – Vince Aug 13 '14 at 16:12
  • And I would not throw a RuntimeException in this case – Leo Aug 13 '14 at 16:13
  • @Leo That alone doesn't seem as if it would help much. Mind explaining why you would choose a different route than throwing a RuntimeException? – Vince Aug 13 '14 at 16:18
  • @VinceEmigh just a matter of preference. Since he's building an API, IMO, declaring the exceptions would help to show how to use it. – Leo Aug 13 '14 at 16:20

2 Answers2

3

Wherever possible, don't let end users screw it up.

public final class Bin2Zipper {
    private final List<InputStream> inputStreams = ...;
    private final List<String> names = ...;    

    public BinZipper() {
    }

    public void add(final InputStream is, final String name) {
        this.inputStreams.add(is);
        this.names.add(name);
    }

    public void bin2zip(final OutputStream os) {
        // ...
    }
}

A fluent interface might even be better. Then your code would look like:

Bin2Zipper.add(is1, name1).add(is2, name2).add(is3, name3).toZip(os);

public final class Bin2Zipper {

    private final List<InputStream> inputStreams = ...;
    private final List<String> names = ...;

    private Bin2Zipper(final InputStream is, final String name) {
         this.inputStreams.add(is);
         this.names.add(name);
    }

    public static Bin2Zipper add(final InputStream is, final String name) {
         return new Bin2Zipper(is, name);
    }

    public Bin2Zipper add(final InputStream is, final String name) {
         this.inputStreams.add(is);
         this.names.add(name);
         return this;
    }

    public void zip(final OutputStream os) {
        ...
    }
}

Where these fall down is when the client starts off with the two arrays. In that case, it can be annoying for them to have to loop over all the entries themselves. I think it's still worth it. If you don't, then you'll have to compare the sizes of the inputs right away. You almost certainly want to throw an unchecked exception, probably an IllegalArgumentException like Vince said.

Eric Stein
  • 13,209
  • 3
  • 37
  • 52
  • This does not seem to do what he wants, as he is passing in arrays of values, wanting to ensure the values are legal (both values share the same length). This answer doesn't seem to be relevant, unless you don't mind adding some context to your answer, explaining how doing this solves his problem – Vince Aug 13 '14 at 16:34
  • 3
    @VinceEmigh I disagree. He's clearly developing the API boundary now, since he talks about alternate designs (validation class, array length check). The problem he states is "What I am trying to do is handling a case when the length of the is != length of name". This design addresses that by ensuring that there are always the same number of elements in both Lists. – Eric Stein Aug 13 '14 at 16:40
  • Thanks, this gives me good perspective to limiting use errors – Dexters Aug 15 '14 at 16:13
0

I think your solution of comparing the array lengths is perfectly appropriate. I think in this case you should throw an IllegalArgumentException; this exception is defined in the standard and used by most standard functions doing this kind of checking.

Many standard libraries use this kind of interface it is easily understood.

That said I think you should prefer an interface that simply doesn't facilitate such misuse such as that suggested by @Eric - the library everybody likes to use is the one that works first time every time because it's too simple to mess up.

Elemental
  • 7,365
  • 2
  • 28
  • 33