Urban Potato

Software for the Masses

Writing a software API for the masses is full of conflicting puzzles to solve.


Writing a software API for the masses is full of conflicting puzzles to solve.

I work on the .NET framework, writing the Windows Forms and component model APIs. One of the hardest parts of this job is trying to nail our target audience. Or audiences, as the case may be. We try to write an API for VB users, C# users and MC++ users. While there is some overlap, these are vastly different types of users. Some folks have never cracked a data structures book, while others eat assembly code for breakfast. Don't go assuming you know which one is which: I know plenty of "VB" developers who are right at home doing completely insane things in VB that many hardcore C++ developers wouldn't know how to tackle.

How do you write a single API for all types of users? Should you even try? I think the answer is definitely "yes". While some would consider Visual Basic .NET a huge increase in complexity over VB 6.0 (and it is...), the .NET framework has provided something unique for the first time in the history of a Microsoft delivered API: consistency. No longer do VB users have to wait for someone to wrap the latest API in a library or control they can use. The APIs come out of the box ready for all to use them.

But man, oh man, is there a lot of debate. People with PhDs in computer science and dozens of years of industry experience are trying to wrap their head around trying to make an API simple. After all, simple is relative; what's simple to one person may not be simple to someone else (hey, I invented the designer framework in .NET. Anyone understand it?) To compound that, often a nice simple API can be misused. One recent debate we've been having is on File.Exists. It's a handy method to tell if a file exists on disk or not. For example, let's open a file if it exists:

if (File.Exists(path)) {
    Stream s = new FileStream(path);
}

Simple, right? Simple yes, but incorrect code. Another process somewhere else on the computer could sneak in and delete the file between the Exists call and the opening of the file. So, you've got to add a try/catch:

if (File.Exists(path)) {
    try {
        Stream s = new FileStream(path);
    }
    catch(IOException) {
    }
}

But, if you've already added the try/catch, then you really don't need the File.Exists code any longer. The File.Exists method was added so everyday people could use the API. Most programmers won't ever think about these types of race conditions and their applications will work fine for years and years. But folks who write operating systems think about these sorts of things a lot. After all, you wouldn't want the operating system to crash if two people tried to access the same file at the same time.

So which way do you go? Offer an easy to use API that makes it easy to write incorrect code? Or write an API that is as hard to misuse as it is to use? We're tring really hard to strike a balance with the .NET Framework. One of the really exciting things about the framework is it is much easier to use than traditional Windows APIs. In most places, we have done a pretty good job of trying to steer people toward correct code without making the object model hard to use. If you make the obvious and easy path the correct path, people write better code without evening knowing it. That's the challenge we're facing now with each new version of the framework. You can bet that there will be much more debate in the hallways of Microsoft as we continue on our journey.

Brian • 7/10/2003 10:46:41 PM