API Consistency and Developer Comfort
by Michael S. Kaplan, published on 2004/12/19 02:07 -05:00, original URI: http://blogs.msdn.com/b/michkap/archive/2004/12/19/325199.aspx
If anyone ever looked at the Win32 API and tried to claim that the functions were implemented consistently, then odds are they are clinically insane. If you know what I mean.
So thats not what I am thinking about.
I am thinking about the little consistencies that one can find in families of APIs, such as
- Most of the NLS APIs take an LCID, all of which use the behavior of ConvertDefaultLocale on the LCID you pass in
- The registry APIs returning the error value so that 0 means success whereas it would mean failure for most other APIs.
- The "Ex" versions of keyboarding APIs take an HKL parameter, and their non-Ex counterparts use the current default
- The NLS APIs can take a buffer size for the in buffer or you can pass -1 to indicate it is null terminated
- Most of the GDI APIs return a BOOL
- Flags and the way they are named seem consistent within families in USER, GDI, KERNEL, NLS, etc., even though wildly different when compared between these families
- Buffer semantics are again generally consistent within families
This is something that I always personally found to be comforting -- like there were teams that had the institutional memory of the APIs they have and that when they add them they try to keep these little consistencies so that people who use them could have intelligent guesses as to behavior so if they understood some APIs they could end up understanding a lot of the rest.
But the other day I was talking to some colleagues who said that they never really grouped API behaviors this way, and they minimized the actual benefit to trying to maintain such a consistency.
So what do you think? Is there a benefit to the little consistencies? Do you believe they are even present? Or is that just me assuming patterns where there are none of any importance?
Also, a random note to answer a question posed by Jonathan Wilson in the "suggest a topic" post -- the LoadKeyboardLayoutEx API sort of follows the above pattern with "ex" versions of keyboard APIs but it also involves other stuff like windowstations. Its not documented because it does not really provide any usable functionality outside of the USER subsystem that one cannot get with existing APIs like LoadKeyboardLayout. But the USER subsystem does have to care about things like separate windowstations....
This post brought to you by "વ" (U+0ab5, a.k.a. GUJARATI LETTER VA)
# Uwe Keim on 19 Dec 2004 12:46 AM:
Usually, I only notice if an API does NOT follow a schema.
E.g. the .NET Framework naming rules state that 2-letter-abbreviations should be made uppercase (if I recall correctly), but e.g. the "SqlDbType" should read "SqlDBType" according to that rules... So there is an inconsistency in some API names.
# Sebastian Redl on 19 Dec 2004 9:16 AM:
The consistencies within families are there. For example, all the Create* functions in the process, thread and sync family return NULL as error value (except for CreateProcess, which doesn't return a HANDLE in the first place, for understandable reasons.)
Yet the Storage function CreateFile, which returns a HANDLE too, returns INVALID_HANDLE_VALUE.
Yes, within families there is consistency. Still I absolutely don't understand why this is limited to families. How can it be that there were no standards set for the API? How can one developer group follow one pattern and another a different one? Where is the communication? Where are the standards?
The inconsistencies are one of the things that make the WinAPI so hard and error-prone to use. Perhaps even the main thing.
While having consistency within families is nice and helps a little, there are far too many families to keep track of. In practice, I still have to look up every function to see how it indicates an error. And because there are some inconsistencies even within families, I can't trust this not to be the case with the very function I'm currently calling, so in practice I still have to look up every single function and can't rely on the documentation of the function from the same family I used a few moments before.
So the consistencies help very little. The truth is that they shouldn't be anything remarkable in the first place. OpenSource projects like GTK, where ther eare hundreds if not thousands of completely disjoint programmers working on it, have better consistency than the WinAPI, which admittedly evolved over years, but still always had the same central guidance, which should have managed to keep them all consistent.
# Michael Kaplan on 19 Dec 2004 1:25 PM:
Sebastian -- I am not going to disagree with a statement that standards across all APIs would have been a good thing. But the train has already left the station on that one, right?
I am also uncertain about how much the consistencies help -- they feel "comfortable" to me but I do not think there is an easy way to translate a feeling of comfort into an actual productivity gain.
At the moment, I'm looking at potential new APIs and how one should proceed there. Are the minor consistencies worth trying to preserve? Or should they be designed based on their own requirements without considering such factors? Its a tough question....
# Larry Osterman on 19 Dec 2004 7:12 PM:
Fascinatingly enough, many of the "families" of APIs are a reflection of the preferences of the developers who write the APIs.
The developer who write most of the file I/O APIs felt that APIs should just return success and failure. The developer who write the user mode registry APIs felt that an API should return the status code (he was following from the convention of the Lan Manager (Net*) APIs).
Similar things happened for GDI and user...
# Michael Kaplan on 19 Dec 2004 7:24 PM:
Indeed, that is definitely the case for the NLS APIs as well, when it comes to the "size of buffer or -1 for null terminated" and "don't touch the target buffer on failure" principles.
I could even name names for some of these preferences (though I am sure Larry could name more!).
And in truth there are times that "preferences" here is a shorthand for very careful thought about what the semantic should be. Though that may not have happened as often as we all would have liked, in retrospect.
go to newer or older post, or back to index or month or day