Secondly, the entire architecture has been created to make
it as easy to develop Internet applications as it is to develop for the desktop
environment.
.NET actually "wraps" the operating system, insulating software developed with
.NET from most operating system specifics such as file handling and memory allocation.
This prepares for a possible future in which the software developed for .NET
is portable to a wide variety of hardware and operating system foundations. (Beta
one of Visual Studio.NET supports all versions of Windows 2000 plus Windows NT4,
Windows 9x, and Windows Millennium Edition.)
A Common Substrate for all Development
The major components of the .NET framework are shown in the following diagram:
The framework starts all the way down at the memory management
and component loading level, and goes all the way up to multiple ways of rendering
user and program interfaces. In between, there are layers that provide just about
any system-level capability that a developer would need.
At the base is the Common Language Runtime, often abbreviated to CLR. This is
the heart of the .NET framework, the engine that drives key functionality. It
includes, for example, a common system of data types. These common types, plus
a standard interface convention, make cross-language inheritance possible. In
addition to allocation and management of memory, the CLR also does reference
counting for objects, and handles garbage collection.
The middle layer includes the next generation of standard system services such
as ADO.NET and XML. These services are brought under the control of the framework,
making them universally available and standardizing their usage across languages.
The top layer includes user and program interfaces. Windows Forms (often
informally referred to as WinForms) are a new way to create standard Win32 desktop
applications, based on the Windows Foundation Classes (WFC) produced for J++.
Web Forms provide a powerful, forms-based UI for the web. Web Services,
which are perhaps the most revolutionary, provide a mechanism for programs to
communicate over the Internet using SOAP. Web Services provide an analog of COM
and DCOM for object brokering and interfacing, but based on Internet technologies
so that allowance is made for integration even with non-Microsoft platforms.
Web Forms and Web Services, comprise the Internet interface portion of .NET,
and are implemented through a section of the .NET Framework referred to as ASP.NET.
All of these are available to any language that is based on the .NET platform.
For completeness, there is also a console interface that allows creation of character-based
applications (not shown in the diagram).
The Common Language Runtime
Let's start with a definition. A runtime is an environment in which programs
are executed. The Common Language Runtime is therefore the environment in which
we run our .NET applications that have been compiled to a common language, namely
Microsoft Intermediate Language (MSIL), often referred to simply as IL.
Runtimes have been around even longer than DOS, but the Common Language Runtime
(CLR) is as advanced over traditional runtimes as a light bulb is over a candle.
Here's a quick diagrammatic summary of the major pieces of the CLR:
That small part in the middle, called Execution Support, contains
most of the capabilities normally associated with a language runtime (such as
the VBRUNxxx.DLL runtime used with Visual Basic). The rest is new, at least for
Microsoft platforms.
Chapter 2 of this book will go into the Common Language Runtime in depth. However,
since understanding the CLR is key to understanding the rest of .NET, here is
a short introduction.
Key Design Goals
The design of the CLR is based on the following goals:
- Simpler, faster development
- Automatic handling of "plumbing" such as memory management and process communication
- Good tool support
- Scalability
Let's look at each of these in detail.
Simpler, Faster Development
A broad, consistent framework allows developers to write less, and reuse more.
Less code is possible because the system provides a rich set of underlying functionality.
Programs in .NET access this functionality in a standard, consistent way, requiring
less "hardwiring" and customization logic to interface with these functions than
is typically needed today.
Getting Rid of Plumbing
A lot of programming infrastructure is either handled automatically by the CLR
or rendered completely unnecessary. That is, some of it is hidden, and some of
it is just not there any more.
Memory management is an example of hidden infrastructure. Visual Basic developers
stopped worrying too much about memory long ago. Today, C++ developers still
have to, but not with the CLR, which has memory management functions built-in
(though C++ developers have the option to do it themselves, and such unmanaged
code is in fact the default for C++). If a C++ developer chooses to take full
advantage of the CLR, it becomes unnecessary to use CoCreateInstance, for example,
to instantiate a class, or malloc to set aside space for an array. A simple declaration
statement will do it, and the CLR allocates the memory as necessary. Then it
goes on to handle reference counting on instantiations and automatically do garbage
collection when the reference count gets to zero.
Another example is proxies and stubs, which map interfaces on a remote object
to the local system. The proxy handles communication with the remote object,
and stands in its place locally, so that local processes can treat the remote
object as if it were local, and the details of remote management are all handled
behind the scenes. Contrast this with the work that is currently necessary to
make DCOM work.
A lot of the missing plumbing is replaced by metadata - standardized information
about components, interfaces, and processes that can be accessed in a consistent
way. No more cycling through IUnknown to find out how to work with an interface
- the CLR provides more flexible and much easier to use equivalents. A later
section of this chapter covers metadata in more detail.
Tool Support
Though much of what the CLR does is similar to operating system functionality,
it is designed first and foremost to support development languages. It furnishes
a rich set of object models that are useful to tools like designers, wizards,
debuggers, and profilers. And since the object models are at the runtime level,
such tools can be designed to work across all languages that use the CLR. It
is anticipated that third parties will produce a host of such tools.
It's also important to note that Microsoft is not restricting use of the CLR
to Microsoft languages. Third party language vendors are encouraged to re-architect
their languages to use the CLR, which offers a host of benefits. Besides taking
advantage of all the CLR functionality (and thereby not having to write it or
support it), using the CLR enables never before seen levels of cross-language
integration. We'll discuss more of that later in the section on Multiple Language
Support.
This capability of the CLR to work transparently with multiple languages has
some huge benefits for developers. Debuggers offer the best example. The CLR
makes it possible to write a source-level debugger that treats all languages
equally, jumping from one language to another as necessary.
Simpler, Safer Deployment
It's hard for an experienced Windows component developer to see how anything
can work without registration, GUIDs, and the like, but the CLR does. Applications
produced in the .NET framework can be designed to install with a simple XCOPY.
That's right - just copy the files onto the disk and run the application. We
haven't seen this since the days of DOS (and some of us really miss it). This
can work because compilers in the .NET framework embed identifiers (in the form
of metadata, discussed below) into compiled modules, and the CLR manages those
identifiers automatically. The identifiers provide all the information needed
to load and run modules, and to locate related modules.
As a great by-product, the CLR can manage multiple versions of the same component
(even a shared component), and have them run side-by-side. The identifiers tell
the CLR which version is needed for a particular compiled module because such
information is captured at compile time. The runtime policy can be set in a module
to use the exact version of a component that was available at compile time, to
use the latest compatible version, or to specify an exact version. The bottom
line is that .NET is intended to eradicate "DLL Hell" once and for all.
This has implications that might not be apparent at first; for example, if a
program needs to run directly from a CD (without first running an installation
program). This was not feasible in Visual Basic after version 3, but the capability
will reappear with Visual Basic.NET.
Another significant deployment benefit in .NET is that applications only need
to install their own core logic. An application produced in .NET will not need
to install a runtime, for example, or modules for ADO or XML. Such base functionality
will be part of the .NET Framework, which will be installed separately and only
once for each system. Those four-diskette installs for a VB "Hello, world" program
will be a thing of the past!
Making all of this work automatically requires a sophisticated security infrastructure.
The .NET Framework captures the origin of a piece of code, and the publisher
of a module can be identified with a public encryption key. This allows a system
to be set up so that it doesn't run untrusted software, which provides mechanisms
to block viruses like the infamous ILOVEYOU. A method of a component, no matter
how deep it is in the object model, can demand proof of authorization to run
all the way back along the call chain that got to it.
Scalability
Since most of the system-level execution functions are concentrated in the CLR,
they can be optimized and architected to allow a wide range of scalability for
applications produced in the .NET Framework. As with most of the other advantages
of the CLR, this one comes to all applications with little or no effort.
Memory and process management is one area where scalability can be built in.
The memory management in the CLR is self-configuring and tunes itself automatically.
Garbage Collection (reclaiming memory that is no longer being actively used)
is highly optimized, and the CLR supports many of the component management capabilities
of MTS/COM+ (such as object pooling). The result is that components can run faster,
and thus support more users.
This has some interesting side effects. For example, the performance and scalability
differences among languages become smaller. All languages compile to a standard
byte code (IL - the Microsoft Intermediate Language), and there is discussion
below on how the CLR executes IL. With all languages compiling down to similar
byte code, it becomes unnecessary in most cases to look to other languages when
performance is an issue. The difference in performance among .NET languages is
minor - Visual Basic, for example, gives about the same performance as any of
the other .NET languages.
There are early-stage plans for the CLR to be available on a wide range of devices.
Eventually the vision is for .NET to be running at all levels, from smart palm-tops
all the way up to web farms. That means the same development tools should work
across the entire range - news that will be appreciated by those who have tried
to use Windows CE development kits. Of course, this is an ambitious plan and
may be subject to changes and retractions.
Comments