There are two fundamentally different ways people use COM: as in-process DLLs and as remote services (DCOM). When COM is used in-process, the objects are typically fine-grained (they expect lots of API calls, each of which returns a small amount of data). This also requires that the caller have a copy of the DLL, since it runs in the caller's process. This means that every time the DLL versions, every application that uses it needs to be redistributed (since the DLL will usually be bundled with these applications). This also means that any databases or other data stores needed by the DLL need to be available from every application the DLL is installed in (meaning all the right drivers need to be distributed as well). These requirements generate a lot of headaches.
In contrast, with Web services and DCOM, the service provider is remote from the client. This allows the service provider to encapsulate any database or other dataaccess logic without the client knowing about it. It also allows the service provider to be versioned without needing to update any of the clients.
Where Web services differentiate themselves from DCOM is in their interoperability. Web services work across operating systems and platforms (Windows, UNIX, C#, Java, etc.), across the internet (since they are accessed via regular HTTP rather than the binary DCOM protocol), and even allow for more advanced versioning than DCOM (for example, you can extend your data structures without breaking clients).
This was first published in February 2005