This is a wordy response to Chris Turner’s Life Without Objects.
Many object models compose poorly. There are no generic methods to combine two objects into a meaningful third. Rather than composition, we get a Cartesian product of specializations (e.g. BufferedInputStream, ByteArrayOutputStream). Functional programming, by comparison, focuses very heavily on composition. We model programs with composable abstractions – lenses, functors, categories, arrows, stream processors, iteratees, pipes, monad transformers.
Functional programmers often reason in terms of compositional properties – i.e. properties that are inductive across all relevant composition operators (e.g. “if A doesn’t deadlock, and B doesn’t deadlock, then A*B doesn’t deadlock”). Purity includes a nice set of compositional properties, and is most publicly associated with functional programming. But there is much interesting ground between `pure functions` and `imperative IO`. Functional programmers often seek and learn new compositional abstractions to achieve desired compositional properties and expressiveness.
It’s often difficult to achieve both expressiveness and rich composition, but invention is the art of avoiding tradeoffs!
While the functional programming community typically achieves composition by providing uniformly-structured entries and exits for every action, this isn’t strictly necessary.
The OO community pursues another viable path to expressive composition: mixins, dependency injection, and auto-wiring mechanisms in general. Ambient oriented and concept oriented programming both provide alternative approaches to resource discovery and wiring objects together. Sean McDirmid has pursued a few interesting possibilities for composition of first class objects. I’ve also been idly pursuing such mechanisms, though without the OO angle – e.g. constraint-based linkers and configuration and dependency injection for functional values.
I’d love to see mixins taken further than Scala takes them – i.e. objects as first class adjectives and adverbs, composition by juxtaposition (so we can say `green triangle`) with good defaults, typing in terms of grammatical subclasses (so we can reject constructs like `colorless green ideas sleeping furiously`). Today objects are mostly nouns (data, passive elements) and verbs (runnables, actors, agents). I think we could take auto-wiring a lot further than we do. Some ideas from Inform 7‘s object model might be applicable.
With respect to compositional properties, one excellent result from the OO community has been the object capability model, which essentially is fine-grained object-based modularity taken to its logical extreme. Ocaps are a very promising basis for secure composition and secure interaction design in open systems. Object capability model includes a valuable set of compositional properties for reasoning about effects, authority, and both hard and soft security (where “soft” security means limiting the damage caused by buggy or malicious code, enabling auditing and revocation if abuse is detected).
Fortunately, capability security is not in conflict with mixins or dependency injection. It only takes a little extra explicit modeling and formalization to avoid ambient authority, e.g. in terms of a powerbox or factory.
As OO’s composition languages become more expressive and accessible, and its compositional properties more powerful, life with objects becomes more tolerable.
(OTOH, it seems less recognizable as “OO” if you compare to prototypical examples like Java. But it’s the programming experience that matters, not fuzzy and amorphous definition of OO!)
Objects, but Stateless…
I think that even if objects prosper in some form or another, they will gradually move to be ever less stateful, and eventually `stateless objects` will be the agreed upon best practice for OO.
Mutable state will be pushed to the very edges of the model and even over the edge – into `external` database abstractions and content-centric networks. Doing so affords us many benefits – orthogonal persistence, orthogonal replication and disruption tolerance (of both the program and the data), orthogonal rewind and replay and support for backtracking debuggers (assuming we favor temporal data), runtime upgrade and live programming, reactive programming, easier administration, reduced bottlenecks and improved scalability (since we aren’t serializing messages at objects).
I’m sure people will try clever, `safe` uses of state – e.g. futures, promises, single-assignment, transactions – but they’ll discover various issues even with those, that it is better to model even promises in external state outside of any object.
We’ll have stateless, reactive objects influencing and observing a stateful grid. They won’t be pure objects, but there won’t be any local state. And good riddance.
Without internal state, object identity becomes irrelevant. Stateless objects may still be unforgeable or opaque closures that encapsulate capabilities, but it is easy to represent unforgeable (and deterministic, reproducible) identifiers for pure objects – via encryption, HMAC, secure hashes, etc.. IIRC, Waterken uses such techniques.
I think we’ll also drift a bit closer to `pure` at the services scale by shifting the data management responsibility.
Ultimately, the favored discipline will be for clients of an object or service to provide references to their own external state services, i.e. client-side state where “client side” might actually refer to some logical amalgamation of client-owned space in a cloud and the local device. There are a lot of reasons for this – it makes third party services cheaper to provide, easier to administer, and more extensible and composable (annotations on state, mashable services); it decouples the client from the service, reduces lock-in, allows clients to change component services without disrupting their state (though there may be a conversion effort), reduces legal and security concerns for hosting, etc.. We can see some beginnings of this movement @unhosted.
Services will still keep their own databases for any cross-cutting state to improve service for all clients. But they’ll mainly compete by providing unique capabilities, difficult functions, and rich features.
My Future with Objects
It would take a broad, fuzzy definition of OO to call RDP an OO paradigm. But RDP does support object capability model patterns. And I do pursue some of the auto-wiring mechanisms suitable for object composition (in addition to rich, arrow-based functional composition). RDP realizes most of my vision of what OO programming will eventually become – a clean, declarative, open, composable, internally stateless fusion of object capabilities and reactive programming. RDP’s continuous time semantics require some interesting models for external state, but state is still an essential part of many applications and the RDP experience.
My RDP is embed with objects. ^_^