Thought Cloud TDD #8: Hey, you, get onto my cloud

This Thought Cloud application is going to be a lot of fun. It’s about to get really exciting.

What good is a collaborative mind mapper if you can’t share thoughts with other people? It’s time to bring on the collaboration tests. The ModelTest creates two communities representing two user’s machines: Mike and Russell.

[TestInitialize]
public void Initialize()
{
    var sharedCommunication = new MemoryCommunicationStrategy();
    _mikesCommunity = new Community(new MemoryStorageStrategy())
        .AddCommunicationStrategy(sharedCommunication)
        .Register<Model.CorrespondenceModel>()
        .Subscribe(() => _mikesIdentity)
        ;
    _russellsCommunity = new Community(new MemoryStorageStrategy())
        .AddCommunicationStrategy(sharedCommunication)
        .Register<Model.CorrespondenceModel>()
        .Subscribe(() => _russellsIdentity)
        ;

    _mikesIdentity = _mikesCommunity.AddFact(new Identity("mike"));
    _russellsIdentity = _russellsCommunity.AddFact(new Identity("russell"));
}

The communities are joined by a shared communication strategy. That means that facts created in one community can flow into the other. In order to trigger this flow, we have to call Synchronize.

private void Synchronize()
{
    while (_mikesCommunity.Synchronize() || _russellsCommunity.Synchronize()) ;
}

The Synchronize method continues to push facts between the two communities until neither one has facts to share. We can use this to set up tests. The first test is that if Mike shares a cloud with Russell, Russell can see the cloud.

[TestMethod]
public void MikeCanShareCloudWithRussell()
{
    Cloud cloud = _mikesIdentity.NewCloud();
    Identity russell = _mikesCommunity.AddFact(new Identity("russell"));
    russell.NewShare(cloud);

    Synchronize();

    Assert.AreEqual(1, _russellsIdentity.SharedClouds.Count());
    Assert.AreEqual("mike", _russellsIdentity.SharedClouds.Single().Creator.AnonymousId);
}

Mike adds a fact to his community with the id of “russell”. This fact matches the one in Russell’s community, so it will be treated as the same fact when the two synchronize. He then shares his cloud with Russell. After they synchronize, Russell should see the shared cloud created by Mike.

A shared fact

To make this test pass, we need to define a fact that shares a cloud with an identity.

fact Share {
key:
    Identity recipient;
    Cloud cloud;
}

Then we need to query an identity for all of the shared clouds.

fact Identity {
...

query:

    Cloud* sharedClouds {
        Share s : s.recipient = this
        Cloud c : s.cloud = c
    }
}

That query combines two sets. First, the set of all shares to this recipient. Then, the set of all clouds thus shared. Finally, we need a method in our partial class to create a new share.

public partial class Identity
{
    ...

    public void NewShare(Cloud cloud)
    {
        Community.AddFact(new Share(this, cloud));
    }
}

With these changes, the test should pass. But it doesn’t. Why not?

Publish shared facts

If you look closely at the setup of each Community, you’ll see a subscription. Here it is again:

_russellsCommunity = new Community(new MemoryStorageStrategy())
    .AddCommunicationStrategy(sharedCommunication)
    .Register<Model.CorrespondenceModel>()
    .Subscribe(() => _russellsIdentity)
    ;

That line says that Russell’s community is only interested in facts that are published to Russell’s identity. So to get the Share over to the other community, we need to publish it to the Identity.

fact Share {
key:
    publish Identity recipient;
    Cloud cloud;
}

And now the test passes.

Rule #4: A community only receives published facts to which it subscribes.

Wait a minute! The test asserts that Russell can see that the cloud was created by Mike. How can Russell see Mike’s identity if it wasn’t published?

Before a fact is sent, all of its predecessors must first be sent. That means that in order to receive a Share, Russell must first receive the Cloud that it references. Before he can receive the Cloud, he must receive the Identity of the creator.

Rule #4.1: … and all of their predecessors.

A community doesn’t receive all facts. It only receives what it subscribes to. You need to manage the publications and subscriptions. Once you do, two Communities can collaborate through a shared synchronization strategy.

Leave a Reply

You must be logged in to post a comment.