Envelope Paradigm

The EnvelopeParadigm for assignment was first coined by JimCoplien alternatively as the EnvelopeLetter in AdvancedCeePlusPlusProgrammingStylesAndIdioms. This is not really a paradigm, as the title of this page suggest, but a DesignPattern or ProgrammingIdiom. Specifically, this idiom is found in both the AdapterPattern and BridgePattern. Both are StructuralPatterns catalogued by the GangOfFour in their DesignPatternsBook.

It refers to treating an object reference as an "envelope", that contains a "value", so that the envelope can stay fixed while it's value changes.

This is lovely, effective, and powerful in an appropriate context.

However, it creates a concurrency problem: How do I know that the envelope has the right letter?

Another approach is to say that each object reference has its own identity, and that assignment accomplishes its change by changing the identity of the LHS. Presumably, somewhere in the computation, an envelope maintains the "current" identities of the objects in use.

A consequence of the EnvelopeParadigm is that the environment must jump through hoops to assure that each envelope has the appropriate letter. In a distributed environment, this assurance can be quite expensive.


c.f. ValueModel

No, ValueModel is more elaborate and visible than I mean -- unless I misunderstand your comment. I mean that referencing a particular (and immutable) version of anObject, by name, is different than referencing the same object with different values. It is the difference between changing the CDR of a LISP cell and replacing that cell with a different one containing the new CDR. --TomStambaugh


Let me see if I understand.. Are you saying that typically we copy objects or refer to them from more than one place, but what you'd like to see is a mechanism that allows an object to "move" from one place to another. -- MichaelFeathers (or am I missing it?)


I'm suggesting a mechanism in which every object can be "hardened", just as an "edition" in Envy/Developer is versioned. Further, that only "hardened" objects can be visible from outside a thread or process. Once hardened, an object is guaranteed to be immutable from that moment onward. If a new value is required, it is a different object (in Envy terms, it might be a different version of the same object, but each version has an infinite lifetime).

Now, objects don't need to be "moved"...they can instead be replicated, as in Lotus notes. When someone needs a new value of an object, they can soften it, then make a new value, then harden it again. "Softening" an object is very much like binding a variable within an environment in Lisp, and I envision it having similar semantics.

The object of all this is that, in a distributed environment, objects can be freely replicated, so that they might leave behind copies as the first request of an object makes its way from one place to another. Subsequent references to that object go faster, because now a local copy exists.

Finally, the repositories that hold these objects will probably timestamp them, and objects that aren't touched in awhile move to tertiary storage.

In such an environment, object access begins to have a similar flavor to internet routing. No one "object server" acts as a bottleneck; instead, objects would tend to spawn copies in local "hot spots", as they were referenced, and then disappear as the focus of computation moved elsewhere.

In some sense, this is like the difference between a semi-space and a mark/sweep garbage collector -- a semi-space collector doesn't ever try to touch every object, and it doesn't do anything to dead objects...instead, it copies the live objects and leaves the dead ones behind. My suggestion here is to do something vaguely similar with persistent objects.

By the way, these are old ideas, they have been applied in EnvyDeveloper, LotusNotes, and are very similar to the ideas discussed by the Kala folks.

--TomStambaugh

It sounds like you're applying FunctionalProgramming to databases. Yep, ImmutableObjects can simplify things, especially in distributed programming. But such a database sounds like a SourceControlSystem? with uncontrolled branching. There needs to be a merge sometime, and the longer you put it off the more painful it will be.

--BrianSlesinsky

Yes, "applying FunctionalProgramming to databases" is about right. I believe you are mistaken about "uncontrolled branching", however, at least in the sense that you mean it. A branch occurs when some consumer needs it. This consumer is itself a branch. Ultimately, these branches root in a small and finite set of enumerable elements that I'll call a RootSet?. Further, a set of semantics can be defined that sets limits on the visibility of branches. The result is something that behaves very much like EnvyDeveloper or Kala (another similar effort from a few years back).

The concept of "merge" is, I think, an implication of the EnvelopeParadigm that is mooted in such a system. A merge is only required when an envelope requires a single letter.

The primary requirement driving a set of "merge" operations is the need to limit the storage space of the repository. In a WriteOnceStore?, this requirement is accomplished by "Cloning" the repository to a new one (starting from the RootSet?). Elements that reference other elements might maintain a rule about how many prior versions of their referenced elements they keep with them; this replaces the "merge" operation. The old repository is moved to tertiary storage; the clone becomes the repository, and system operation continues.

Thus, the "hard" elements of the merge operation are implied in the branching structure itself, thus minimizing or eliminating the painful process of an explicit merge. Those of us who work in both ClearCase and EnvyDeveloper have first-hand experience with the distinction. EnvyDeveloper requires the thinking part of the merge operation to be done at the time the new edition is created. ClearCase creates the "merge problem" by deferring it until "check in" time.

-- TomStambaugh

I'm not familiar with Envy and I'm not sure what you mean. However, I think there's more going on than saving disk space.

Maybe I can put it a different way: it seems like the tip of a source control tree is an envelope - you can make versions immutable but you can't get rid of the "latest version" envelope.

As another example, take a news site. You can make individual articles immutable and give them each their own URL which never changes. Instead of editing articles, you just post a new version. However, the front page of the site cannot be immutable because it has to point to the latest versions of everything, and "what's new" is always changing.

-- BrianSlesinsky

Yes, this is true. I believe that Kala called such a thing a "basket". The interesting wrinkle is to maintain a metaphor that these mutable entities are transient, rather than persistent items. Even in your examples, the envelope is something very constrained...an identifier of the source being controlled, the URL of the news site. The contents of this handle or basket are, however, immutable entites.

The news site is an interesting example. Even though the individual elements are changing, they change together. A particular article often appears in multiple groups. It would be an error for a group to show the article in the header before the article is available, and it would an error to show the article in one header and not the ten others that also contain it.

Thus, one very quickly gets led into an increasingly complex transaction management system, where no article or header is updated until all are. The changes are atomicized, and ultimately the state of the front page reflects a stream of such atomic changes. Yet this is precisely what would result from a write-once store, where the front page is a vector of immutable versions. The URL of the front page is soft, but the front page itself is not.

And yes, there is much more going on here than saving disk space. Much more.

-- TomStambaugh

An important part of OOP is that objects have identity, which doesn't change, and state, which does. I think that is what you mean by the EnvelopeParadigm. It is possible to have something that is like an object in every way except that its state doesn't change and identity isn't important. That is what many people mean by a ValueObject. Both ways of modeling things are important. Making your objects immutable is great if it works, but it doesn't work for lots of things. Suppose you are building a real-time system like an air traffic control system. The whole point is that objects are changing their state and you have to react to them.

I think that EnvelopeParadigm is a poor name for this. The EnvelopeLetter pattern is an example of this idea, but it is much more specialized. This is really just ObjectIdentity.

-RalphJohnson


EditText of this page (last edited February 16, 2008) or FindPage with title or text search