Correspondence is a base class library (currently in Java and C#) for historic data models.

A historic data model is one in which the objects represent atomic operations rather than entities. To record that an operation has taken place, you create an object. You can then observe the history of related objects to determine the current state.

Anatomy of a correspondence object
The base class is CorrespondenceObject. A correspondence object has fields (simple data types) and predecessors (references to other correspondence objects). These fields and predecessors are assigned at construction and never change.

I'll demonstrate with the Java version of the library. Here is a simple correspondence object representing a project in a bug tracking system:

public class Project extends CorrespondenceObject {

	private @Field UUID id;

	private Query<Issue> issue = new Query<Issue>(this)

	public Project() {
		id = UUID.randomUUID();

	public Project(Memento memento) {

	public Iterable<Issue> getIssues() {
		return issue;

And here's a bug:

public class Issue extends CorrespondenceObject {

	private PredecessorObj<Project> project;

	private @Field UUID id;

	public Issue(Project project) {
		this.project = new PredecessorObj<Project>(this, "project_issue", project); = UUID.randomUUID();

	public Issue(Memento memento) throws CorrespondenceException {
		this.project = new PredecessorObj<Project>(this, "project_issue", memento);

	public Project getProject() {
		return project.getObject();

A correspondence object has two constructors. One is used by the application to create the first instance of a new object. The other is used by the library to rehydrate an existing object from a memento.

Notice that both of these objects have id fields that are initialized to unique random numbers. This is how identity is assured in Correspondence. The identity of a correspondence object is the set of its predecessors and fields. If you try to create another object with the same predecessors and fields, you get back the same object.

These predecessors and fields cannot be changed. You cannot move an issue from one project to another. That is why you don't see project name or issue name as fields. These should be modifiable properties. We'll see how to make modifiable properties in a later post.

The list of issues for a project is dependent. It is represented by a query for all successors of the project. When a new issue is created, it will be returned from this query. You don't write code to add the issue to the list. Instead, the library updates this query when the new issue is created.

Data storage
The library takes care of persisting and caching objects and their relationships with one another. When you set up your correspondence project, you select a storage strategy. In Java, I have implemented MySQL and PostgreSQL storage strategies so far. In C#, I have ADO, DAO, and SQL Server CE. The Memento class is the intermediary that separates correspondence objects from the storage strategy and make that possible.

Although all of the storage strategies that I've implemented so far are built on relational databases, don't confuse Correspondence for an ORM. It does not map objects to a relational schema. The database does not resemble your object model in any way. It has two tables: Object and Predecessor. If you love relational data, do us both a favor and don't look in the database.

Even though it does not produce a database that you would want to use for reporting (or anything else, for that matter), the Correspondence library takes care of the persistence and caching of your objects automatically. You write an object model, and you get storage and caching for free. When you create an object, it gets stored. When you follow a reference to a predecessor, it gets cached. When you execute a query, the results are cached.

Next, we'll continue the development of the bug tracking system to demonstrate some of the common patterns that occur while using Correspondece.

Leave a Reply

You must be logged in to post a comment.