PARTICIPANT:This guy did not make it.
[Reading names of classes]
Binary reader, Buffered stream, Reads and writes...
[Pauses, Scrolls through list of classes].
So let me just...stream writer. Implements a text writer writing characters to a stream in a particular encoding. Umm...stores an underlying string. Text...hmmm. Text reader, text writer. Represents a writer that can write a sequential series of characters. This class is abstract.
[Pause]
Ummm...
[scrolls up and down through list of classes]
So it, you know, it sounds to me like it's, you know, it's more low-level kind of stuff. Whereas I just want to create a text file. Umm.
[Points at the description of one of the classes]
Characters to a stream in a particular encoding. I'm not sure what...obviously a text writer for writing characters to a stream.
[Clicks on the link to view more details about the TextWriter class. Then looks at list of classes that derive from TextWriter]
System dot IO dot StringWriter. This seems too low-level to me to be a text writer thing but maybe I am wrong. Umm...
[scrolls through description of the TextWriter class]
Text writer is designed for character output, whereas the stream class is designed for byte input and output.
[Sigh. Clicks on link to view TextWriter members]
Probably going where no man should have gone before here.
Neither did any of the other 7 professional programmers that were participants in that experiment! Their task was "to write a program that would write to and read from text files on disk". They had 2 hours for that and could browse all of the relevant documentation. They were testing the API of the then new programming framework called .NET - the programmers did not know it yet - but they had programmed in VisualBasic. This is an example code fragment using the file writing API that they were expected to write: After that experiment they added a new 'File' API: and ran the experiment again. This time all participants were able to complete each task in 20 minutes and without browsing the documentation. This is the story from the "Chapter 29 How Usable Are Your APIs?" in Making Software.
Fascinating puzzle - isn't it? The article proposes following solution to it: there are three types of programmers - opportunistic, pragmatic and systematic. The opportunists tend to use the high-level abstractions and try and experiment with what would work and they intuitively get the File API as opposed to the StreamWriter
API. And it just happened that all 8 participants of that study were opportunist programmers?!
The developers who participated in the file I/O studies were very much in the opportunistic camp. The way they used the FileObject
class in the second study was almost a perfect example of opportunistic programming. The contrast with the more abstract classes they had to use in the first study was stark. Indeed, one of the main findings from the file I/O studies was that without such high-level concrete components, opportunistic developers are unlikely to be successful.
Sounds like a weak argument:
- Copy pasting examples and playing with the code is the most efficient way to learn a new API - so I suspect that what they call 'opportunistic programming' is actually learned behaviour that would be characteristic of any experienced programmer.
- Expecting a file related API sounds quite natural and not really related to being opportunistic or systematic, the task at hand was exactly file related IO and in most programming languages there is such an API, it also makes sense that there is one because file operations are very common.
- I don't see anything higher level or more concrete in the
FileObject
related example code - it looks on the same level of abstraction as theStreamWriter
code. The authors claim that it is the fact that you have bothStreamWriter
andStreamReader
that makes it lower level thenFileObject
which is only one - but I don't see how that follows.
There are only two hard things in Computer Science: cache invalidation and naming things.Naming things also comes out as quite important.