Using OO to Avoid Branch Logic

Repeat after me: Interfaces and OO are my friends.

Object oriented programming is much, much more than coagulating a concept of a system into a class that contains data and methods that act on that data. Unfortunately, it seems as though many developers' understanding of OO begins and ends here--even though it should only be the starting point toward learning how to truly work with objects. There are numerous techniques one can learn to vastly improve one's effectiveness at creating a flexible, stable, and extensible system--and a professional developer will earnestly seek for these techniques because, well, otherwise they are not a professional developer. After all, shouldn't we give some relevance to the word "professional?"

One aspect of OO programming that has to be mastered by anyone interested in designing and coding winning solutions is interfaces. Just this past week I was faced with a common problem that can serve as a good example of interface usage. Also, this example displays the merits of a great pattern that I only occasionally see (unfortunately): Null Object. First a bit of background that has some relevance to the story:

Instant Communication with the Client

We're currently engaged with a project in the financial sector that in my mind could not be better in terms of client-developer communication. We each have the end-client on IM and can ask questions whenever we have them, and the end-client can do the same with us. In this way we get to know specific details of the business as soon as we need to know them, and we can be as agile as possible. Here is a tweaked IM conversation I had with our client--whom I'll call "Client" for reasons of privacy:

Steve: I've got some thoughts regarding theoreticals I'd like to share. Let me know when you're ready
Client: ok
Steve: Cool
Steve: Would it kill you right now if I made them a type other than IMoney? I want to create an ITheoretical interface that also exposes a Guid of the person owning the theoretical. In this way they will be more conceptually like what they are in the real world (associated with a specific user).
Steve: This will make things a lot easier, I think, both right now and in the future.
Client: not a problem
Steve: Gotta love it
Steve: No chains of bureacracy to go through. Man, I love that
Client: let me know when you have the change ready, i'll take care of it

See how agile this conversation is? See how much less money the client has to pay for this change than s/he would if there was a huge chain of bureaucracy to deal with? The change is instant and now we have an application that more closely models the business. I'm not proposing that all applications can be built with all developers in instant touch with the de facto domain expert, but the more communication can flow between the development team and the domain experts--whether they come in the flavor of the client or one or more business analysts--is the more effective you'll be.

I wanted to make this change because two requirements previously unknown to me reared their heads:

  1. The application is only supposed to display the theoretical value if it belongs to the logged in user; if not, it should display zero. However, when this requirement unfolded it was impossible to know the owner of the theoretical because the theoretical is represented by the IMoney interface and IMoney has no relationship to a specific user.
  2. In a couple of situations in the application that rarely occur I have to obtain other information associated with a theoretical's owner, but because we don't want to pass the entire object representing a person across the network I can't associate it with every theoretical value (theoreticals get serialized a lot and and the object representing a person is relatively large).

The Original Implementation

Here is the IMoney definition:

    public interface IMoney
    {
        decimal Value { get ; }
    }

And the domain object class that uses this for a theoretical (which the UI control depends upon to display the theoretical) looks something like this:

    public class DomainObjectThatHasTheoreticalValue
    {
        private IMoney itsTheoretical;
        public virtual IMoney TheoreticalValue
        {
            get { return itsTheoretical; }
            set { itsTheoretical = value ; }
        }
        
        //Other properties and methods
    }

Introducing an Interface and Implementation

I decided I would change things by introducing an ITheoretical interface that combines the concept of money and a person associated with that money:

    public interface ITheoretical : IMoney
    {
        Guid Owner { get ; }
    }

and then I changed the DomainObjectThatHasTheoreticalValue class to use the ITheoretical interface instead of IMoney:

    public class DomainObjectThatHasTheoreticalValue
    {
        private ITheoretical itsTheoretical;
        public virtual ITheoretical TheoreticalValue
        {
            get { return itsTheoretical; }
            set
{ itsTheoretical = value ; }
        }
        //Other properties and methods
    }

All I had to do at this point was create the Theoretical class:

    public class Theoretical : ITheoretical
    {
        private IMoney itsMoney;
        private Guid itsOwner;

        public Theoretical(IMoney money, Guid ownerID)
        {
            //Code not displayed that checks arguments for null and anything else so that an invalid Theoretical instance cannot be created.

            itsMoney = money;
            itsOwner = ownerID;
        }
        public virtual Guid Owner
        {
            get { return itsOwner; }
        }
        public virtual decimal Value
        {
            get{return itsMoney.Value; }
        }
}

Initial Usage of the Interface

You'll notice above that ITheoretical implements IMoney, and it also adds a Guid property representing the owner of that money. (Normally I would have favored using the entire class/interface representing an entire person for the Owner property because I always favor using as large an object as I have on hand, but I used a Guid in this case because the ITheoretical implementation(s) will be serialized across the network numerous times and because I don't need the entire "person" object at this time.)

My plan at this point was to:

  1. Change the grid that displays the theoretical to check the theoretical owner against the logged in user.
  2. Display the theoretical value in the UI if the current user owns it or display zero if not.

Here is a condensed version of the element that gets bound to the grid, with the code that implements the above plan:

    public class GridElementThatDisplaysTheoreticalValue
    {
        private Guid itsLoggedInUser;
        private DomainObjectThatHasTheoreticalValue itsDomainObject;

        public virtual decimal TheoreticalValue
        {
            get
            
            {
                //This if check is new. This getter previously returned itsDomainObject.TheoreticalValue.Value in all cases.
                if (object .Equals(itsLoggedInUser, itsDomainObject.TheoreticalValue.Owner))
                     return itsDomainObject.TheoreticalValue.Value;
                return 0;
            }
        }
    }

This might not be too bad if this is the only code displaying a theoretical value in the application, but it isn't. If I was to take this approach I'd have the following concerns:

  1. I'd be duplicating the above if-check in numerous places throughout the code, and anyone else coding the application would have to remember to do the same for whatever requirement depends upon different behavior in regards to the theoretical value, the owner of that value, and/or the logged in user. Duplicate code is bad enough on its own, but when it applies to the domain of the business it is especially bad. What would surely follow from this line of attack, I thought, would be one or more bugs popping up throughout the life of the application. In this case such a bug would give a potential advantage to a user because if they can see the theoretical value(s) of other users they would then have a competitive advantage in the marketplace over those users. Not a good situation to have.
  2. Related to the above concern, if I have duplicate code I have duplicate code paths that must be tested (at both the automated test level and the acceptance/QA test level).
  3. If I decide to send all theoreticals across the wire and then weed them out at the UI level, what if there is an especially crafty user that knows how to use a network packet analyzer to examine the values coming in through the network, even if I successfully write code that stops the display at the user-interface level?

Using the Null Object Pattern to Fulfill a Need

So what did I do? I leveraged the power of interfaces to carry out the Null Object Pattern.

In my experience the Null Object pattern is a lesser known pattern, probably because it didn't appear in the GoF book--which is the most famous design pattern book. The Null Object pattern is a good choice when you have a number of code paths in which the value you test against can be null (or some other "special " value) but you don't want to write if/else code throughout the system to check the value for null (or the "special" value). Eliminating such checks can make your code a lot less error-prone because we all forget to check things from time to time...and hence we all create bugs. Add other developers coming and going from a project into the mix and we have a recipe for disaster.

Here is how I applied the Null Object pattern to the above situation with Theoreticals. Because we are using the ITheoretical interface above, I created a NullTheoretical class like this:

    public class NullTheoretical : ITheoretical
    {
        public virtual Guid Owner
        {
            get { return Guid.Empy; }
        }
        public virtual decimal Value
        {
            get {return 0; }
        }
    }

Note: Some optimization-centric people might wonder why I use the virtual keyword above. I do this because I'm not concerned with the extremely negligible performance hit created by the virtual keyword and instead do it because I might want to override the behavior. In fact, I'd declare that if I'm doing TDD (which I am) I am very likely to override the behavior for testing purposes.

Now all I had to do was to change the DomainObjectThatHasTheoreticalValue class like this:

    public class DomainObjectThatHasTheoreticalValue
    {
        private ITheoretical itsTheoretical;

        public virtual ITheoretical TheoreticalValue
        {
            get
            {
                if
(object.ReferenceEquals(itsTheoretical, null))
                    return new NullTheoretical( );
                return itsTheoretical;
            }
            set { itsTheoretical = value ; }
        }

        //Other properties and methods
    }

I'm hoping you're beginning to see how this greatly helps the system. Remember, I was hit with these requirements out of the blue:

  1. The application is only supposed to display the theoretical value if it belongs to the logged in user and nothing if not (by nothing I mean nothing and not zero). However, when this requirement unfolded it was impossible to know the owner of the theoretical because the theoretical was represented by the IMoney interface and IMoney has no relationship to a specific user.
  2. In a couple of situations in the application that rarely occur I have to obtain other information associated with a theoretical's owner, but because we don't want to pass the entire representing a person across the network I can't associate it with every theoretical value (theoreticals get serialized a lot and the object representing a person is relatively large).

With my initial change, in which I would check the logged in user's Guid againt each theoretical value's owner, I introduced an if-check in the the element bound to the grid control (along with any other UI elements with similar behavior):

    public class GridElementThatDisplaysTheoreticalValue
    {
        private Guid itsLoggedInUser;
        
        private
DomainObjectThatHasTheoreticalValue itsDomainObject;

        public virtual decimal TheoreticalValue
        {
            get
            {
                //This if check is new. This getter used to just return itsTheoreticalValue.Value in all cases.
                if (object.Equals(itsLoggedInUser, itsDomainObject.TheoreticalValue.Owner))
                    return itsDomainObject.TheoreticalValue.Value;
                 return 0;
            }
        }
    }

However, because I have introduced the NullTheoretical class to the system I don't even have to change the element bound to the grid, so the entire UI--meaning any code that deals with theoreticals in the above respect can remain unchanged. And so the GridElementThatDisplaysTheoreticalValue can be left alone:

    public class GridElementThatDisplaysTheoreticalValue
    {
         private Guid itsLoggedInUser;
         private DomainObjectThatHasTheoreticalValue itsDomainObject;

         public virtual decimal TheoreticalValue
        {
            get { return itsDomainObject.TheoreticalValue.Value; }
        }
    }

If the itsDomainObject variable in the above class gets set to a NullTheoretical instance, the TheoreticalValue property will return 0; if it gets set to a Theoretical instance, it will return whatever value the Theoretical instance represents. In this way I push responsibility into the domain instead of the UI--which is really where it belongs. If I'm the grid I now say, "Hey, my responsibility is to show the stuff that's given to me, not decide business logic for you. You just give me what you want to show and I'll do my job and show it. I'm a grid and I have a lot of other responsibilities to take care of, so you make the decision for me."

If no one sets the DomainObjectThatHasTheoreticalValue.TheoreticalValue property it always returns a NullTheoretical instance, which is fine because it is an object instance and not null. Anyone depending on this property does not have to write special code--which ends up getting scattered throughout the system--to deal with this situation. There is now no way to set the property to true "null". Whether you set it to a NullTheoretical instance or to null, it returns a NullTheoretical instance.

Another tangential note to focus on here is that I introduced the pattern to fulfill a need. What I didn't do is use the pattern before it was needed. Patterns are a great tool to use, but just like any other tool there is a time and place for them. An experienced carpenter doesn't sand the studs he cuts when framing a house; he sands when building something requiring a smooth finish. Because duplicate code arose in the system, I used a pattern above to remove it because removing duplicate code is always a worthwhile effort. As your familiarity of patterns increases, you'll find yourself getting faster at spotting which ones to use and where they can be applied.

A Wisecrack Ending

If you've been especially focused on the details above, you might ask, "Yeah, but what about dealing with Guid.Empty when you use the DomainObjectThatHasTheoreticalValue.Owner property to retrieve the object representing the owner of the theoretical? Since Guid.Empty won't be associated with such an object, what do you return?"

The answer? A NullPerson instance, of course. :)

Comments



Hey Steve,

Good illustration of polymorphism. Why not altogether get rid of IFs from your example, as follows:

public class DomainObjectThatHasTheoreticalValue
{
private ITheoretical itsTheoretical = new NullTheoretical( );

public virtual ITheoretical TheoreticalValue
{
get { return itsTheoretical; }
set { itsTheoretical = value ; }
}

Is there a chance that ThoreticalValue getter will never be accessed and you’re delaying object creation? But then again, as you said, NullTheoretical has small overhead. CU!



Hey, massybird.

I thought about it, and I also thought about using a static readonly NullTheoretical cached in the DomainObjectThatHasTheoreticalValue. I didn’t do it your way because I don’t want anyone setting the value to null. The best way would probably be to check to see if the value it is set to is null, and, if so, then set it to a cached static readonly instance of NullTheoretical. Agree? There was a bit of me that didn’t do it this way because I wanted to display the concept of not optimizing up front, but I would probably do it with the static readonly instance.

Are you Chief Architect/CEO/President/Superman over there yet?

:)



Hey, I should also say that we’re doing another session on TDD for our user group next Wednesday, if you happen to be in town. It’ll be on TDD and the GUI…should be fun…I think we have a lot of good content to share. Let me know if you can make it.