'. '

WhiningBuilder

From APIDesign

(Difference between revisions)
Jump to: navigation, search
(Multiple Throws)
(Multiple Throws)
Line 7: Line 7:
<source lang="java">
<source lang="java">
public final class Builder<MissingName extends Exception,MissingMIMEType extends Exception> {
public final class Builder<MissingName extends Exception,MissingMIMEType extends Exception> {
-
 
+
public Source build() throws MissingName, MissingMIMEType {
 +
if (this.name == null) {
 +
throw (MissingName)new Exception("name missing");
 +
}
 +
if (this.mimetype == null) {
 +
throw (MissingMIMEType)new Exception("MIME type missing");
 +
}
 +
// create and
 +
return source;
 +
}
 +
public static Builder<Exception,Exception> newFromText(String content) {
 +
// create new builder without name and MIME type
 +
return theBuilder;
 +
}
 +
 +
public Builder<RuntimeException,MissingMIMEType> name(String name) {
 +
// specifying name
 +
this.name = name;
 +
// keeps the "mime type" exception unchanged but
 +
// turns the "name" exception into runtime one
 +
return (Builder<RuntimeException,MissingMIMEType>)this;
 +
}
 +
 +
public Builder<MissingName,RuntimeException> mimeType(String mimeType) {
 +
// specifying MIME Type
 +
this.mimeType = mimeType;
 +
// keeps the "name" exception unchanged but
 +
// turns the "mime type" exception into runtime one
 +
return (Builder<MissingName,RuntimeException>)this;
 +
}
}
}
 +
 +
Please note that ''MissingName'' and ''MissingMIMEType'' are generics type parameters - e.g. they aren't real exceptions, just specifications/place holders for the actual {{JDK|java/lang|Exception}} subclass. This gives us early compile time warning as in [[ChameleonBuilder]]. When one tries to compile:
 +
 +
<source lang="java">
 +
private static Source buildMySource() {
 +
return Source.newFromText("function hi() { print('Hi'; }").
 +
build();
 +
}
 +
</source>
 +
 +
one gets a compilation error, as the build method throws a [[checked exception]]. Even if one specifies '''name''', the error still remains. Only if both '''name''' and '''mimeType''' are specified the [[checked exception]]s go away (as they are replaced by runtime [[exception]]s).
 +
 +
=== Explaining Why ===
 +
 +
=== Drawbacks ===
 +
 +
=== Evolution ===
[[TBD]]
[[TBD]]

Revision as of 13:31, 16 June 2016

One problem with ChameleonBuilder is that the change of the return type works only for a single essential attribute. Can we modify the [[builder] pattern to work with multiple such attributes? Another problem is the reported error - it doesn't push the user towards proper fix. Can we improve that and encourage cluelessness in users of our builders?

Contents

Multiple Throws

Java allows only a single return value - yet, it allows multiple throws - and throwing an exception is kind a return value as well. As the BuilderWithConditionalException it is possible use a generic type parameter to control whether the exception thrown from the build() method is checked exception or unchecked one. Let's do the same with multiple throws for two essential attributes (name and mimeType):

public final class Builder<MissingName extends Exception,MissingMIMEType extends Exception> {
  public Source build() throws MissingName, MissingMIMEType {
    if (this.name == null) {
      throw (MissingName)new Exception("name missing");
    }
    if (this.mimetype == null) {
      throw (MissingMIMEType)new Exception("MIME type missing");
    }
    // create and
    return source;
  }
 
 
  public static Builder<Exception,Exception> newFromText(String content) {
    // create new builder without name and MIME type
    return theBuilder;
  }
 
  public Builder<RuntimeException,MissingMIMEType> name(String name) {
    // specifying name
    this.name = name;
    // keeps the "mime type" exception unchanged but
    // turns the "name" exception into runtime one
    return (Builder<RuntimeException,MissingMIMEType>)this;
  }
 
  public Builder<MissingName,RuntimeException> mimeType(String mimeType) {
    // specifying MIME Type
    this.mimeType = mimeType;
    // keeps the "name" exception unchanged but
    // turns the "mime type" exception into runtime one
    return (Builder<MissingName,RuntimeException>)this;
  }
}
 
Please note that ''MissingName'' and ''MissingMIMEType'' are generics type parameters - e.g. they aren't real exceptions, just specifications/place holders for the actual {{JDK|java/lang|Exception}} subclass. This gives us early compile time warning as in [[ChameleonBuilder]]. When one tries to compile:
 
<source lang="java">
private static Source buildMySource() {
  return Source.newFromText("function hi() { print('Hi'; }").
    build();
}

one gets a compilation error, as the build method throws a checked exception. Even if one specifies name, the error still remains. Only if both name and mimeType are specified the checked exceptions go away (as they are replaced by runtime exceptions).

Explaining Why

Drawbacks

Evolution

TBD

Personal tools
buy