Potty Little Details

Just another WordPress.com weblog

Context Bound Object- Part I

leave a comment »

 

  Caution 

Everything in this article is 100 percent undocumented. Reliance on these techniques is not supported by either Microsoft.. Use at your own risk! If your computer won’t work afterwards, your toaster blows up, or your car doesn’t start, I assume no liability whatsoever.You’re now about to enter the uncharted territories of .NET and you do so on your own risk. I can only provide some guidance.

Well, it’s great that you’re still with me after this introductory warning. So let’s start with a look at some common business applications. You will quite likely have some object model that holds local data before it’s committed to the database. Those classes will contain parts of your business logic. For example, assume that your application provides an instant way for employees of your company to donate various amounts of their paychecks to charity organizations. In that case you might have a data object that looks like the one shown below , which allows a user to set an organization’s name and the donation of a specified amount to it.

Start example

using System;

namespace ContextBound
{
   public class Organization
   {
      String _name;
      double _totalDonation;
      public String Name
      {
         set
         {
            _name = value;
         }
         get
         {
            return _name;
         }
      }

      public void Donate(double amount)
      {
         _totalDonation = _totalDonation + amount;
      }
   }
}

End example

You might also have some database restriction or business logic that limits an organization’s name to 30 characters and allows a maximum donation of $100.00. Therefore you need to extend Donate() and the setter of Name to check for this logic:

public String Name
{
   set
   {
      if (value != null && value.Length > 30)
      {
         throw new Exception(“This field must not be longer than 30 characters”);
      }

      _name = value;
   }
   get
   {
      return _name;
   }
}

public void Donate(double amount)
{

   if (amount > 100)
   {
      throw new Exception(“This parameter must not be greater than 100.”);
   }
   _totalDonation = _totalDonation + amount;
}

You’re checking the business logic and your application works as expected. So far, so good. The problems only commence as soon as more developers start using your objects as the base for their applications because they don’t know about those restrictions by reading the interface definition alone. As in most real-world applications, the business logic is in this case hidden inside the implementation and is not part of the metadata level. There is no way for another developer to tell that the maximum amount for a valid donation is $100.00 without looking at your source code.

If you’re a well-informed developer, you already know that you can at least document those parameters using inline XML comments to automatically generate online documentation for your classes—but you still have to document and implement the logic in two separate places. If you’ve never, ever changed any implementation detail without updating the inline documentation, you don’t need to read further—you already solved the problem.

In most projects though (at least in some I’ve recently heard of) there is a direct proportionality between days to deadline and quality of documentation. Somehow people tend to forget to update comments as soon as their boss is reminding them that they should have shipped it yesterday.

Wouldn’t it be great to just specify those checks using some source code attributes and have some “black magic” happen between the client and your objects that takes care of checking the passed values against those attributes?

In a perfect world, these methods might simply look like this:

public String Name
{
   [Check(MaxLength=30)]
   set
   {
      _name = value;
   }
   get
   {
      return _name;
   }
}

public void Donate([Check(MaxValue=100)] double amount)
{
   _totalDonation = _totalDonation + amount;
}

Now the documentation of your business logic is applied on the metadata level! You could easily use reflection to generate printed or online documentation that includes these basic business logic checks as well.

Well, unfortunately, no checks have been done yet. In fact, when using this class, you could easily set Name to any possible value and Donate() to whatever amount you’d like.

  Caution 

You’re now really about to read about unsupported and undocumented features of .NET Framework.Your mileage may vary.

What’s still missing is that magic something I mentioned that would sit between the client and your object (running maybe within the same process and application) and perform those checks. This is where ContextBoundObject enters the game we will explore on next series.

Advertisements

Written by oneil

September 9, 2008 at 2:40 pm

Posted in C#

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: