Let other users know how useful this tip is by rating it below. Got a tip or code of your own you'd like to share? Submit it here!
All good programmers aspire for as much code reuse as possible simply because it allows you to make very robust and scalable applications very quickly.
There are two types of code reuse:
- White box: This refers to pasting existing pieces of code into a monolithic executable.
- 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 also provides developers with ways and means to create and deploy components. Since this approach closely resembles COM, it's not difficult for developers to get confused between the two distinctly separate approaches to component-based development. So, let's take a look at 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, which 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 waste 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 -- client applications written in the same programming languages as the function libraries could not 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. So the programmer does not have worry about creating a single executable, since the component is identified by means of GUID (Global Unique Identifier), a 128-bit number that is stored in the system registry, along with other relevant information, to uniquely identify the component.
Client applications dynamically create an instance of the component at runtime to use the business logic in the component, so only one copy of the function library is required.
The disadvantage is that the developers have to contend with what is commonly referred as "DLL hell." This problem arises when a particular DLL is replaced by a newer version. The developer has to remove all references to the component by shutting down all the client applications, and if that doesn't work, close down the WWW service. Sometimes even that doesn't work, and the server has to be restarted before the programmer can actually replace the DLL.
In order for an enterprise application to be able to use COM, it has 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 don'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 components.
DCOM is an RPC (Remote Procedure Call) protocol used for communication between distributed components. Here the client makes requests to a proxy class on the local machine, which then delegates the call invisibly to a remote stub class installed on a remote machine. The results follow the reverse path from the stub class to the proxy class to the client. The client is completely ignorant of the location of the component that achieves location transparency. The disadvantage of DCOM is that it is a protocol that uses a different hardware port than the default HTTP port 80. So a different port has to be kept open at all times in order for the components to communicate, which is a major security hazard. So DCOM cannot work easily across firewalls.
In order to use MTS, programmers place special MTS hooks in their components, compile them and place them in MTS packages. Keeping related components in a single package has its own advantages. Whenever the client requests an instance of a component in a package, MTS ensures that a new dedicated process is created for that package, a new instance of the component is created in that process -- and applied transactional services, object pooling services and security are applied according to the requests of the component developer.
MTS allows related units of work to be treated as transactions, which means that if all units of the work completed successfully, then the entire transaction is treated as successfully completed. Whereas, if any one of the units failed, the entire transaction is rolled back.
MTS conserves memory resources by retaining the objects in memory even after the clients that originally requested them releases them. So when another client requests the same component, MTS hands the retained object to the new client. In this way, MTS eliminates the overhead on the server resources needed to instantiate a new object.
MTS allows developers to equip their components with security measures for authenticating the client that requests its services. It ensures that no unauthorized clients can take undue advantage of the component.
MTS is 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, is also integrated with Windows 2000 under COM+. MSMQ allows for asynchronous communication between clients and servers, which absorbs the impact of server inaccessibility. Event Service was added so that server classes can asynchronously communicate event occurences to multiple clients. The Load Balancing Service automatically instantiates requested objects on the machine that has the most available resources in the server farm.
.NET provides a completely new approach to creating and deploying components, which are also known as assemblies. With COM, the developer has to register the component on the server -- i.e, its information had to be updated in the system registry. The purpose is 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 meta data 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 .NET. Also, since the .NET runtime maintains garbage collection externally, the component does not have to worry about keeping its reference count, as is 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 can be useful if you want to migrate your current application to .NET by 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. That could be one more reason why developers might 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.