Jul 16 2008

Eliminating Nulls

Category: .Net Framework | Best PracticeAlexRobson @ 14:51

I present for your reading enjoyment, my newest soap-box: eliminating the use of null in databases and code as much as possible. I realize the implications this has. I realize that Microsoft, under pressure from a lot of developers who wanted to further bastardize null, introduced nullable value types in the 2.0 version of the framework. But I think I can make a rock-solid argument for why 1) nulls are not intended to drive business or programmatic logic and 2) should only be allowed in code or database on the rarest of occasion.

Null Isn't A Value
In .Net, Null isn't a value. Null wasn't put into the framework for your uses. In .Net you have two kinds of types: value types and reference types. A value type is defined by a struct or enum and places it's data directly on the stack. A reference type is defined by a class and is called a reference because any instance of this type is actually stored out in a blob of dynamically allocated and managed memory called the heap. The variable which represents this instance is placed on the stack and is actually a pointer to the spot in the heap where the actual instance resides.

Null is what happens when an instance variable doesn't point to a memory address on the heap. Null is not an actual value which is why (traditionally) value types cannot be null because they're not an address pointer but a value directly on the stack. The sole reason for the null keyword (or Nothing for you VB folks) is so that you can programmatically test for and handle the unfortunate case when your reference type variable isn't pointing to anything you can use. The reason you get a NullReferenceException in the framework isn't because Microsoft loves to annoy you, it's because you're trying work with an object instance that no longer exists.

Testing For Null vs. Testing For Constants
A common argument against the "no more nulls" campaign I'm on comes up when discussing UI binding and validation. You may not want to display underlying values in the UI to the user if the values weren't populated from something like a database. As I understand it, the code would look something like:

 if (class.Property != null)  
 {      
      textBox.Text = class.Property;
 }


Well, what I don't get is how that's any different from:

 if (class.Property != EMPTY_CONSTANT)   
 {
      textBox.Text = class.Property;
 }
 

Where EMPTY_CONSTANT would be for whatever value type you were testing for whether that's EMPTY_DATETIME or EMPTY_STRING (though that's really unnecessary). As you can see, the point is pretty moot. You can just as easily test for a constant, it's still readable and you protect everyone from NullReferenceExceptions.

Avoiding Null In The Database
Harder for me to argue this one other than to say that I believe default values and NOT NULL exist in RDBMs for a great reason! If you allow nulls in database columns, you're going to end up having to write additional logic to code around them everywhere. The one great exception I'm aware of is foreign key columns. A column marked as FK has to have a value which ties to a row in the parent table. This means if you don't have a row for the FK, it has to be null. The work around for this would involve putting a non-sense row in the related table which would need to be filtered out all over the place (bad).

Tags: ,

Comments

1.
trackback DotNetKicks.com says:

Trackback from DotNetKicks.com

Eliminate Nulls

2.
Chris Pietschmann Chris Pietschmann United States says:

I order to get rid of the use of Null, you basically need to institute some kind of default value. But, when you use a default value, there isn't any way to tell whether the property/value was set or if it just contains the default because it could be set to the default. By using Null you can tell if it's been set yet or not. If it hasn't it's Null, if it has it's some other value. You may think that you could use the default value of String.Empty for a String or 0 (zero) for an Integer, but the user could enter those values in through the UI. Basically, the only reason Null exists is so we can tell if the property/value has been assigned a valid value or not. If Null, then no value has been set yet and we can perform the appropriate action.

3.
Naz Naz United Kingdom says:

When you instantiate an object it also uses some memory when you put a value in the database even if it's empty that also uses some space. Nulls are there for a reason you need to learn to use them they can be a pain sometimes but they are needed.

4.
AlexRobson AlexRobson United States says:

@Chris

I completely understand where you're coming from. I've actually got a very clean solution for the problem you've described. I'll have an upcoming post about that and link it back to the comment list here. Thanks for your response.

5.
AlexRobson AlexRobson United States says:

@Naz,

You're absolutely correct, nulls are there for a reason. That reason is when a reference type (pointer) does not contain the address to a value on the heap. Nulls aren't there so you can write clever logic against.

I understand that using nulls as state indicators may not have catastrophic results in small scale projects but when writing things like facades or and enterprise service bus, all the places where those nulls get intentionally created or used end up causing headaches.

A Null can exist for so many different reasons that treating it as though it's logically indicative of a single cause will make for some really difficult to track bugs. The right approach is to provide default values and simply provide a mechanism that determines whether not a value has changed. As I mentioned in my response to Chris, I'll provide that in a forthcoming post.

Thanks for your reply.

6.
Evil Rob Evil Rob United States says:

Wow, this post was a bunch of nonsense. Don't worry - I've laid out the truth for the internet to see. No more deceptions by you: robtechdiff.blogspot.com/.../...r-best-friend.html

Add comment


(Will show your Gravatar icon)

  Country flag

biuquote
  • Comment
  • Preview
Loading