I've been experimenting with fluent API design. You can find the sources in part 4.
I've often been frustrated with the verbosity of Java I/O. Handling close with decorators got better with the introduction of the Closeable interface, but there's still a bit of boilerplate. This post describes a new fluent API to wrapper around the existing I/O API.
The goals of this API are:
- Reduce the amount of code required for I/O operations.
- Be extensible.
- Interoperate with the existing java.io API and any 3rd party frameworks that build on it (like Guava and Apache Commons I/O).
- Reduce the opportunities for resource leaks and poor error handling.
- Encourage good character data transcoding.
- Add some support for runtime exception handling.
- Be small, clean and easily understood.
- Doctor: to revise, alter, or adapt in order to serve a specific purpose or to improve the material
- Die: any of various devices for cutting or forming material in a press or a stamping or forging machine
Traditional Java I/O
The following method replaces all the newlines in a UTF-8 text
input file with unix-style
This code does its best to be bullet-proof. Even if a stream
constructor were to throw a
RuntimeException, the use of
ensures that the contract for the preceding streams is enforced and they
are closed properly. The downside: a load of extra lines and a nested
It is possible to leverage the
to eliminate some of this code. Here is the method rewritten to use
from the new API:
CoupledCloser type just holds two
Closer just holds a reference to the last
passed to its
This code manages to eliminate a try-finally block. The calls are compressed onto fewer lines, but it is arguable whether this code is clearer.
Here is the transform method rewritten to use the new API:
To make the type system visible, here is the code broken down into individual calls:
This code is obviously way worse than just using the core API, so it should be clear why sticking to the fluent style is prefereable.
doctor method illustrates the main extensibility
mechanism in the API. By writing
implementations, you can doctor stream types in any manner you see fit.
Since no I/O API can cover every conceivable stream decorator, this is a
necessary compromise to the fluent design pattern.
- Part 1: introduction
- Part 2: extending the API
- Part 3: error handling
- Part 4: conclusions and downloads
Comments & criticism are welcome.