All good programmers aspire for as much code reuse as possible simply because it allows you to make
very robust and scalable applications quite easily.
There are two types of code reuse
1. White Box : This refers to pasting existing pieces of code into a monolithic executable.
2.Black Box : This involves linking together of segments of compiled machine code.
Hence, compiled black box class libraries from which the client application can create objects are called Components.
. NET, too provides the developers with ways and means to create and deploy components. Since this approach closely resembles COM, it would not be difficult for developers to get confused between the two distinctly separate approaches to component based development, so, let's take a look at these different approaches in order to eliminate the confusion.
The Birth of COM
In the early
days of programming, programmers kept their function libraries in separate files
called Object files,
contained the compiled version of the code. If and when the programmer needed to
use a particular object file, he compiled the client application to machine code
and then relied on dynamic linking to join the client application to the object
file to make a single executable. The only advantage being the time saved to
compile the function libraries. There were disadvantages like wastage of storage
space because each executable had a copy of the function library embedded in it.
Maintenance of these applications was difficult. If a bug was discovered in the
function library, the entire executable was to be recompiled and redistributed.
There was one more serious limitation i.e. client applications written in the same programming languages as the function libraries could be used together. For example, a client written in QuickBasic could not reference a library written in C++.
Hence Microsoft came out with COM, which was nothing but a specification. Components built in any language according to this specification can be used with a client in any other language. Again the programmer did not have worry about creating a single executable since the component was identified by means of GUID (Global Unique Identifier), a 128-bit number, which was stored in the system registry along with other relevant information to uniquely identify the component. Client applications dynamically created an instance of the component at runtime to use the business logic in the component; hence only one copy of the function library was required. The disadvantage was that the developers had to contend with, what was commonly referred to as "DLL HELL". The problem arose when a particular DLL was to be replaced by a newer version. The developer had to remove all references to the component by shutting down all the client applications and if that didn't work, close down the WWW service. Sometimes even that didn't work, and the server was to be restarted before he could actually replace the DLL.
In order for enterprise applications to be able to use COM, it had to have certain capabilities like:
- Object Pooling
- Transaction Management
Support Distributed Architecture.
Microsoft came out
with DCOM(Distributed COM)
and MTS(Microsoft Transaction Server)
so that the developers didn't have to add these capabilities to
their components. Using the above two technologies , they can concentrate on
writing the business logic instead of the background plumbing for their
DCOM is an
RPC(Remote Procedure Call)
protocol used for communication between distributed components. Here the client
made requests to a "proxy" class
on the local machine which then delegated the call invisibly to a remote
"stub" class installed on a
remote machine and the results followed the reverse path from the stub class to
the proxy class to the client. Hence the client was completely ignorant of the
location of the component, which achieved
Location Transparency. The
disadvantage of DCOM was that it was a protocol which used a different hardware
port other than the default HTTP port 80, hence a different port was to be kept
open at all times in order for the components to communicate which was a major
security hazard. Hence DCOM could not work easily across firewalls.
In order to use MTS,
programmers placed special MTS hooks in their components, compiled them and
placed them in MTS packages. Keeping related components in a single package had
it's own advantages. Whenever the client requested an instance of a component in
a package, MTS ensured that a new dedicated process was created for that
package, a new instance of the component was created in that process and applied
transactional services, object pooling services and security was applied
according to the requests of the component developer.
MTS allowed related units of works to be treated as transactions which meant that if all units of the work completed successfully, then the entire transaction was treated as successfully completed, whereas if any one of the units failed, then the entire transaction was rolled back.
MTS conserved memory resources by retaining the objects in memory even after the clients who originally requested them released them , so when another client requested for the same component , MTS would hand the retained object to the new client. In this way, MTS eliminated the overhead on the server resources needed to instantiate a new object.
MTS allowed developers to equip their components with security measures for authenticating the client which requested it's services. Hence it ensured that no unauthorized client could take undue advantage of the component.
MTS was integrated with Microsoft's Windows 2000 OS under the new name COM+. But COM+ isn't just MTS, it also includes a host of other services. MSMQ (Microsoft Message Queue Server), which was released around the same time as MTS, was also integrated with Windows 2000 under COM+. MSMQ allows for asynchronous communication between clients and servers, which absorbed the impact of server inaccessibility. Event Service was added so that server classes could asynchronously communicate event occurrences to multiple clients. The Load Balancing Service automatically instantiated requested objects on the machine which had the most available resources in the server farm.
. NET provides a completely new approach to creating and deploying components. They are also known as Assemblies. With COM, the developer had to register the component on the server, i.e. it's information had to be updated in the system registry. The purpose was to keep the information of the components in a central location so that COM+ can find the appropriate component. With .NET assemblies, the assembly file encapsulates all the metadata required in special sections called Manifests. In .NET, for an assembly to be available to the client, it only has to be in the same directory as the client application. When the client application requests for an instance of a particular component, the .NET runtime searches the same directory for the assembly and then interrogates the assembly's manifest to know the various classes that the component provides. Since the information about the component is kept in manifests, the developer doesn't have to register the component on the server and several versions of the same component can safely co-exist together on the same machine.
Creating a .NET assembly is a lot like creating a VB6 component, the developer only has to worry about the business logic, all the background plumbing code is generated by the .NET, also since the .NET runtime maintains garbage collection externally, the component does not have to worry about keeping it's reference count as was done in COM with the help of the IUnknown Interface. In short, creating a .NET assembly is easier than creating a VB6 COM.
Pure .NET assemblies can't be registered under COM+ services since they comply with a different standard than the original COM's binary one. In the face of .NET, there have been references to COM as "Classic COM" which could mean that .NET assemblies are the way forward. But the dependability of current applications on COM+ suggests that COM could be around for quite a while. That could be one of the reasons why Microsoft provides developers with tools to use .NET assemblies and COM together.
The Type Library Importer (TLBIMP.exe) utility creates .NET wrappers for the COM components so the old legacy code can be used with .NET applications.
The Type Library Exporter (TLBEXP.exe) utility creates COM wrappers for .NET components which could be useful if you want to migrate your current application to .NET taking the piecemeal approach i.e. gradually replacing the COM components with their equivalent .NET assemblies. The services provided by COM+ can't be ignored in an enterprise application, hence that could be one more reason why developers might be end up making COM wrappers for .NET assemblies. Alternatively, developers can access much of the functionality from the classes in the .NET base class library.