Remix.run Logo
mananaysiempre 4 days ago

Cool, yes. Useful or a good idea, I dunno. Reading through the (non-reference) documentation on SOM, I’m struck by how they never could give a convincing example for the utility of metaclasses. (Saying this as someone who does love metaclasses in Python, which are of course an inferior interpretation of the same academic sources.) The SOM documentation is also surprisingly shallow given its size: with a copy of Brockschmidt, Box, the COM spec, and the Platform SDK manual, you could reimplement essentially all of COM (not ActiveX though), whereas the IBM’s documentation is more like “here’s how you use our IDL compiler and here are the functions you can call”. (This is in contrast with the Presentation Manager documentation, which is much tighter and more detailed than the one for USER/GDI ever has been.) From what I can infer of the underlying principles, I feel SOM is much more specific about its object model, which, given the goal is a cross-language ABI, is not necessarily a good thing. (I’d say that about WinRT too.)

And of course COM does do implementation inheritance: despite all the admonitions to the contrary, that’s what aggregation is! If you want a more conventional model and even some surprisingly fancy stuff like the base methods governing the derived ones and not vice versa, BETA-style, then WinRT inheritance[1] is a very thin layer on top of aggregation that accomplishes that. Now if only anybody at Microsoft bothered to document it. As in, at all.

(I don’t mean to say COM is my ideal object model/ABI. That would probably a bit closer to Objective-C: see the Maru[2]/Cola/Idst[3] object model and cobj[4,5] for the general direction.)

[1] https://www.interact-sw.co.uk/iangblog/2011/09/25/native-win...

[2] https://web.archive.org/web/20250507145031/https://piumarta....

[3] https://web.archive.org/web/20250525213528/https://www.piuma...

[4] https://dotat.at/@/2007-04-16-awash-in-a-c-of-objects.html

[5] https://dotat.at/writing/cobj.html

pjmlp 4 days ago | parent | next [-]

Because at the time it was obvious, Smalltalk was the C++ companion on OS/2, a bit like VB and .NET came to be on Windows years later.

Aggregation is not inheritance, rather a workaround, using delegation. And it has been always a bit of the pain to set up, if one wants to avoid writing all the boilerplate by hand.

As for WinRT, I used to have it in high regard, until Microsoft management managed to kill everything good that UWP was all about, and now only folks that cannot avoid it, or Microsoft employees on Windows team, care about its existence.

owlstuffing 3 days ago | parent | next [-]

> Aggregation is not inheritance, rather a workaround, using delegation

Although the designers of COM had the right idea, they implemented delegation in just about the worst way possible. Instead of implementing true delegation with multiple interface inheritance, similar to traits, they went pure braindead compositional. The result: unintuitive APIs that led to incomprehensible chains of QueryInferface calls.

pjmlp 3 days ago | parent [-]

In general the tooling sucks, which is kind of strange given how relevant COM is on Windows, even moreso since Windows Vista.

It seems the Windows team is against having something like VB 6, Delphi, C++ Builder, .NET Framework, MFC, approaches to COM tooling, just out of principle.

Thus we end up with low level clunky code, with endless calls to specific API like QueryInferface(), manually written boilderplate code, and with the IDL tools, manually merging generated code, because they were not designed to take into account existing code.

mananaysiempre 3 days ago | parent | prev [-]

> Because at the time [the utility of metaclasses] was obvious, Smalltalk was the C++ companion on OS/2 [...].

Maybe? I have to admit I know much more about Smalltalk internals than I ever did about actually architecting programs in it, so I’ll need to read up on that, I guess. If they were trying to sell their environment to the PC programmer demographic, then their marketing was definitely mistargeted, but I never considered the utility was obvious to them rather than the whole thing being an academic exercise.

> Aggregation is not inheritance, rather a workaround, using delegation. And it has been always a bit of the pain to [...] avoid writing all the boilerplate by hand.

Meh. Yes, the boilerplate is and always had been ass, and it isn’t nice that the somewhat bolted-on nature of the whole thing means most COM classes don’t actually support being aggregated. Yet, ultimately, (single) implementation inheritance amounts to two things: the derived object being able to forward messages to the base one—nothing but message passing needed for that; and the base object being able to send messages to the most derived one—and that’s what pUnkOuter is for. That’s it. SOM’s ability to allocate the whole thing in one gulp is nice, I’d certainly rather have it than not, but it’s not strictly necessary.

Related work: America (1987), “Inheritance and subtyping in a parallel object-oriented language”[1] for the original point; Fröhlich (2002), “Inheritance decomposed”[2], for a nice review; and Tcl’s Snit[3] is a nice practical case study of how much you can do with just delegation.

> As for WinRT, I used to have it in high regard, until Microsoft management managed to kill everything good that UWP was all about [...].

Can’t say I weep for UWP as such; felt like the smartphonification of the last open computing platform was coming (there’s a reason why Valve got so scared). As for WinRT, I mean, I can’t really feel affection for anything Microsoft releases, not least because Microsoft management definitely doesn’t, but that doesn’t preclude me from appreciating how WinRT expresses seemingly very orthodox (but in reality substantially more dynamic) implementation inheritance in terms of COM aggregation (see link in my previous message). It’s a very nice technical solution that explains how the possibility was there from the very start.

[1] https://link.springer.com/chapter/10.1007/3-540-47891-4_22

[2] https://web.archive.org/web/20060926182435/http://www.cs.jyu...

[3] https://wiki.tcl-lang.org/page/Snit%27s+Not+Incr+Tcl

twoodfin 3 days ago | parent [-]

If they were trying to sell their environment to the PC programmer demographic, then their marketing was definitely mistargeted, but I never considered the utility was obvious to them rather than the whole thing being an academic exercise.

IBM wasn’t selling to developers. SOM was first and foremost targeting PHB’s, who were on a mission to solve the “software crisis”. We somehow managed to easily escape that one despite no one coming up with a silver bullet solution.

mananaysiempre 3 days ago | parent [-]

I admit to having no experience with this particular model year of PHB. Were they really that prone to being dazzled with seemingly advanced shinies? All of the metaclass talk must have sounded like a stream of meaningless technobabble if you weren’t not just a practicing programmer, but also up to date on the more research-oriented side of things (Smalltalk, CLOS, et al.).

The talk was meaningful, don’t get me wrong, I just don’t see how it could sell anything to a non-technical audience.

twoodfin 3 days ago | parent [-]

What I mean is that the SOM feature checklist was downstream of trying to sell “software components” as a means of turning development shops into “software factories” to an audience of PHB’s.

CORBA had a ton of “technobabble”, too: It wasn’t there to make the standard better for developers.

pjmlp 3 days ago | parent [-]

Yeah, but since this stuff comes in cycles, now we have WebAssembly Component Model, with gRPC predating it.

And I would vouch that REST/GraphQL with SaaS products, finally managed to achieve that vision of software factories, nowadays a big part of my work is connecting SaaS products, e.g. fronted in some place, maybe with a couple of microservices, plugged with CMS, ecommerce, payment, marketing, and notifications based SaaS products.

cyberax 3 days ago | parent | prev [-]

That's because the core of COM is just a function table with fixed 3 initial entries (QueryInterface/AddRef/Release). I had a toy language that implemented COM and compiled to native code, it produced binaries that could run _both_ on Novel Netware and Windows (Netware added support for PE binaries in 98, I think).

The dark corner of COM was IDispatch.

mananaysiempre 3 days ago | parent [-]

Yeah, IUnknown is so simple there isn’t really much to implement (that’s not a complaint). I meant to reimplement enough of the runtime that it, say, can meaningfully use IMarshal, load proxy/stub DLLs, and such.

As for IDispatch, it’s indeed underdocumented—there’s some stuff in the patents that goes beyond the official docs but it’s not much—and also has pieces that were simply never used for anything, like the IID and LCID arguments to GetIDsOfNames. Thankfully, it also sucks: both from the general COM perspective (don’t take it from me, take it from Box et al. in Effective COM) and that of the problem it solves (literally the first contact with a language that wasn’t VB resulted in IDispatchEx, changing the paradigm quite substantially). So there isn’t much of an urge to do something like it for fun. Joel Spolsky’s palpable arrogance about the design[1,2] reads quite differently with that in mind.

[1] https://www.joelonsoftware.com/2000/03/19/two-stories/ (as best as I can tell, the App Architecture villains were attempting to sell him on Emacs- or Eclipse-style extensibility, and he failed to understand that)

[2] https://www.joelonsoftware.com/2006/06/16/my-first-billg-rev...