High Wire Walking With No Net
As a young programmer, I was heavily influenced by Joel Spolsky's post, The Joel Test: 12 Steps to Better Code. The entire article is worth reading. For now, though, I want to focus on the first and most important step: Source Control.
I started my professional software development career in 2007. I was a junior developer for the company I now own, Grandjean & Braverman, Inc. Our portfolio of programs at the time was almost entirely in Microsoft Access.
In those early days, our method of "source control" was making regular copies of the front-end database and appending a date to the filename. This was....less than ideal. The problem is best illustrated with a quick story.
I was fixing bugs in our largest application. There were over 800 queries, more than 250 forms, 275 reports, and 50 standalone code modules. There were well over 100,000 lines of code. Here I was, a green developer, let loose in this behemoth with my boss's single foreboding piece of advice, "Don't forget to make a backup copy of the file before you make any changes."
I was nervous. This program was a core piece of our company's entire business. So I made copies. Lots of copies. I had Assessor2k-2007-05-02.mdb
and Assessor2k-2007-05-03.mdb
. Pretty soon I had Assessor2k-2007-05-03-1141.mdb
and Assessor2k-2007-05-03-1158.mdb
. You get the idea. I was making backup copies multiple times a day. It became second nature. It was just part of my workflow. Something still didn't feel quite right, though. I wasn't able to put my finger on it yet.
After a few weeks, I built up some confidence. I was starting to work through my impostor syndrome. Now when I was fixing bugs, I would also go through and refactor working code. Before I had heard the term "technical debt," I intuitively understood that confusing code made programs harder to maintain.
One of the first things I fixed were a bunch of If...Then...Else
statements where the True
lines of code had apparently been deleted. They were statements that looked like this:
Dim CustomerFirstName As String
If Forms!MyForm!FirstName = "" Then
Else
CustomerFirstName = Forms!MyForm!FirstName
End If
I fixed these statements by converting them to this:
Dim CustomerFirstName As String
If Not (Forms!MyForm!FirstName = "") Then
CustomerFirstName = Forms!MyForm!FirstName
End If
I smiled with smug satisfaction as I cleaned up my boss's code blocks where he was obviously too lazy to do it the right way himself. I made changes similar to the above in about half a dozen different places. I made these changes over the course of several weeks or months.
Until one day I learned something about how VBA performs Null comparisons.
Sub TestNull()
If Null = "" Then
Debug.Print "A"
Else
Debug.Print "B"
End If
If Not (Null = "") Then
Debug.Print "C"
Else
Debug.Print "D"
End If
End Sub
--------------------------
--== Immediate Window ==--
TestNull
B
D
--------------------------
That's right. The only difference between the two conditionals in the above If...Else...Then
statements is that one is being negated. Surely if you have two identical conditional statements and the only difference is that one is wrapped in a Not
operator, then in one instance the If
clause would be evaluated and in the other instance the Else
clause would be evaluated.
What I failed to realize in all my self-righteousness is that in VBA, comparing Null
to anything results in Null
. Furthermore, negating a Null
also results in Null
. And, finally, when evaluated in an If
statement, a Null
always returns False
. Or, as Microsoft notes more succinctly, "any expression containing a Null is itself Null and therefore False."
As I read about the idiosyncrasies of Null
handling in VBA, I came to a startling realization. I had just spent the past few months methodically introducing very subtle logic bugs all over our flagship software. All in the name of reducing technical debt. Oh, the irony.
What truly horrified me, though, is that I had no idea where I had made the individual changes. To make matters worse, there was no way to easily find those changes. I mean, I suppose I could have opened up Assessor2k-2007-05-03-1141.mdb
and Assessor2k-2007-05-03-1158.mdb
side-by-side and started combing through lines of code. I had dozens of backup copies of the program. Eventually, I would find all my changes. So I did what any reasonable person would have done in my situation. Nothing.
At least, in the short term, I did nothing. But that was the straw that finally broke the camel's back for me. I decided then and there that I was tired of writing high-wire code with no net. I still wasn't sure how I was going to do it, but one way or another I would figure out how to use this "source control" thing that Joel Spolsky seemed to like so much.
So that's how my journey into Microsoft Access version control began. It's a journey that continues to this day.