You may have noticed that you can't delete a fact. Once the user logs on, how are they to log off? After you start a game, how are you to finish it?

A negative fact undoes the effect of a predecessor within a given query. If you query for users logged on to a machine, a log off fact will undo that log on. If you query for active games, the outcome of a game will remove it from the list.

A negative fact looks like a regular fact in the Factual modeling language. It's how it's used that makes it negative. Add the LogOff fact to the model.
fact LogOff {
key:
    LogOn logOn;
}

This fact simply references the log on that it wants to negate. It is a successor of the log on. We can add a predicate to the LogOn based on the existence of this successor.
fact LogOn {
key:
    unique;
    User user;
    Machine machine;

query:
    bool isActive {
        not exists LogOff lo : lo.logOn = this
    }
}

A predicate is a query that evaluates to true or false based on the existence of related facts. The predicate can then be used as a condition in another query.
fact Machine {
key:
    unique;

query:
    LogOn* logOns {
        LogOn l : l.machine = this
            where l.isActive
    }
}

Write a unit test in MachineModelTest to verify that a user can log off.
[TestMethod]
public void UserLogsOff()
{
    Machine machine = _community.AddFact(new Machine());
    LogOn logOn = machine.LogOnUser("alan1");
    _community.AddFact(new LogOff(logOn));

    Assert.IsFalse(machine.LogOns.Any());
}
By combining predicates and conditions, a fact can undo the effect of another fact in a specific query. This makes it a negative fact. Even though facts cannot be deleted, negative facts allow us to model deletion.

Next: Lesson 3b: Negative command in the view model

Last edited May 15, 2011 at 4:02 AM by MichaelLPerry1971, version 3

Comments

No comments yet.