One of the first major mistakes I made as a software engineer involved strings. It happened about 15 years ago. I had written a tool to log out data link traffic to an encrypted file. That part was done, I could open up the file and see a bunch of gibberish. It was now time to read that data back in. I opened up the file and traversed through the file until I reached the end of file (EOF) on the file. What I found was that even small files, with only a few dozen lines of data link traffic were taking longer and longer to load. The file size itself was capped at 10MB, and I knew that MS Word could open up a file larger than that and at least show the first page while it loaded the rest, but my code hung the entire program. I called some of the more senior folks over to me and they immediately saw the issue.
Inside my while loop, I was concatenating my decrypted text with the decrypted text of the next line. Something like:
entireDocument += Decrypt(fileLine);
I was using C++ at the time, and this is when I truly learned the word immutable. By the time my loop ended, I had n+1 strings, each one a little bit larger than the one before, and only the last one being used by anything. The problem wasn’t C++, though, it was me.
My Second Language
About 5 or 6 years later I took a new job, in a new state, using a new language. I was no longer writing C++, I was writing C#. One thing I’d been burned by in the past was not cleaning up after myself. I created a couple memory leaks in C++ because I either didn’t write a destructor, or I didn’t delete everything I needed to delete. When I came to C#, I felt like I was cheating. You could write a destructor, but you were actually advised not to. C# knew what needed to be cleaned up and when, just trust C#.
Except that wasn’t entirely true. It was (and still is, I believe) possible to open a file, read it in C# and have it cause a memory leak if you don’t close it properly. C# handled the cleaning up of member variables by default, but it doesn’t prevent all memory leaks.
But when I encountered opening a file, I already knew from my C++ days that it could be a problem, so I investigated and found out that if I simply wrap the file in a using statement, when it leaves scope, it will be cleaned up.
using(var myFile = File.open(“read.me”))
There were other gotchas that would catch me from time to time with C#, and although I don’t remember specific issues like I do with C++, in part because they typically didn’t carry the weight that the ones in C++ did. I don’t mean they weren’t as important or as fatal as the ones in C++, but by this time, I’d started to develop a better framework for learning these things.
Test Driven Development (TDD)
It was also during my early days in C# that I started experimenting with TDD. I was alone on a project and could not enlist anyone else to help me test. So I read about testing some and saw this idea of TDD. I thought it was stupid. I asked some other people I knew, and they agreed that it was stupid.
But coded unit tests seemed to make sense. I could write some code that would run and tell me if other code was performing correctly, so I started playing with unit tests. Often when a bug came in, one thing I’d do before I declared I had squashed that bug was write a unit test so I wouldn’t have to deal with that bug again.
After playing around with unit tests for a few years I tried TDD again, and it seemed less dumb to me now. But I still wasn’t ready to go 100% with it, that wouldn’t come for a few more years.
My First Dynamic Language
Looking back on the past 17 years I’ve been able to play with some different tools in my career, including some different languages. I felt like I was more productive in C# than I was in C++. And I think a lot of people could read that and agree, they probably have similar stories. It might even cause some people to claim that C# is better than C++.
I have a hard time saying X language is better, or Y tool is superior. Not because I don’t think there is such a thing as better or superior, but because I’m starting to realize how much individual developer experience plays a role. Because I’ll never again be someone that doesn’t know how to do TDD. So even when I’m not writing the failing test first, I’m often thinking that way. In the same way that even if I’m never looping through a file again, I’ll know that concatenating strings is typically an expensive operation.