Thursday, August 19, 2010

Known Values and NULL - Communication channels and when to cache

"There are known knowns. These are things we know that we know. There are known unknowns. That is to say, there are things that we now know we don’t know. But there are also unknown unknowns. These are things we do not know we don’t know."  - United States Secretary of Defense Donald Rumsfeld

Rumsfeld really summed up the problem with his statement.  One of the most commonly used constructs in programming in the concept of NULL, to indicate an unknown or unset value.  This is all fine, until you start to design a communication channel and start caching information on the client.  


The problem really comes down to half filled data structures being returned to the client or sent to the server.  This occurs usually because of a trade off between completeness of data and performance or queries.  Now, we can argue whether or not this is the best approach, but for now let's just assume this is the case.  A more valid place for this is an "Update" message to the server, where we want to use a common UpdateRequest structure, but only want to update some portions of the data.


The problem is, when the client sees a NULL in a field, does it mean the value was actually NULL in the database, and therefor a "known unknown" or does it mean the value was never set and therefore the client should request that value from the server if needed?  The same problem can go for updating data:

Say we have the simple UpdateRequest as:
int id;
string name;
string description;


If we send an update request with {id=1, name="Kevin", Description=null}, does that mean that the description is unknown, and should be written as such to the database, or does it mean we don't want to update the description and keep whatever the previous description was?


In order to solve this problem, I introduced a simple wrapper class called KnownValue:


  [DebuggerDisplay("Known: {Value}")]
    public class KnownValue <T> 
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="KnownValue&lt;T&gt;"/> class.
        /// </summary>
        /// <param name="value">The value.</param>
        public KnownValue(T value)
        {
            Value = value;
        }

        /// <summary>
        /// Gets or sets the value.
        /// </summary>
        /// <value>The value.</value>
        [DataMember(IsRequired=true)]
        public T Value
        {
            get; set; 
        }
    }

The beauty of this simple class is we can now introduce three-state logic:

Description = null: The value is unknown, so don't change it on the server or if the user requests it, we don't have it cached so go get it.
Description = KnownValue<string>(null): The value is known, and should be set to NULL. If the user requests the value, don't go to the server since we already know it is NULL.
Description = KnownValue<string>("My Description"): The value is known, and should be set to "My Description".