Ultimately, today's UNIX is not that far from this ideal. In Linux, you can make pretty much everything be an fd: signals can be delivered over a descriptor (signalfd(2)), filesystem change notifications can be delivered over a descriptor (inotify(7)), and so on. Everything ends up being something you can pass to select (or a variant), and so you don't really need to handle the different concepts in different ways: a modern Linux application reads from a bunch of fds and takes action based on what it receives.
Work is being done in this direction, with mount and UID namespaces. The main concern is that allowing users to make these kinds of bind mounts may confuse legacy suid apps.
Which really is the problem with modern Unixes -- legacy features that expect things done in a broken way, leading to complexity and ugliness where none should exist. The new features and simplifications continue to exist in a complex world, have arcane restrictions and interactions with the old system, and generally end up increasing the complexity, instead of making things simpler.
No, that's the problem with software designed to work in the real world. Software has to work in a legacy environment to be useful. This is why Unix gets used and Plan 9 doesn't. It's also why TCP and the Web, just to name two examples, survive.
I'll quote jwz: "Convenient though it would be if it were true, Mozilla is not big because it's full of useless crap. Mozilla is big because your needs are big. Your needs are big because the Internet is big. There are lots of small, lean web browsers out there that, incidentally, do almost nothing useful. If that's what you need, you've got options... "
Incidentally, this is node.js' model.