The title is a line from an episode of Uncle Bob’s clean code video series. He advocates refactoring until you get down to 3 lines of code per function and make sure every function is doing one thing and is clearly named. At least that’s what I got out of it. I like his approach on this. So part of Test Driven Development in the coding to make the test pass phase is to do whatever is simplest and easiest to get the test to pass. Well, maybe with some caveats, although I’m not sure what they are right at the moment, but I’ll let you know as I think of them.
So, what did I write that I want to refactor? This:
Private Sub FormToAudit_BeforeUpdate(Cancel As Integer)
Dim OldValue As Variant, NewValue As Variant, AddChange As Boolean
OldValue = FormToAudit.TestText.OldValue
NewValue = FormToAudit.TestText.Value
If IsNull(OldValue) And Not IsNull(NewValue) Then
AddChange = True
ElseIf Not IsNull(OldValue) And IsNull(NewValue) Then
AddChange = True
ElseIf IsNull(OldValue) And IsNull(NewValue) Then
AddChange = False
Else
If FormToAudit.TestText.OldValue <> FormToAudit.TestText.Value Then
AddChange = True
End If
End If
If AddChange Then
pListOfChanges.Add FormToAudit.TestText.Value
End If
End Sub
I don’t like this giant if else set of structures I added to this function. So what can I do? How about extracting the boolean tests to some functions…
Private Sub FormToAudit_BeforeUpdate(Cancel As Integer)
If FieldChanged(FormToAudit.TestText) Then pListOfChanges.Add FormToAudit.TestText.Value
End Sub
Private Function FieldChanged(Field As Access.Control) As Boolean
Dim OldValue As Variant, NewValue As Variant, retVal As Boolean
OldValue = Field.OldValue
NewValue = Field.Value
If IsNull(OldValue) And Not IsNull(NewValue) Then
retVal = True
ElseIf Not IsNull(OldValue) And IsNull(NewValue) Then
retVal = True
ElseIf IsNull(OldValue) And IsNull(NewValue) Then
retVal = False
Else
If FormToAudit.TestText.OldValue <> FormToAudit.TestText.Value Then
retVal = True
End If
End If
FieldChanged = retVal
End Function
Ok, so the original BeforeUpdate module is now SUPER clean. It checks the function FieldChanged, passing the field and it looks much nicer. I’ve now moved most of the code into it’s own function. Before continuing to refactor, let’s make sure I didn’t break anything by running the tests:
Yay, so I think I can make the new function FieldChanged much cleaner as well. Let’s see:
Private Function FieldChanged(Field As Access.Control) As Boolean
Dim retVal As Boolean
If OnlyOneFieldIsNull(Field.OldValue, Field.Value) Then
retVal = True
ElseIf IsNull(Field.OldValue) And IsNull(Field.Value) Then
retVal = False
Else
If Field.OldValue <> Field.Value Then
retVal = True
End If
End If
FieldChanged = retVal
End Function
Private Function OnlyOneFieldIsNull(OldValue As Variant, NewValue As Variant) As Boolean
Dim retVal As Boolean
retVal = (IsNull(OldValue) = True And IsNull(NewValue) = False) Or (IsNull(OldValue) = False And IsNull(NewValue) = True)
OnlyOneFieldIsNull = retVal
End Function
Well, it’s getting better, but I need to do more. Tomorrow… Thanks for joining me!