BuilderWithConditionalException

From APIDesign

(Difference between revisions)
Jump to: navigation, search
(Throw on I/O Error)
(Throw only for I/O)
Line 38: Line 38:
=== Throw only for I/O ===
=== Throw only for I/O ===
-
[[TBD]]
+
The option that [[I]] come up with is to parametrize the builder with the exception the ''build()'' method is going to throw:
 +
 
 +
<source lang="java">
 +
public final class Builder<E extends Exception> {
 +
public Source build() throws E {
 +
// construct and/or read the content and
 +
return source;
 +
}
 +
 
 +
public static Builder<IOException> newFromFile(File file) {
 +
// ....
 +
}
 +
 
 +
public static Builder<RuntimeException> newFromText(String text) {
 +
// ...
 +
}
 +
}
 +
</source>
 +
 
 +
The actual code is shown at [https://github.com/jtulach/truffle/commit/a61f1e18356399ce6a8a2fbffa2b2a9fdc0e5301 my github commit]. It properly encourages users to handle I/O exceptions when needed, but doesn't annoy them when there is no need.

Revision as of 13:38, 10 June 2016

The builder pattern is gaining more and more popularity in the APIs that I design: In Truffle API we are trying to use it a lot. For example an instance of the PolyglotEngine is constructed via a builder obtained from its newBuilder() method.

Builder for Source

These days I am trying to use the builder pattern also for construction of Source. Rather than having various (and overloaded) methods with fromFileName, etc. we'd like to have:

Source source = Source.newFromFile(file).
   mimetype("text/javascript").
   name("FancyName.js").
   build();

It works fine and allows the users to specify only those properties that are needed - for example one can omit the name - then it would be derived from the name of the file. The same applies to mimetype.

Throw on I/O Error

The builder pattern delays reading of the actual file up until the build() method is called. As reading of a file means an I/O operation and as each I/O operation in Java may yield checked IOException, it is desirable for the build() method to propagate it to the caller:

public Source build() throws IOException {
   // construct and
   return source;
}

However there is more. The builder may also construct a {{truffle|com/oracle/truffle/api/source|Source} object from already provided text. The usage looks like:

Source source = Source.newFromText("6 * 7").
   mimetype("text/javascript").
   name("FancyName.js").
   build();

but in this case there is no I/O operation - e.g. throwing IOException from the build() method isn't appropriate. Doing so would actually expose the biggest flaw of checked exceptions in Java - forcing people to catch them when there is no need/no recovery. Can that be fixed?

Throw only for I/O

The option that I come up with is to parametrize the builder with the exception the build() method is going to throw:

public final class Builder<E extends Exception> {
  public Source build() throws E {
    // construct and/or read the content and
    return source;
  }
 
  public static Builder<IOException> newFromFile(File file) {
    // ....
  }
 
  public static Builder<RuntimeException> newFromText(String text) {
    // ...
  }
}

The actual code is shown at my github commit. It properly encourages users to handle I/O exceptions when needed, but doesn't annoy them when there is no need.

Personal tools
buy