Sunday, 1 August 2010

Java: a fluent I/O API (4/4)

This is the fourth post about my experiments with a fluent I/O API. This post covers conclusions and limitations of the implementation. You can find downloads and source repository details further down the page.

Conclusions

In my first post, I outlined some of the goals of the API. Here's a run down of how the API measures up.

Goal: reduce the amount of code required for I/O operations

In terms of the number of characters you're required to type, the API does do its job. It won't necessarily result in fewer lines of code, but the fluent style combined with IDE code completion should make them easier to write.

Where the API might fall down is in using many external stream types. If you have to write a bunch of Doctor implementations just to decorate a stream, this may result in more code than just using the core API.

Goal: be extensible

The Doctor mechanism is quite powerful. It is possible to chain a bunch of these operations together to produce a single Doctor type that transforms an input type through a series of intermediate types to an output type.

The main weakness of the current Doctor implementation is in its generics support. The type support is weak, despite the fact that the types are known at compile time. Writing a method in a parameterized type to transform a parameterized type of a parameterized type (T<A<B>>) to another parameterized type of a parameterized type is tricky to get working in a single compiler. Getting it working in multiple compilers has so far proved beyond my abilities. As a result, some of the methods just take wild cards and trust the programmer to do the right thing.

This is why many of the Doctor implementations are static instead of being returned via strongly typed methods (as in the Collections.emptySet-style methods). There is no advantage in doing this until stronger typing can be enforced in other parts of the API.

Goal: interoperate with the existing java.io API and any 3rd party frameworks that build on it

Support can be added for these stream types via the Doctor type. It would be necessary to write a support library for each I/O library.

Goal: reduce the opportunities for resource leaks and poor error handling

To use the API, you have to use a Closer instance. Whether this will drum into people that they have to use the try/finally pattern or not is another matter. But if all the examples do, perhaps we can hope people will copy them.

Goal: encourage good character data transcoding

The API doesn't let the user create an InputStreamReader/InputStreamReader without specifying a Charset instance. This should reduce the number of character transcoding bugs. The API also makes it easy (and preferable) to use UTF-8, which should reduce character-related data-loss bugs.

Goal: add some support for runtime exception handling

Switching entirely to runtime exceptions from IOException requires a lot of stream type decorators. The API adds limited support for some operations, but I'm sure there is more that could be done.

Goal: be small, clean and easily understood

This one is a bit subjective. The type and method naming definitely needs work.

The API in its current form has 28 types. This is too many. Some of these should be removed and there is scope for better division via packages.

Other issues and limitations

To me, the glaring omission is NIO support. I'm sure something can be done here, but I'm still mulling over exactly what.

Source code

You can download a binary here: fluentio-0.0.1-SNAPSHOT-dist.zip

All the sources are available in a public Subversion repository.

Repository: http://illegalargumentexception.googlecode.com/svn/trunk/code/java/
License: MIT
Project: fluentio

Related posts

Comments & criticism are welcome.

1 comment:

  1. Hello, well that was an interesting articles, I don't manipulate IO that often to have a worthy feedback, but I like the approach. In these time there might be a good opportunity to create a good fluent API. You might want to propose your ideas to the Google Guava project.

    Maybe you might can offer to the API an IO builder style, instead of returning specific objects such InputDie or ReaderDie.

    As for testing you should defintely try mockito. Maybe there's some idea to take from this library too. The OO design of the mockito is somehow inspiring compared to other "old school" libraries.

    As for the Doctors, there should be precoded utilities like the Preconditions or Functions.

    ReplyDelete

All comments are moderated