Application Security Testing: An Integral Part of DevOps
|Bruce Eckel's Thinking in Java||Contents | Prev | Next|
The Java IO stream library does seem to satisfy the basic requirements: you can perform reading and writing with the console, a file, a block of memory, or even across the Internet (as you will see in Chapter 15). It’s possible (by inheriting from InputStream and OutputStream) to create new types of input and output objects. And you can even add a simple extensibility to the kinds of objects a stream will accept by redefining the toString( ) method that’s automatically called when you pass an object to a method that’s expecting a String (Java’s limited “automatic type conversion”).
There are questions left unanswered by the documentation and design of the IO stream library. For example, it would have been nice if you could say that you want an exception thrown if you try to overwrite a file when opening it for output – some programming systems allow you to specify that you want to open an output file, but only if it doesn’t already exist. In Java, it appears that you are supposed to use a File object to determine whether a file exists, because if you open it as an FileOutputStream or FileWriter it will always get overwritten. By representing both files and directory paths, the File class also suggests poor design by violating the maxim “Don’t try to do too much in a single class.”
The IO stream library brings up mixed feelings. It does much of the job and it’s portable. But if you don’t already understand the decorator pattern, the design is non-intuitive, so there’s extra overhead in learning and teaching it. It’s also incomplete: there’s no support for the kind of output formatting that almost every other language’s IO package supports. (This was not remedied in Java 1.1, which missed the opportunity to change the library design completely, and instead added even more special cases and complexity.) The Java 1.1 changes to the IO library haven’t been replacements, but rather additions, and it seems that the library designers couldn’t quite get straight which features are deprecated and which are preferred, resulting in annoying deprecation messages that show up the contradictions in the library design.
However, once you do understand the decorator pattern and begin using the library in situations that require its flexibility, you can begin to benefit from this design, at which point its cost in extra lines of code may not bother you as much.