I’m building an application which I’ll talk more about later – but this one’s different from other applications I’ve built: this one’s for me. In the same way teaching your spouse/significant other how to do X is a major pain in the ass, building your own application makes you do dumb, silly things (I think Jeff Atwood might be able to back me up on this one…). This, friends, is a story of my pain to ease your Monday blues.
Starting Out Seemed So Simple…
I had an idea, and the idea was good. So I decided to build an application around this idea and I got together the various tools and things that I thought I would need. I played with the idea of using Rails (for a change – why not), but then a curious thing happened: my inner Type 1 Ass-kicker decided to wake up:
This aint no disco butthead. Build using something you know, stop dicking around!
He’s a real dick – that inner Type 1 Ass-kicker (we’ll call him Bad Rob) and if I don’t listen to him – or at least make him *think* I’m listening to him, well things will just get ugly.
I ditched my Rails musings and plowed ahead with ASP.NET MVC. I grabbed my favorite testing tools, updated jQuery with my favorite plugins, and I was off to the races. With one exception – I snuck in a last-minute substitution while Bad Rob wasn’t looking: DB4O. Here are the tools I went with:
- ASP.NET MVC 1.0
- Machine.Specifications (BDD testing stuff)
- XUnit (love u Brad!)
- jQuery UI – full suite, ajaxForm plugin, validation plugin
- DB4O – just because.
I’ve written about using DB4O before – I love the thing. Persistence made easy! I kicked up VS and got ready to roll…
Good Rob, Bad Rob
That’s when the fun started. See, Good Rob (the guy who likes to write tests *first*, the guy who tries to vet just WTF he’s going to do and why) would have sat down and cranked out some specs against some type of iteration and time plan. Then maybe tied everything to a nice build server (which is purring away at my webhost) and… yadda yadda yadda.
Whatever Nancy-boy, it’s not like you’re getting paid to dick around here and no one’s gonna see your code! This site needs to go LIVE so get ON IT. Yah testing is fun – test whatever you want – AFTER YOU’RE DONE.
And there it is: business vs. process. The best part is that this Fight Club dialog is taking place right inside my skull, and Bad Rob is playing on my fear of “getting something done” while Good Rob wants to do it right.
Yikes. Dueling success metrics (such a lovely corporate term): “results” vs. “quality”.
Yes, this kind of thing is common – in fact it’s expected – in every
software project ever undertaken. It doesn’t matter the company and in fact it happened to me at Microsoft. I was working with a team right after I started and I was about a week into the work when we had a team meeting and I was asked to “give a demo”.
“I don’t really … umm… have anything to show… oh wait yah I do – take a look at my test results so far.”
And the room erupted into laughter. “Nice! We don’t have an app but we can show our users some great test results!”
Granted – they were teasing me. All the same I couldn’t help feel that the expectation was that I needed to Show Something. Next time I’m in that situation I’ll be smarter and bring some HTML mockups – either that or Balsamiq.
Good Rob Loses
As always, time is short when doing these things. Bad Rob was continuously reminding me that I needed to get this thing done and out and I gave in to the pressure. It really sucks to give in like this, but Bad Rob can be awfully, awfully convincing.
So I appeased him – I wrote the app quickly and cranked out the initial spec, and the decided I would back everything up with a set of tests. I really, really like the BDD approach so I started with that, and I gave myself 3 hours to write as many tests (errrr specs) as I could.
And then all hell broke loose.
I wish I could surround the following paragraph in glitter and flashing lights, because it’s something that I had forgotten by being “out of the mix” for a few years. I was surprised at myself – so much so that Bad Rob started to panic and got really pissed off at Good Rob for writing “such crappy code”. Here’s what happened:
- In my haste to write said application, I managed to goof up one of the main specs. I thought I was doing it right, but…
- When I started to write my tests I realized this error, and I started to fix it. This “fix” led to me refactoring a lot of “slop” that I had left until later – the “technical debt” if you will that I figured I’d refactor when I was testing.
- The slop started to build, and the refactoring started to spiral. I was fixing things that I knew I shouldn’t have done – things I would have dealt with properly had I slowed down. Next thing you know the entire app was in pieces on the floor…
- Including my tests. I had about 50 or so written and now I was commenting out my tests liberally – they were invalid and I felt really dumb for writing them in the first place without using them to validate the code I was going to write!
What was supposed to be a 3-hour fun session of writing tests turned into much more and ended with a shouting match between Good Rob and Bad Rob, with Good Rob threatening that he was “going to BLOG THIS” (looks like he went ahead and did that…).
Back On Track
I wasted hours and hours retro-fitting my little application and stuffing Bad Rob back into his id-box. As I say I knew better, but feel prey to the “we need it NOW” bomb that Bad Rob kept lighting off.
What I should have done was this:
- Use Tools you know. I like DB4O a lot – and it worked perfectly as a testing “Fake”. I ran into some problems with it (which I’ll talk about later) and what I should have done was go with something I know.
- Write out your specs. I should have written out the specs and behaviors of my app and formalized it into a testing suite. At least 20 or so to get going. Adjustments are easy and reading the behaviors crystallizes WTF you are doing in the first place. If you’re not a BDD fan – then write your tests in “comment form” – just to get the ideas down.
- Have some damn discipline. I know I’ll need ViewModels to handle complex UI logic, I know I’ll need Service classes to handle specialized domain logic as well. I’ve built this application many, many times before – I know what’s out there. Yes – YAGNI and all but in terms of structure, there is arm-waving and then there’s reality. These things I know.
What I ended up doing was:
- Moving to SubSonic. I know it like the back of my hand and the SimpleRepository fit the bill nicely. I was also able to add some cool features in (which I’ll talk about later). DB4O is great, but if I’m really in a hurry then I need to stick with what I can make sing.
- Stopping everything and specc’ing (how the hell do you spell that word?) out every last element of what I was building while thinking it through from end to end.
- Write code *only* when you have a mandate to do so. Yah I’m a smart guy and yes, I can juggle things in my head – I’ve been doing this for a long time. I was wrong, however, when I started to assume.
- Stopped worrying about domain names and CSS and didn’t look at the web app for the rest of the day.
The Score Card
For those of you who don’t think “qualitatively” – here’s the breakdown on lost time:
- I had a 40% loss on rewriting existing tests
- a 25% loss on refactoring things the way they should have been done in the first place (using Services, View Models, etc)
- a 40% loss on removing DB4O and going with SubSonic. Caveat: I didn’t *need* to do this but I had a gut feeling.
- a 30% loss on restructuring my repository to be less DB4O-specific (using Add/Update methods, removing Flush/Commit). This was dumb.
Overall I would have been 1/3 ahead had I “done things right” – or more appropriately I would have finished in 2/3 of the time. That’s a lot of time!
The only reason I got so derailed is because I have a major stake in this thing’s outcome. I can forgive myself – just this once – for getting carried away and I’m happy that the damage wasn’t too great.
Bad Rob is happy that the app works and it’s lighter and more nimble than before. Good Rob is happy because his assumptions are covered and he can see the light at the end of the tunnel.