Component-based Software Development

If you read the literature for long enough, you see the same ideas come around again and again, be they good or bad. A good idea is imposing a structure of larger units, components, composed of many indiviual modules. Components are also often used as a unit of deployment, rather than one of work assignment like modules.

History

As I said, none of this is novel. Back in the 90s there were several interesting projects, even if they were of limited impact. These are in order of when I became aware of them, not chronological.

First, Taligent. I've heard it referred to as a noble failure, like the Charge of the Light Brigade. Clean C++ interfaces for all OS features, but it was built as a library for AIX, OS/2, etc. I never saw it running, apparently very few did since it didn't sell well at all, but did I leaf through the documentation.

Taligent documentation

Second, NewtonOS. Again, I never saw this running, but read some docs on it. Notably, it was a complete OS, not an OO layer on top of something else.

Finally for the history lesson, NextStep. I only got to see this after it had transformed into macOS. The FoundationKit & AppKit libraries followed the Taligent design of being a nice wrapper around BSD. But you had to write Objective-C, which was ok but worryingly non-standard.

$CURRENT_YEAR

I can see similar stacks in the two major client OSs, Windows & macOS; and the major server OS, Linux.

macOS

This is easiest to describe. Cocoa has had more than 30 years of refinement and extension. And now you can use Swift which is just as non-standard, but has better ergonomics at least than Objective-C.

Windows

This was a surprise to me, but Microsoft have a good technical solution here. Although it was originally done for Windows Phone & Windows 8 (neither of which lit the world on fire), the WinRT framework for mainstream Windows is now fairly competitive with Cocoa. Also, it's programmable from multiple languages, e.g. Rust. But a langauge I find interesting is C++20, which may approach Rust's safety with the Core Guidelines checkers that Microsoft also have invested in. It's not absolutely necessary to spend time learning a proprietary language.

C++/WinRT

The implementation is based on COM, but this is almost all hidden from you.

Linux

There are two tools in use here, similar to the in-process and out-of-process usages of COM on Windows. Within one process, the best option seems to be GObject (probably with introspection), for inter-process D-Bus.

GObject grew out of the GLib & Gnome libraries, but it's useful stand-alone. As usual, there are some limitations. The most notable is that the called code must present a C interface. It probably makes most sense to write it in C, luckily enough I have some idea how to do this with tools like cppcheck, Nana and the CII libraries.

The calling code can be anything, and the introspection feature is a good solution to supporting fairly arbitrary calling languages. It doesn't seem worthwhile to pursue the *.def files, etc. that gtkmm use for wrapping Gtk. I easily found a GObject-introspection library for Lisp, but failed for SML. This is a slightly worrying pattern.

Edit: I missed the Giraffe library which implements GObject Introspection.

GObject library for Lisp

D-Bus reminds me a lot of CORBA back in the day, but lighter-weight (what isn't?). You write server & client processes, with defined interfaces between them. This all still happens on one machine though (at least, for the common case). Interestingly, there is a GObject-introspection way to use D-Bus too.

D-Bus home page

GIO library that contains GDBus

D-Bus and GObject will run on OSs like OpenBSD and macOS no problem. However, then you can really only talk to your own code. On Linux, D-Bus is reasonably widely-used so you can access a lot of OS services over it. This is definitely a disadvantage for something like OpenBSD.

Final Thoughts

As often happens, it's annoying that there isn't a clear winner without any drawbacks. For server development though, the combination of GObject & D-Bus looks useful. You could write most code in SML or Lisp, and call GObject interfaces. GObject may be a superior interface than calling the C ABI over a FFI. If you want to use different high-level languages, just expose a D-Bus interface (using GDBus) and use a separate process for each Non-C language.

For client, unfortunately it lookes like you have to code twice. Boost, etc. are great for abstracting the traditional OS interfaces but don't do this kind of task well. And on a lighter note, there's the fact that Microsoft seems to have many split personalities. Their business ethics were terrible, but WinRT is surprisingly good (and their Singularity project was honestly revolutionary but lost to office politics).

Back to my gemlog