Once you've written some very basic boostrap tools, the "second generation" of stuff that adds convenience and flexibility are a lot simpler.
A trivial example: 20 seconds after you wrote "directory listing", someone will say "I want a directory listing, but sorted by date, and it would be awesome if it didn't immediately scroll past the end of my screen."
With Unix Philosophy tools, you might already have have a "sort" and "paginate" command, so it's just piping stuff together. They can do it themselves, or it will take 20 seconds to explain.
Without it, you're going to have to add additional options to "directory listing" (or parallel commands) to handle the sorting and pagination features. The tools get bigger and buggier for the same functionality.
Early Unix machines weren't much bigger than mid-80s PCs-- 512K of memory or less-- but offered a very rich command line experience compared with DOS machines of similar sizes.
Programs like database or CAD packages probably go monolithic because they're more "state dependent" than your usual command-line tools. "sort" and "more" can take their inputs from stdin and feed them out to stdout, and when they're done, forget everything with no damage.
That wouldn't work well for other packages. You could probably make a database or CAD system that worked as composable units, like `echo db.sql | db-query "select username from accounts where credit < 0" | xargs delete-account` or `echo image.dxf | add-circle -x 200 -y 400 -r 60 > image.dxf` But you'd spend a lot of time reloading and reparsing the same files. A persistent monolith that keeps the data file open and in whatever internal representation is most efficient is going to perform better.
Some use cases also have limited composability, because the user can only plan a few moves ahead. Tools that encourage interactive/experimental usage, like drafting software, might involve the user stopping every step or two to make sure they're staying on plan, and queuing up a series of commands could wreak havoc. Some of these packages ended up simulating composable tools through internal macro/scripting languages which still avoided the penalty of having to rely on the OS to orchestrate every single action.
Sorting the output of textual tools like ls requires parsing which can be non-trivial. It's easier to do it by using a modern structural shell such as nushell.
(Offhand, I've never touched Plan 9 but...) Hypothetically /proc/SOMEPID/db/DATABASE/SCHEMA/TABLE/various views which provide expressions in some order. Or /proc/SOMEPID/containerofthings/ and the directory listing is serviced by the application, as an enumeration of keys (filenames) to values (datasets). For a database the API would behave similarly to how ORMs operate since filesystems are inherently similar to objects.
It kind of feels a bit of cargo cult, praising it all the time.
COM is everywhere on Windows, specially since Vista, as the WinDev regained the control they thought Longhorn was going to take away from them.
One of Powershell strengths is the easy access to COM, just like .NET, frameworks.
Linux could do the same with D-Bus, but alas so is the distributions wars, and hate on anything like proprietary OSes, that it only has a minor role on systemd, GNOME and KDE.
Imagine writing a huge complex program that is dependent of communication between smaller existing programs. Either you use the default programs that where shipped with all the different versions of OS'es with different distro's (never going to work, too many different versions of programs and their communication interfaces) or you ship certain fixed versions of all of the small programs that form your bigger program.
In case of the latter: why not just use libraries? It's basically the same thing with an easier API?
Maybe I'm missing something...
Except at the end of the day, the interface can be as simple as a stream of bytes over a socket. If I want a h264 decoder in my application I could just pipe a stream to a specific program made to decode it. That could be written in Python, in Rust, in C, in Go, etc. whereas dynamic libraries don't give you that freedom as you have to abide by the ABI defined by the host application.
I’d guess the trick is that you’re not thinking small enough. GNU coreutils, etc. are not minimal by any means, but compared with even late-90s graphical desktop software they are still fairly compact, and you’re rarely using each and every tool at once. And the smaller the tool and the problem it targets, the more likely it is that the problem is mostly a solved one, so interface churn is less necessary.
I’m not sure every problem area is amenable to this—GUIs and things best expressed as GUIs seem particularly stubborn. (It would be sad if OLE/ActiveX was the best possible solution.) But some are, and few enough people are trying to expand the simplicity frontier for their real-world tasks in recent years that I don’t believe the state of the art of the 1980s is the farthest it can reach, either.
Also there's the old viewpoint of "let's put everything in XML. Everything can read and write XML", and that seems similar to the argument of "everything can be an object that is exposed to other programs". The problem in both cases, objects have requirements for function call names, function arguments, nuanced conventions, as XML has specific tree structures. Interfacing programs must be wise to these conventions and sometimes nuances so it doesn't "just work". Windows is like - programs CAN share objects and interface BUT it needs developer work for program A to work with program B. Unix is like "programs X and Y, whatever they are, work together with no additional work". The magic of unix is that if there are 1000 programs, now there are 1,000,000 combinations that "just work" vs. 1,000,000 developer hours
Unix on the other hand recognizes that it's a lot easier to just say "everything is a text stream, and all programs are responsible for inputting and outputting only fairly clean text streams without extraneous output" . This is extended to "everything is a file", a file also typically made to be read into a clean text stream so it can feed into that whole ecosystem.
Composable software is something I’m highly interested in. There were efforts in the 1990s to make desktop software more composable, such as COM from Windows and OpenDoc from Apple, but the desktop world is still dominated by large applications such as those that constitute Microsoft Office and the Adobe Creative Suite. It would have been a wonderful opportunity for the Linux desktop world to embrace components, but, alas, the community embraced OpenOffice, GIMP, and other large applications.