Sponsored Link •
Anders Hejlsberg, the lead C# architect, talks with Bruce Eckel and Bill Venners about DLL hell and interface contracts, strong names, and the importance of interoperability.
Anders Hejlsberg, a distinguished engineer at Microsoft, led the team that designed the C# (pronounced C Sharp) programming language. Hejlsberg first vaulted onto the software world stage in the early eighties by creating a Pascal compiler for MS-DOS and CP/M. A very young company called Borland soon hired Hejlsberg and bought his compiler, which was thereafter marketed as Turbo Pascal. At Borland, Hejlsberg continued to develop Turbo Pascal and eventually led the team that designed Turbo Pascal's replacement: Delphi. In 1996, after 13 years with Borland, Hejlsberg joined Microsoft, where he initially worked as an architect of Visual J++ and the Windows Foundation Classes (WFC). Subsequently, Hejlsberg was chief designer of C# and a key participant in the creation of the .NET framework. Currently, Anders Hejlsberg leads the continued development of the C# programming language.
On July 30, 2003, Bruce Eckel, author of Thinking in C++ and Thinking in Java, and Bill Venners, editor-in-chief of Artima.com, met with Anders Hejlsberg in his office at Microsoft in Redmond, Washington. In this interview, which will be published in multiple installments on Artima.com and on an audio CD-ROM to be released this fall by Bruce Eckel, Anders Hejlsberg discusses many design choices of the C# language and the .NET framework.
Bill Venners: To what extent is "DLL Hell" a failure of interface contracts to work adequately in practice? If everyone fully understands and adheres to the contract of the functions of a particular DLL, shouldn't updating that DLL in theory not break any code?
Anders Hejlsberg: Hell has many tortures. One aspect of DLL hell is that you don't adhere to your promised semantic contract. You do something different than what you did before, and therefore you break code. That's actually probably not the biggest issue that we face. The true problem with DLL hell is that we don't allow you to have multiple different versions of a particular DLL present on the machine. Once you upgrade the DLL you upgrade everybody, and that's a mighty big hammer.
Bill Venners: But if the contract is followed, shouldn't the most recent version work for all users of that DLL?
Anders Hejlsberg: In theory, yes. But any change is potentially a breaking change. Even a bug fix could break code if someone has relied on the bug. By the strictest definition you realize that you can do nothing once you've shipped.
Versioning is all about relaxing the rules in the right way and introducing leeway. The absolute answer, the only way guaranteed to not break anything, is to change nothing. It is therefore important to support side-by-side execution of multiple versions of the same functionality, on the same box or even in the same process. Side-by-side execution is one option we support in .NET that we didn't support in the older DLL model.
Bill Venners: I assume you use strong names to identify the library version that you want. How do strong names work?
Anders Hejlsberg: Strong names have a logical and physical part. The logical part is composed of the namespace and class names. Actually, from the Common Language Runtime's [CLR's] perspective, namespaces don't really exist. We can pretend that namespaces exist in the programming language, but from the CLR's perspective, a class name may have dots in it. That's the logical name of the class. The physical name includes the name of the assembly that the code lives in, the version number, the locale, and the cryptographic key associated with the name.
You can refer to a particular type in a particular assembly with a particular version or with a particular strong key. You can literally have a guarantee that you will either get precisely the implementation you were compiled against or nothing. Or, you can relax parts of the strong name. You can say, "I'll take any version later than some version."
Bruce Eckel: Have you come up with any interesting thoughts about ways to enforce semantic contracts?
Anders Hejlsberg: I think the most promising ideas are existing and new developments in pre- and post-conditions, assertions, invariants, and so forth. Microsoft research has several ongoing projects that we continually evaluate . We have looked at some pretty concrete proposals. In the end we realized that—as is the case for almost any truly important feature—you can't just do contract enforcement from purely a programming language perspective. You have to push it into the infrastructure, the CLR, the Common Language Specification, and therefore all the other programming languages. What good is putting invariants on an interface, if it is optional for the implementer of the interface to include the code of the invariant? So it's really more at a type system level than at a programming language level, but that doesn't necessarily mean that we're not going to address it. We are not doing that in the next release, but it could become a first class feature in C# down the line.
Bill Venners: You have said that where Java is striving for platform independence, .NET is striving for interoperability. What do you mean by interoperability?
Anders Hejlsberg: Interoperability means several things. First, it means interoperability between various programming languages in .NET. Our design goal was that the .NET CLR would be language neutral, that it would support multiple programming languages. Java, by contrast, was one programming language and execution machinery for that one programming language. The CLR supports many features that have surfaced in only a few programming languages, for example, pointers. Unsafe code in C# and managed C++ have pointers, but Visual Basic and JScript don't. Yet all the infrastructure for pointers is in place in the CLR. Language interoperability is about the realization that as much as we try we're not going to convince everybody that you just program in one programming language. And honestly the way that the industry moves forward and innovation happens is by new programming languages being created. And we're not going to try to stop that. We're going to encourage it.
Another aspect of interoperability is interoperability with existing systems. Back when we were in the Java business, one of the things that we tried to improve upon in our Java VM was interoperability with existing code, because we just think that kind of interoperability is so key. And we still think that. In the CLR, therefore, we have focused very heavily on interoperability with DLLs,COM, OLE automation—all of these technologies that any piece of code was written in before .NET.
It goes back to what I said earlier [In Part IV] that the key today is leverage. We've got to find ways for our programmers to leverage existing systems and code. Achieving that goal means having great interoperability, because how else can you leverage? That puts us in a complete opposition to Java's "100% Pure" viewpoint of the world. And I think we're doing the right thing with it. I really do.
If you contrast what it feels like to call a DLL from C# versus to do it from Java, you'll very quickly see what I mean. It is very complicated to use JNI, and I think it is a pity that they haven't done anything better there, because so much more could be done. It doesn't make sense that the minute you have to interoperate with any other system in the world you enter this netherworld that is quite possibly more complicated than straight C or C++ programming. You have to run all these tools that spit out some header files. You have to remember to call this and that. If you want to dereference an object, you better remember to lock it down else it could, in one out of a thousand cases of running your program, move when the GC somehow happens to sweep right then. Then you can never reproduce it again. If it's OK for a system to do garbage collection and type safety and all, why shouldn't it help you interoperate? It just seems like such a reasonable thing to do.
Bill Venners: From my perspective looking in from the outside of both Microsoft and Sun, I've noticed a cultural or philosophical difference between the two companies that I think influences the design differences between Java and .NET. At Microsoft, I get the sense that the prevailing view is that software is written to program the hardware—the box, the device, and so on. I think that's a totally reasonable perspective given how Microsoft makes its money. By contrast, even though "The network is the computer" was a Sun marketing slogan, I find that attitude really does exist in Sun culture to a great extent. The network offers the services, not the box. And Java is really like an object-oriented layer sitting on top of the network stack, aimed at abstracting away the heterogeneity connected to the network.
Anders Hejlsberg: What's interesting is that any Java solution you care to point at in the real world has platform-specific stuff in it. I know of nothing that is pure Java only, that doesn't somehow rely on some other component. Any of the web stuff relies on Apache or some web server, some database, and some form of interoperability with those systems. It's just ridiculous to think that the whole world is pure Java. The whole world is about putting systems together and making them work. And that's why the whole world is so excited about things like web services, because they're a wonderful way to interoperate. And we just think interoperability comes in many forms and we should just push as hard as we can and make it better and easier for systems to interoperate.
Bill Venners: Actually, the scenario you just described is exactly what I have on the Artima.com server. I have Tomcat running JSPs, and Tomcat does talk to Apache.
Anders Hejlsberg: And you probably have a database.
Bill Venners: Yes, the Java application also talks to a database. There is platform-specific stuff in the sense that the Java API implementations use JNI, but the code of my application is all Java. And in my case even the connectors from Tomcat to Apache and the database are pure Java, because they use sockets to interoperate, not JNI.
Bruce Eckel: One of the things that I like about Python is that it says if you want to be platform independent you can, if you want to talk to the platform, you can.
Anders Hejlsberg: Yes, exactly. It should be your choice.
Come back Monday, November 10 for part III of a conversation with Java's creator James Gosling. I am now staggering the publication of several interviews at once, to give the reader variety. The next installment of this interview with Anders Hejlsberg will appear in the near future. If you'd like to receive a brief weekly email announcing new articles at Artima.com, please subscribe to the Artima Newsletter.
Deep Inside C#: An Interview with Microsoft Chief Architect Anders Hejlsberg:
A Comparative Overview of C#:
Microsoft Visual C#:
Anders Hejlsberg was not the first Artima interviewee to mention taste. Jim Waldo made almost
an identical comment about building a team of tasteful programmers in his interview:
And an entire portion of Ken Arnold's interview was devoted to design taste - Taste and Aesthetics: