Friday, March 6, 2009

Conditional Logic and Code Smells


At Ward Cunningham's wiki one finds a discussion entitled Switch Statements Smell. This discussion begins with considerations of Beck and Fowler's statement in chapter 3 of Refactoring (Fowler, 1999) that switch statements were smelly because they tended to create duplicated code. I unsuccessfully tried to add to that discussion the treatment found in the Gang-Of-Four book (Gamma, 1999). So, please find below a few more thoughts.

The following quote predates and complements Fowler and Beck's discussion in chapter 3 of Refactoring. In the Gang-Of-Four book one finds the following quote on page 307.

“Like long procedures, large conditional statements are undesirable. They’re monolithic and tend to make the code less explicit, which in turn makes them difficult to modify and extend. The State pattern offers a better way to structure state-specific code. The logic that determines the state transitions doesn’t reside in monolithic if or switch statements but instead is partitioned between the State subclasses.”

Using conditional logic to implement behavior which is dependent on the state of a class is programming in temporal ignorance. If a change of state has occurred that affects behavior, then the readyness of that class to implement the appropriate behavior should occur synchronously with the change of state. Why should an object live in ignorance when a change of state has occurred that will also change how the object behaves? I refer to this state of ignorance as decoupled state-behavior (DSB). Allowing the state of an object to be decoupled from its behavior should be considered a loose end, a piece of untidyness which requires conditional logic to be resolved. Why leave such loose ends around? They can only lead to problems. Note that this does not apply to using conditional logic to determine other actions not related to the state of the object. DSB refers stricly to the relationship between the state and behavior of the same object. Since DSB requires conditional logic for resolution, this situation also demands consideration from the race condition perspective.

Temporal ignorance creates race conditions. In addition to violating a principle of OO programming, that a method should do no more than one thing, conditional logic statements are not thread safe. Consider the following 'if' statement:

if (propertyValue == 1)
execute statement1;
execute statement2;;

We generally assume that nothing will change the value of propertyValue before we execute statement1. That is a false assumption. It is easy to create race conditions where the propertyValue is set to 2 by a competing thread in between executing the 'if' statement and executing statement1 in the example above. Wouldn't it be smarter to securely change the behavior at the same time the property value is changed?

public void setPropertyValue(int intValue)
synchronized (this)
propertyValue = intValue;
currentStrategy = appropriateStrategy;


Gamma, Erich et al (1994) Design Patterns: Elements of Reusable Object-Oriented Software [0201633612]

Fowler, Martin (1999) Refactoring [ISBN 0201485672]

No comments:

Post a Comment