Just take your Unix mentality and make a few substitutions:
* gcc -> cl.exe
* ar -> lib.exe
* ld -> link.exe
* make -> nmake.exe
* libfoo.so -> foo.dll
And there you have it, the world that "didn't exist before .NET" ... This is crazy amounts of ironic because Windows had DLLs at a time when shared libraries were not so much a thing on Unix. Not to mention things like COM which are all about creating de-coupled components.
COM is/was a rats nest of confusing and frequently duplicated APIs with insanely complicated rules that by the end really only Don Box understood. CoMarshalInterThreadInterfaceInStream was one of the simpler ones, iirc. COM attempted to abstract object language, location, thread safety, types, and then the layers on top tried to add serialisation and documented embedding too, except that the separation wasn't really clean because document embedding had come first.
Even just implementing IUnknown was riddled with sharp edges and the total lack of any kind of tooling meant people frequently screwed it up:
I think the good ideas from COM are: IUnknown, consistent error handling through HRESULT, the coding style that emerges from being clear about method inputs and outputs.
Some things done not as well as these core ideas: registration done globally in the registry, anything to do with threading, serialization, IDispatch.
I think in many situations you can take lessons from the good parts and try to avoid the bad.
I don't see how pointing out common bugs helps your argument though. You can write bugs in any paradigm.
Yes you can write bugs in any paradigm, but some designs are just empirically worse than others when it comes to helping people write correct code.
IUnknown is a classic case of something that looks simple but in fact a correct implementation is not at all trivial, yet COM developers were expected to get it right by hand again and again. COM itself didn't help with it at all, so the ecosystem was very dependent on IDE generated code and (eventually) ATL and other standard libraries.
None of the things you highlight were good ideas, in my view, although probably the best you can do in C.
Er... Prior to .NET, the previous "enterprise targeted" language for Windows was Visual Basic. Visual Basic absolutely supported creating COM DLLs. On 6.0 (and perhaps earlier) there's even some nice templates for "ActiveX DLLs" (ActiveX being the Microsoft buzzword for certain COM objects at the time).
Firstly, I always remember VS having click through wizards for creating libraries. So I think you are even wrong on that.
Moreover, what a sad world for our profession when an IDE doesn't do something for you and people start to doubt it exists. Reminds me of kids on here saying a programming language without a package manager might as well not exist at all.
On Unix there is nothing to stop you from creating libfoo.so without a version number in the filename. Conventions for doing the latter part came about over time. As they did on Windows too (see msvcrtxxx.dll, where xxx is a version number). These days there is also WinSXS on Windows which I don't really expect HN users to know about and is probably not relevant to the historical context.
Microsoft did really fuck it up historically (IE overwriting shell32 comes to mind) but the mechanism didn't have problems when applied by the right hands (sometimes a first party is the wrong hands :P)
If you want to talk problems in the mechansim, ask me sometime how it's possible for a Win32 process to host multiple incompatible malloc implementations in the same address space.
"As they did on Windows too (see msvcrtxxx.dll, where xxx is a version number)."
I didn't use Windows enough to know more about it than that let you have multiple copies of the libraries. Did it let you upgrade a compatible library?
"If you want to talk problems in the mechansim, ask me sometime how it's possible for a Win32 process to host multiple incompatible malloc implementations in the same address space."
Just take your Unix mentality and make a few substitutions:
* gcc -> cl.exe
* ar -> lib.exe
* ld -> link.exe
* make -> nmake.exe
* libfoo.so -> foo.dll
And there you have it, the world that "didn't exist before .NET" ... This is crazy amounts of ironic because Windows had DLLs at a time when shared libraries were not so much a thing on Unix. Not to mention things like COM which are all about creating de-coupled components.