Back in the day, when I opened my first savings account, they gave me an account register. It had a column for deposits, another for withdrawals, and a third for the balance. It was pen and paper, and it was good enough. It was all I needed to keep track of money in the bank.
Many years later, when I was working for a church in Arlington, VA, I had a chance to work with Chris. Chris was an IRS auditor, but not the kind of auditor you ordinarily think of when you think "IRS audit". Chris didn't audit people like you and me for the IRS; he worked for the Treasury Department auditing the IRS's books. He was also the church treasurer.
From Chris, I learned about double-entry accounting. I confess, at the beginning, I didn't get all the fuss Chris was making over the general ledger. Why was he bothering with this general ledger thing, when just recording the church's checks in one column and receipts in the other seemed fine to me, and way less complicated.
He was concerned with tracking everything in 2 places because he knew immediately when credits and debits didn't balance that there was a mistake somewhere.
Still, I was skeptical. It seemed like a lot of extra work. And it took some effort to wrap my thinking around the more abstract concepts of equities and liabilities. But when I finally did start to understand, it opened a whole new level of vision about the church's financial standing.
Fast-forward a few years. I'd learned some PHP. I could write code that got the job done. I was doing just fine, thank you. Then I met Tonya. She suggested that I might start writing tests for my code. Why? To prove that my code worked.
At first, I didn't get it. Of course my code worked. I could tell it worked. There was a website running with my code!
"But how do you really know it works?" she wanted to know. "What if this happens? Or that other thing gets into it? Will it work then?"
So I started writing tests. I wrote the code, and then I wrote some tests to prove it worked. But writing tests was hard. Most of the time, writing the tests for code I'd written was much harder than writing the code itself. But that's how I started. It was frustrating. It was really hard. I wondered, was this extra pain really worth it?
As I started looking more deeply into this testing thing, I found a lot of people saying that if you write tests first, it's not so hard. (Tonya had mentioned this "Test Driven Development" thing — TDD — but we never did it that way, I think, because we were dealing then with WordPress.) Writing tests first, though, was a bit like wrapping my mind around equity and liabilities. How can you write a test for code that hasn't been written yet? What are you even testing at that point?
It's counter-intuitive. "Tests" isn't the best word for what you're doing at this stage. Maybe "behavior specification" is a better way of putting it. The "test" is itself a program that tells you whether another program does what it's supposed to do. When you first write the test, it fails; there is no code doing that thing yet. Then you write whatever code makes the test/specification pass. When it passes, you know the code you wrote meets the behavior you specified.
Coding this way has several beneficial side effects, one of which is that you have some "proof" that your code works. (You don't really have proof, just like having a general ledger isn't proof that the books haven't been cooked, but that's a different post.) Another side effect is that writing to the test/specification forces you to write the code more efficiently; you tend to write only the minimum needed to pass the test, so it's simpler, more modular and decoupled.
Coming back around to my earlier experience with accounting, when I've written tests for a project, it's like I've got not just a checkbook, the code itself, but also a general ledger that provides much deeper insight into the state of the code and what it does.
When Chris did the church accounting, I noticed that he always made the general ledger entry first, then the corresponding entries in whatever accounts he was dealing with. It just made things easier. The ledger was the "source of truth" to which the other accounts had to match. People in the church didn't care about the ledger; they wanted to know what was in their accounts. The Sunday School teachers just wanted to know if they had money for crayons, but writing out the accounts was easier knowing already what the end result had to be.
I write the tests first. It just makes things easier. Once I've established a "source of truth" in the tests, the code my end users care about, that actually does what they want, has to match. The business I work for really doesn't care about the tests, but writing the code they do care about is easier knowing already what the end result has to be.