A while back I was refactoring some C# code, and I noticed that, in the process, I was blindly converting as many instance methods to static as I feasibly could. My process was this:

  1. Stumble across instance method.  This method would run an algorithm using values stored in the object before setting a different value on the same object; it usually returned void or some sort of success flag. For example:
    instance method
  2. Convert to static method that accepts the necessary ‘before’ state as parameters and returns the results.
    static method
  3. Alter the calling method to both pass in the ‘before’ state and set the ‘after’ state of the object according to the value returned from the newly-staticized method.From
    old constructor
    to
    new constructor
  4. Feel sense of satisfaction that I’ve “fixed” the software somehow.
  5. Rinse and repeat, sometimes moving the actual setting of particular object state up the call tree several times by the time I’m done.

But is my sense of satisfaction justified? Certainly in an example as simplistic as the one I pasted above one could argue that I actually made the program harder to read. I had just been doing it because it felt right, not because I had logical reasons for it. And that’s no way to write code.

Surely, I needed to sit back and think about what I was doing.

My first realization was that I wasn’t preferring static methods, per se; I was preferring methods that had no side effects.  I was merely converting instance methods to statics in order to guarantee that no instance variables were being set, a common side effect in day-to-day imperative programming.  External IOs (e.g. accessing a database) and setting static variables (e.g. in rarely-used singletons) are still possible side effects in static methods.  I considered both of those with the same distaste, or at least wariness.  However, I had already ghettoized external IO and minimized singletons as much as possible, each for their own reasons; as those had already been addressed before I went on my latest refactoring rampage, only the instance methods remained to draw my ire.

Eliminating or minimizing side effects via converting instance to static methods had a corollary:  I had to separate object state from the methods operating on that state.  No longer would I have objects that simply knew what do with themselves.  Before, I would have a void method call that did calculations and set state on its object (e.g. the original CalculateTotalPrice() method); now I had some functions that only performed calculations on input values (the new CalculateTotalPrice), and other methods that only set/retained state (the new CoolClass() constructor).  I didn’t even need the two kinds of methods to exist on the same object.  I was giving up on one of the most basic principles of object-oriented programming.

And you know what?  It made the code better.

(to be continued in part II…)