What I’ve done wrong
Everyone likes to blame everyone else for their project’s shortcomings, especially programmers. I’m no exception. Instead of writing about what others have done to make me not succeed or at least fall short of all of the project’s goals I’ll write about the flip-side. I’m just as much or even more so to blame than everyone else. This project spanned the better part of 3 years. In no particular order:
- Not saying “no.” There’s something magical about the word “no.” I read a great post on “no” not too long ago. Instead of, we’ll never meet those deadlines if we… or if I do that then I’ll have to completely redo… or sure, why not? I’m already behind on… simply, no. As a junior developer I never felt it was my place to say this to anyone. As a matter of fact no one asked me or allowed me to make technical decisions until I said no. A developer, not making technical decisions and not being included in most technical conversations, shouldn’t happen. Once I had the confidence to say no not only was I able to better meet deadlines but my own work proceeded at a more measurable pace.
- Updating everything to the latest patch. Over the past few years we’ve used a variety of third-party, propriety libraries to build our software. The quality of these libraries was without question poor. Every two months one of the library vendors rolled out another patch aimed at introducing more bugs …er, fixing bugs. Invariably once working code didn’t. Sometimes once compiling code didn’t! Knowing full well what would happen, we’d update anyways. The gamble? The newest update would fix the bug preventing the implementation of the “must have” feature du jour without breaking anything else in the process.
That’s not entirely true. Some of the updates were done to make delivery requirements at customer request. In the beginning it was me gunning for the latest updates. I learned fast.
- Prematurely accepting subcontractor code. A subcontractor delivered asked for code. It was accepted by management. I thought nothing of it that it had been accepted. I thought nothing of it that it hadn’t been tested, that I hadn’t tested it, before acceptance. I thought nothing of it that the source was not made available for inspection. I thought nothing of it that their one “object” was the library. All of this I paid no heed until a month later when upon using it I discovered it didn’t work. It didn’t work not as in “the car won’t start” work but rather “the engine starts but the gas pedal is stuck and it shot Roger in the foot.” Corrupted memory, unimplemented methods, undocumented string based function arguments, the list goes on. The minute that code arrived I should have requested to test it myself. It ultimately cost me 2 months of my time.
- Maintaining unused code. I was mandated by those above me to keep old work alive on the off-chance we might need it. Let me reemphasize the important part: chance we might need.
As it turned out, we never needed any of it. See #2? Guess where all the compilation errors occurred. One time was I allowed to comment out sections of unused code but only as a last resort to meet a deadline. I should have pressed harder on commenting out unused sections. As the requirements and features list changed I could have spoken up and justified removing these. We did it before, why can’t we do it again? The lost productivity — measured in weeks — could have been put to better use.
- Refactoring. Yet one more thing I was not allowed to do until recently which is a standard of good software methodology. “If it worked, don’t touch it! We had far too many new features to add and too much old code to maintain to begin changing things. Stuff was breaking everywhere at once, why add to it?…”
Why add?! I wasn’t talking about adding anything. Refactor means reduce. I can’t begin to tell you how many violations of the DRY principle could be found in the code. The only “refactoring” I did manage to accomplish was to take functions that had been clicked and pasted between projects and stick them into a single base library. I should have spoken up and attempted to explain the difference between rework and refactor. I should have insisted on it. I should have backed up those arguments with logical reasons.
- Unit Tests. When the code was handed to me it was nearly untestable. Not that you couldn’t look at the output to see errors. Rather, in the state it was given I would have had a very difficult time writing unit tests or any tests for that matter. Looking back at some of the changes I made, I didn’t help. You’re supposed to leave code better than when you found it.
- Subversion. CVS, Git, whatever you choose. Our server glitched one time and we lost a few days worth of work. From that point forward we weren’t allowed to use automated source control software. It was done by hand through a naming convention on the file system. I didn’t argue. Nowadays I can’t even point to older code to say “see this? It was worse before I got to it.” and have people believe me. They just assume I’m the one that screwed it up in the first place. Do you know how bad that makes me look?
- Spending time on dead-ends. I could point to a bug in a library blocking us from meeting a goal. If that goal was the current “must have” feature the reply was keep working on it. Didn’t matter that the goal was unreachable. I remember one whole week spent toiling away in futility attempting a task. I began researching other third-party libraries just to reach my goal until that too was shot down. Customer requirements meant that was a no-go.
See #1? I should have stood my ground and insisted that I work on something else. Instead, I waited in misery for management to come to the realization. I not only wasted both my time and their time but I also endangered the project delivery dates.
- Gold plating. I was allowed full reign on creativity for this one GUI. Four days into a task that should have taken a single day and the project was now 3 days behind schedule. My excitement was contagious. I got management excited too. They wanted more. More new features, more new functionality and now we were 7 days behind schedule. Sure looked sweet but I violated KISS.
- Not being informed. My first manager had a head that was a human hard-drive. The man could remember everything. Since he could remember everything there was very little written down; we only needed to query him. However, as it turns out there were things he didn’t remember or at least didn’t pass on to us.
One month before our last delivery date we found out about requirements that were nearly 2 years old. I did ask to be more informed but I never pressed the point strongly. If I had, we might have known about that requirement. Then I would have been able to meet delivery dates under less stress and produced higher quality code. The code they did get reflected poorly on me and on my company as a whole.
- Not being involved. I was kept to my little cubicle in the front of the office, near where everyone enters and away from the customer. New features were added weekly. Sometimes new features were agreed upon because it was felt either the customer would forget, they could be talked out of them at a later date, or requirements would change making them moot (paraphrased but yes, this was said.)
If I had been more involved perhaps those feature requests could have been avoided. Schedules met. I’m now much more involved with customer interface. Then again, I sort of sounds like a father in a candy store: “No. No. No. You can’t have that. Why do you really want that? No. No. No…”
- Benchmarking. Without quantifiable proof presented many things were claimed about the code by previous developers. Instead of benchmarking I accepted these statements as truth. I optimized accordingly and spent quite a lot of time making hideous code in the pursuit of speed. Then I bench marked like I should have done in the first place. I discovered where the bottlenecks really were to be found and then improved upon them. Again, time wasted on the wrong portions not to mention I’m also stuck with some severely deformed bits of code that I’m ashamed bear my name.
I guess, in the end, what you get out of these things is what you learn from them. Three years later and I’m much wiser. I could be bitter or angry or frustrated but instead I feel I got a lot out of it.