Test First And Functional Programming Synergy

While experimenting with the principle of CodeUnitTestFirst using PythonLanguage, I've noticed that ReFactoring tends to lead me towards FunctionalProgramming. In other words, I can most easily satisfy my newly written test without affecting anything else by writing functional code, even if it's just for that method.

For example, when writing a class that takes an optional argument to describe its initial state we get something like this:

 def testCreate(self):
 	obj = MyClass('abc')
 	assert obj.state == <some tricky value>

class MyClass: def __init__(self, state) <do other stuff> self.state = <Lots of tricky coding here>
Boy that tricky code is tricky. Let's refactor it out:

 def testCreate(self):
 	obj = MyClass('abc')
 	assert ob.state == <some tricky value>

class MyClass: def __init__(self, state) <do other stuff> self.doTrickyCode(state)

def doTrickyCode(self, state) self.state = <Lots of tricky coding here>
The Tests still pass. But I want more confidence that the tricky code is working, so I'd better test it some more. Hmmm, other stuff happening in MyClass is making that hard. So:

 def testCreate(self):
 	obj = MyClass('abc')
 	assert obj.state == <some tricky value>

def testTrickyCode(self): obj = MyClass() assert <tricky value> == obj.

class MyClass: def __init__(self, state) <do other stuff> self.state = self.doTrickyCode(state)

def doTrickyCode(self, state) value = <Lots of tricky coding here> return value
So the end result is that to make things more testable (testy? ;-) The doTrickyCode method has been written in a functional style, i.e. it doesn't change the state of anything.

So, here is my point for discussion: is there a synergy between CodeUnitTestFirst and FunctionalProgramming that we should be trying to exploit?

-- DavidPlumpton

I have definitely noticed that I write code in a functional style when I'm also writing automated tests for the code. I don't think it matters whether you write the tests first or not (I never do). It's just that it's easier to write automated tests for side-effect free code.

-- CurtisBartley

If you created the object with a state then doTrickyCode is side effect free because no state has been changed. The code [change?] makes for worse code, not better.

The root difference between purely functional programming and object oriented programming (in my opinion) is that pure FP keeps all of the statefulness of a program in only one place, and OOP divides the state into many small pieces. Any stateful bits of code in FP have that state explicitly passed into them whether that's visible or not (monads). If you can easily set your 'objects' in a known state, they're a lot easier to test than if you have to call sixty other objects to have the state setup correctly. If you've ever tried to write unit tests in a web application environment, you know what I'm talking about.

In my experience, purely functional languages such as Haskell really do encourage decoupling of code, since state is explicitly passed, but it's still possible to write crappy heavily coupled code. --ShaeErisson
See also: ExtractMethod

View edit of April 24, 2010 or FindPage with title or text search