Saturday, July 05, 2008

The art of Microsoft (R) Windows (TM) programming

Eric S Raymond has an amazing set of Unix Zen koans here. His book, The Art of Unix Programming summarizes the Unix philosophy extremely well. I've wondered for a while if there was an equivalent for the Microsoft way. The closest I came to was an article by Joel Spolsky called Biculturalism. There were other posts I found on philosophy of specific windows features, but I failed to find anything that describes the Microsoft way of programming.

Recently, we had a talk by Dr. Sundar Sarukkai from NIAS on the "Philosophy of Science". Suggesting that despite it's attempts, science wasn't independent of the observer, and that it had a belief system not very unlike religion, and with its language, mathematics being incomplete, science too was incomplete, Dr. Sarukkai raised a few hackles amongst the listeners. Personally, while I thought that they were all interesting observations I didn't agree with the conclusions he drew from them, but that is a story for another day.

What this talk did though is to force my train of thought towards the station of philosophy - specifically, programming philosophy for Windows. Now, Eric Raymond and Joel Spolsky make the point about the GUI being part of the application instead of being an afterthought (as in Unix), and I agree with that. But a fundamental principle of every Microsoft API is to get programmers hooked with rapid development of basic applications. As early as MFC, you could create a fully functional Notepad application without writing a single line of code. Then there was COM that attempted to hide the complexity of developing distributed applications from you. Today, we have .NET, with LINQ, giving you hidden code generators and attributes for everything from RPC to serialization to workflow management. The underlying principle of all these APIs and platforms is to give users a helping hand when they start, by hiding complexity. In short, a large part of the new Microsoft APIs are tailor-made for the novice-intermediate programmer, who wants to develop a mashup or a cool Forms picture viewer for his grandmom.

This approach has a serious drawback. Because programmers don't have to invest upfront in learning these APIs (instead relying on code generators and other tools/constructs), there is no incentive to learn the basics well. So, when something breaks, or if a programmer wants to do something that the API designer didn't anticipate, he is left high and dry, because he hasn't made the investment in knowing what is happening underneath.

In addition, many crucial features are provided as random attributes or "facts you need to know". Therefore, the transition from a novice programmer to an intermediate one is accomplished by increasing your vocabulary, something developers aren't comfortable doing (I mean, if you could remember things instead of having to learn them, why would you take up computer science instead of history?) Of course, you can turn to your favourite search engine for help, but many times, that isn't sufficient.

The other aspect I've recognized is the preference given to large, monolithic APIs and heavy integration. Of course, it serves Microsoft well to have its tools and APIs jell with each other, but the heavy levels of integration (think for instance, an ASP.NET grid view) and monolithic APIs end up leading to an all-or-none approach that developers are forced to choose between. Customization is next to impossible, and important aspects of the code get hidden from the developers leading to performance headaches and again, maintenance nightmares as the codebase evolves.

I'll update this post as I think of others.

API headaches

As a programmer, you sure have your favourite API-thrashing story. You know, the one where a destructor fails to release memory held by the object, causing an innocuous leak that is only caught when a million-dollar contract is at stake. The one where you need to call a function twice to use it once. And the one where you sacrifice your types at the altar of someone who thought it would be fun to use void pointers in a public interface.

API design is notoriously difficult. This paper says why. Suffice to say that the task of balancing conflicting requirements, for instance, of power v/s ease-of-use, along with constraints imposed by the target language, by the large (unknown) user base, and of issues like maintainability, extensibility, and performance - you have hell on your hands.

Still, I can't help but wonder why the APIs I use on a daily basis have the flaws they have. Why, for instance, does the Linq Aggregate function throw an InvalidOperationException when I pass an empty list to it. Why, for instance, the DateTime class does not comment what its MinValue is, beyond saying that it is public, static, readonly, and is the minimum possible date. Why, for instance, should the Enumerator be modified to check for end-of-container.

I have similar problems with some language features. The illogical distinction between structs and classes in C#. The whole mess created when operator overloading (specifically, op ==) meets reference equality.

I'm just venting. The C# language and the .NET runtime have amazing utility for programmers and have replaced native C++ as my choice of programming language.