Skip to content

Archive

Category: Agile Teams

I did move on to refactoring some of my stuff using TDD. Well kind of. In outline…

  1. I had a bunch of code which I wanted to redesign.
  2. This code wasn’t under test.
  3. The changes I am making are fairly drastic. No matter how hard I try, refactoring this code (versus rewriting it) is very hard.
  4. I couldn’t even write tests that would work with both versions (new and old)
  5. I’m refactoring this stuff ‘as best as I can’, knowing that I can’t avoid regressions.
  6. Once I have a half-cooked draft of the code using the new design, I write unit tests to help me finalize and validate the new code.

What would you call that. Test driven refactoring? Either way this gives me some elbow room, letting me reuse my existing code without overly tying me to the existing design. The whole process feels utterly painful at the moment, but that’s mostly because I have a release target and pushing it back is demoralizing.

It would probably feel a lot easier to just rewrite some of this stuff from scratch, with or without TDD and unit tests. Unfortunately my experience shows that there’s a huge lie factor in there. However painful, reusing old code doesn’t just mean taking onboard code that’s not shaped to work with my design. On the positive side, it forces me to look at code that actually does a job, rather than starting from airy, over-simplified abstractions.

Practical considerations

Even if you haven’t read my previous article about using/not using doubles, you may still be aware of the tradeoffs involved:

  • Using doubles means writing more test code (stubs, mainly; I haven’t found mock tools for objective C just yet). It allows covering the object under test atomically but leaves integration testing undone.
  • Using actual collaborators is typically easier if we have production grade collaborators handy and we’re confident that the code already works. Coverage isn’t atomic, so it’s like putting a foot into integration testing without altogether giving up on unit testing.

Practically the decision is made on a case basis. Some examples:

  1. If A uses B, B is easy to instantiate and I think B is correctly implemented, then I typically don’t use a double.
  2. If B is instantiated by A, then I typically don’t use a double
  3. On the other hand, if a resource is hard to instantiate, I’ll give up fairly quickly.

Either way, putting the classes under test typically involves redesign/more design. The redesign process I’m doing this for is already time consuming. So the short answer is, whatever works easiest is better, because trying to solve too many problems at once can result in a lot of confusion.

Nil stubs?

Objective C has this weird property that nil is a valid target for any function call (that call is just being ignored). So I’ve encountered a number of cases where instead of writing a stub or instantiating a collaborator, you can just use nil.

In development mode, I normally guard against passing nil using asserts. Feels like a very slippery feature that ‘lets nothing happen silently’ instead of failing safely and immediately. So I find interesting that nil has this hidden ‘testing friendly side’. I could write weird sh*t to allow nil when testing, but I feel rather worried I’ll end up with a lot of conditional compilation.

OCUnit templates in XCode

In XCode, the default class template for unit test is nice to understand how things work the first time around. It does become tedious after a while as it’s loaded with pretty much every other useless thing we don’t need. It’s pretty easy to find and edit templates from the XCode folder (take any significant code fragment and search in Finder)

Off topic

I guess ‘use whatever works’ isn’t very impressive advice. Unfortunately at the moment, ‘whatever works works for me’. If you have an inkling of what’s going on, bring your silver bullets and comment. Please don’t advise Working Effectively with Legacy Code. Like there’s a manual and you need a degree to drive a garbage truck. Just kidding, I’ll read it later.

In the meantime there is a very nice article about waste management on Wiki. Just so you know. Worrying about code metrics also seems a bit of a digression, notwithstanding I just found interesting bits here. I like code metrics.

This article mainly addresses the rest of us. If you’re not a TDD (test driven development) convert, yet your heart responds to the sirens of unit testing but you find yourself admiring the solution without cracking the nut, you may find it useful. Intermediate agile adopters may skim through as well. This isn’t a tutorial about how to write unit tests.

Key-points:

  • If you’re not in the habit of writing tests, and you can’t get into it, the best time to write tests is when your code undergoes significant or overwhelming changes.
  • Only write mocks or stubs if you find it easier than using actual classes. I know this may sound heretical or misleading. I’ll explain.

It won’t get us anywhere

Unless you start with generous faith and enthusiasm, getting started with unit testing (or worse, TDD) while hitting a new project won’t get you anywhere. My first experience with TDD and unit testing was starting with a weeny-tiny, critical yet project. Finally I put 3 or 4 classes under test (out of ~50). It was interesting but inefficient, and I also ended up doing 4 days overtime.

A unit test isn’t a footnote attached to a bug fix

The big plus with unit testing is that it forces us to design code in (usually) better ways. It doesn’t tell us how to do it. We’re left working it out, and this may turn out to be overly time consuming. Or it may piss you off and you’ll bury all the good stuff under a pile of curses.

In ‘legacy code literature’, unit tests are high on the list, along with suggestions to ‘write a test for every bug fix’. So I fix the bug and write a test and the critter won’t recur – job done. Right?

Uh-oh. The normal story is, as often as not this class isn’t even testable. It needs to be redesigned. That will affect dependencies with other classes (it is precisely because of these dependencies that the class can’t be tested), then you’ll be wanting to re-factor these other classes as well, and you’ll end up giving up, unless you actually call home and sign up for an overnight crusade. Sad but true, better designed code is less likely to break down, and easier to test.

The barbarian and the healer

The good news about badly written code is that it shouts for itself. You’ll be fed up, exhausted. You’ll be a dog that used their wise teeth gnawing a pile of skulls. And then…

You’ll be using the mace.

Maiming your code, changing, removing or invalidating methods, classes, sometimes entire packages. And then…

Well then, any good barbarian needs a healer. So after we made a mess for the good cause, we’ll be looking at the result bitterly, itching to sub-revert to whatever can-of-worms just needed a new expiration date hastily patched over it, and we’re ready for adding tests. Viz…

  • We’ve already agreed to redesign our code for the better (better code) and the worse (overtime).
  • We’ve entirely lost confidence into our codebase. Rewriting everything is a tempting (-ly dangerous) alternative and the prospect of running that code at all is simply frightening.

Am I drunk?

Some will claim that doubles (stubs, mocks, fakes… you name it) are inherently necessary when writing unit tests. I agree. Here’s why.

One foundational purpose of unit-testing is to ensure classes are well implemented.

Now let’s consider a class Acme depending on a class Foo. Suppose you write AcmeTest, carrying that dependency on Foo. Now say somebody changes Foo and AcmeTest breaks down. Well we’ve just proven that AcmeTest is testing Acme and Foo.
Among stories hailing the successes of unit testing, I’m sure you read something like ‘I made a minor change and a bunch of red lights fired up, signaling my change caused unexpected error in (apparently) totally unrelated classes’.

I’ll be surprised to hear that the guys witnessing ‘red lights in CC’ religiously used mocks or stubs. More likely, they had dependency chains ’spoiling their tests’. These ‘half baked tests’, however, are still popular with some agile practitioners (read here. Yes, here!)

The bottom line is that well designed unit tests using mocks and stubs are testing less, less safely, than half-cooked unit tests depending on actual, production caliber collaborators:

  • Tests using mocks and stubs are indeed asserting whether classes are correctly implemented. These only test interactions between classes to the extent that doubles are ‘locally faithful’ to the original. Foo can evolve independently from FooStub inasmuch as the original contract specified by Foo doesn’t change (mocks are even more flexible than stubs in this respect). Yea. Doubles are basically formal specs lying around. Like documentation, they can get out of date without anything breaking down.
  • Tests using actual collaborators are non-local. We’re not testing just the ‘object under test’. We’re testing its actual collaborators (however indirectly) along with the net sum of interactions between the object under test and the underlying subsystem. This makes it potentially harder to tell what is breaking down. Yet…

Lazy’s Good. Less isn’t more.

Consider an ideal situation (Acme.com, IT division):

  • We have enough time and discipline to maintain our tests. When a class implementation changes, we review stubs and mocks related to this class.
  • We have a ‘full featured battery of tests’. Unit tests; component tests; acceptance tests.

In this situation, the advantages of mocks and stubs hold dearly true. Since we have component tests and acceptance tests, our unit tests need validate only class implementations, not their holistic sum. Since we have enough time and discipline, our stubs and mocks never get out of date.

Now consider a workable (if-ever stressful) situation (AgileKitten.com, $5,000 registered capital):

  • We have 2% test coverage, courtesy Adjil Gik Jr (dude’s recently completely an internship with us, at least the test suite is up and running).
  • We’re 8 weeks before release as we got this over-designed product that we just blew a year of angel funding on.
  • The lead dev just decreed curfew (no leaving the office before 12pm) and the whole codebase needs to be ‘improved’.

In the workable, stressful situation, writing these stubs and mocks may just appear to be a waste of our precious time. We may end up writing mocks and/or stubs hastily and we don’t have component testing anyway, so how about writing a few of these half-cooked tests instead, since they double as integration tests?

Doing without mocks and stubs doesn’t just save time. It helps increase test coverage faster. Further, retrofitting a test using doubles likely will require more (re)design (just try with any class that instantiates its delegates). When coverage is low, we’re also likely to find collaborators are difficult to instantiate ‘in vitro’. The redesign effort involved in making it possible to instantiate collaborators without firing up the whole watchamacallit is the first step towards making these classes testable. Writing a stub won’t give you that.

Mock-ists often point out how tests written without doubles cause chain damage (lots of red lights) whenever anything breaks down. But if you’re only relying on unit tests, there are integration level errors that ‘true to form’ unit tests won’t catch. And by the way Mocks and stubs help masking dependency chains; here’s a design twist not encouraging us to modularize code.

Summary

The best time to write tests is when the shit hits the fan, and we lost confidence in our codebase. Mocks and stubs are neat, but we don’t usually need them to write tests. Half-cooked tests are easier and faster to write, providing more extensive coverage than mock-tests. True-to-form unit tests merely give the illusion of safety unless you have component testing and/or acceptance tests. By any means, write tests.

Acknowledgement and Disclaimer

This article has benefited explanations from an article written by Martin Fowler (Mocks aren’t Stubs, also quoted inline). Needless to say the views expressed in this article are mine. These views may appear radical, should be taken with a pinch of salt and merely track my slow progression up Agile Hill. Screw up your code at will, don’t blame me.

5:04 am, I’m scurrying around my desk like a mouse (rather, like a semi-bearded rat), anxious to check my task-list and count bugs.

I remember the day a manager at work suggested we might adopt a ‘rolling kanban’. No end to the task-list. Never. It sounded terrifying.

Well – I guess everybody’s different – I like the 2 week sprint. Crisp, short, but not too short. Long enough to waste half a day not really working. Not working at work is good, it makes the office a friendly place. Short enough that we need to rush a little to get done done towards the end. Neat. You got me, I like working off a small batch, enjoying a white mocha and breaking a brown sweat. I also like ticking boxes off a list, throwing lists away and making new lists.

So why aren’t we done done already?

Done done says it all. It sits high on my Agile Friends List when I’m in the office. I do like ticking’em boxes and turning a page.

On the other hand, when I’m working on my own stuff… well… The psychological cogs are somewhat different, and I even find positive aspects to leaving things just done. (half-done, you see).

  1. The illusion of speed. Aye. Codeworks is snailworks. Painfully slow. I like to half-bake something, pretend that I’m moving swiftly to the next task, then go back again. If you’re walking from Paris to Rome, you might as well dance along the way, 3 steps forward and 1 step back. You won’t arrive earlier but you might actually enjoy the trip.
  2. I won’t ship it if I don’t have it. There has to be a day when I look at my stuff and I think this is it, we have a game. And the sooner this day comes the better, because the enthusiasm of the first few days wears off all soon enough, and velocity will drop and drop and drop as deadlines swoosh by, weeks pile up and your family and friends start looking at you with generous commiseration.
    But when this day comes, I grow wings, and it really doesn’t matter that there’s another 3 to 12 weeks to go. What matters is, I’d rather it be 3 to 12 than 6 to 24 just because I’m not feeling the wind in my ears.
  3. There is a good time to read code. Working monolithically, getting features done done one by one, could mean we’re coding forward and never looking back (pending refactoring). Granted one should beat the iron while it’s hot (easier and faster), I often find it redemptory to look back at my code 2 to 6 weeks after I wrote it. At this point I can look at it more objectively, and get a feeling of how… readable and maintainable it will be 6 months later. And it’s not too late. It isn’t yet a threatening mass of nonsense that makes me feel like starting over.
  4. Sketching’s good. If I wanted to fit in every detail the day I write a feature, I’d spend less time designing and thinking about the structure of the code, and more time hacking pieces together. In theory, it’s never too late to refactor and always too early to over-design. In practice, putting water in our wine rarely hurts.

6 months after

Sharp. It’s been 6 months since the first Antistar release. I’ve just ‘cleared one of these lists’ and sneaked 24 bugs off it in the process (that is, I made a new list) – I’ll be ignoring the 24, trying at least – and worrying instead about putting some artwork together.

Then I’ll be looking at it, thinking this is it, and death-march cheerfully towards the next release.

Yay :)

A good place to start is Wikipedia’s Comparison of SVN clients. I skimmed through the list and retained a few solutions (my selection is arbitrary)

  • OS X native front ends: Cornerstone, SCPlugin (finder integration), svnX, Versions, ZigVersion
  • Java front ends: sdSVN, SmartSVN, Subversive, sventon, Syncro SVN
  • Other front ends: RapidSVN

I was rather used to TortoiseSVN. Tortoise integrates well with the windows desktop although the SVN version isn’t flawless (been quite a learning curve to understand some of what it does, and how, and why…). Never mind, tortoise isn’t available on MacOS.

Since I started developing on OS X, I used svnX. It’s free, but it’s nothing like Tortoise. XCode integrates SVN services and it’s OK to do simple operations, but it doesn’t substitute a comprehensive SVN front end.

I’m testing SmartSVN right now. It feels great compared to svnX so far. However I’m kind of missing a nice desktop integration so before I drop the buck ($79, oh my goodness) I guess SCPlugin is next on my list.

How XCode manages my files…

Working with XCode doesn’t make it intuitive to keep the actual code base neat. What really happens is like this:

  1. You create files and add them to your project.
  2. You organize your files using groups. Groups are nice in a way. The downside, however, is that without care all files end up in the same folder.
  3. You put aside files you don’t want anymore (well, yea… happens to everybody, right)
  4. The files aren’t ‘project files’ anymore, but they’re still in your project folder and still in SVN.
  5. XCode’s SVN integration keeps track of these files like anything else. So we have these ghost files in the repo and in the project director(ies), and we don’t really know where they’re coming from, what they’re doing here and if we want to keep them or not.

I feel annoyed with this situation – it’s not terribly annoying if we were only working with XCode, and that is exactly why it is annoying. I end up with scores of files that I don’t need, making checkouts heavier. I’m also having a hard time running other tools against my codebase. All the while everything looks perfectly neat inside XCode. And to perfect a rather diminishing portrait, the XCode proj. files aren’t anything easy like neat, humanly readable XML. More like porridge.

But surely that is nothing to bear with. Objective-C doesn’t even support packages anyway.

The Beauty and the Nerd

Elegance doesn’t belong to the tailor. Concluding a quick test drive, I added offense to injury as I attached both a jurassic wacom tablet and a cheap numpad to a shiny, brand new Mac Air.

So new in fact that I’m surprised I haven’t bled my fingers off the sharp edges. Not that I’m really complaining either, it’s a definite plus (to my liking) that the ’soap box’ designs inaugurated by the first iMacs have been sliding off the chart, if ever so gradually.

As I quickly discovered, my new Mac isn’t overly social. With just a couple of USB ports, a jack, (what appears to be) a card reader and no LAN connector, it clearly came back from the beautiful, wireless future.

At 1.3 kg, the 13” beastie doesn’t outweigh all competition. To compliment it with a decent freeware pack (xcode, blender etc…), I took advantage of a merry 600kb/s, sending my smaller (11”, 1.1kg), sturdier (3 USB ports, LAN, …) S101 to the rescue. This time around, you won’t be blaming me for hanging out with a portable drive.

I’m not absolutely disappointed. I can avoid having to hook the num-pad after I get hold of my 16 buttons Razer. Even the  num-pad works better with the mac than with the eeepc, although that’s sheer luck and nothing you care about unless you’re a blender user.

In conclusion I’d say it’s a cute, slim laptop with a beautiful screen, and that is exactly what held me from getting the seductively small, yet potentially unfit for purpose 11” version.

Beyond Perfection

I’m staying in Hong Kong for another day. It’s almost becoming a pilgrimage and this time I’ll even post pictures when I get a chance. One year back I was busy designing my first game and resurrecting my 3D modeling skills. This time around I took my girlfriend along and tried to make a holiday out of it. While this wasn’t altogether unsuccessful, it made me notice a couple of things:

  1. I don’t want to hang around without a computer I can code with. Yes, I can code on my eeepc and I’m interested in porting my stuff to JME, but no, that’s not bread and butter to me now.
  2. Projecting myself a couple of months in the future, I’ll have no day job to speak of and no office to commute to. Commuting isn’t great, working from home is worse. So finally it’s the prospect of being able to code somewhere else, that got me to buy an OS-X laptop. Sure, not all the time, just so I can get a breath of fresh air without idling the whole afternoon.
  3. Apple now boasts an 11” laptop. I wanted one 2 years ago and now that it’s out I have no use for it, or too much use for a bigger one.

I still found some time to do some modeling. This time I tried a different approach to organic modeling, taking advantage of the retopo Blender feature to draw a connected mesh over geometric primitives. I’ve been putting off writing about my organic modeling experiments/training since 2001 but I’m still thinking about it (sigh).

Tempting Murphy’s Law

Keeping source code in SVN is nice. Doing all the work from just one computer isn’t. So taking aside uncertainties regarding my geographic location, or my willingness to cage myself in my flat 24/24, 7/7, I had another, triflingly good reason to get another Cocoa-enabled tin. I need to duplicate my existing development environment to guard against a minor disaster. I’ve just done that, or about… Have a 1 coder team if you really have/need/want to. Don’t just keep everything in the same box forever. You and your projects will survive this box.

Write once, run on PC?

Feeling inspired, I installed Unity 3D (pending serious evaluation for at least 12 months) and Eclipse Pulsar on my new Mac. Then I realized the Nokia dev kit doesn’t seem to be running on OS-X. Oh well…

My first attempt at loading my sample 3D scene on an actual device didn’t work out too well.

I have two smartphones handy and one connection cable. Bluetooth died on my netbook long ago anyway. Both devices are 5 years old. Although my E61 is listed as Ovi compatible (the other isn’t), it doesn’t connect. Maybe I just need the right cable :)

Now that I have the Ovi suite installed, I had a quick look and… the prospect isn’t great. I hope they will understand someday that a web browser (versus native software) is just a let-down way to buy apps. So you open the Ovi suite, click on an app and expect pressing a download or buy button. Instead they fire up the default web browser. The UI and store presentation feel unpolished, like they didn’t have UI designers, or CSS enabled coders. Maybe it looks better on-device…

The Ovi suite itself seems like a half baked flash app made by a high school kid. They didn’t even manage a decent scroll bar.

I’m losing interest. And this may be the right time to explain why I’m interested after all. So why should an iPhone dev studio consider other devices?

  1. Workflow and release schedule. There are tons (literally tons) of devices out there that have nothing like the screen definition or horse power of an iPod 2nd gen. Meaning you simply can’t put as much content or smart code. Meaning low end devices are a good market for an early release. So with de-spec-ed devices available, you can release a ‘lite’ version earlier, thus abiding to ‘release early, release often’. Meaning that finally you can release a better app (benefiting early feedback etc…) on higher spec devices.
    Just from a technical point of view, java code is safer than compiled code, so even targeting comparable devices, the release cycle is bound to be shorter (that is, unless you mean to release on all and every Java enabled device at once)
  2. Not everybody will ever have an iDevice. In my company many people are carrying HTCs running Android. A (happy) few are carrying an iPhone. In the ‘real world’ around us, iPhones are visible exceptions, nothing like the norm. Now don’t tell me everybody will finally get an iPhone. Even taking aside pricing considerations, just imagine what it would be like? A mobile phone is something users carry with them. Consciously or not, their choice of a device reflects their personality as much as their means. One size fits all may be good for OSes – well that’s because an OS is something people don’t care about, as long as it works (and the more it’s like anybody else’s, the more ‘it works’).
  3. Anybody can enjoy a nice app. A quick look at the Ovi store shows that people didn’t wait for the iPhone to make mobile games (!). No matter what the store(s) may look like, there is an app market beyond iTunes, and I’m confident this market will grow, part because people see iPhone users enjoy apps on the go, part because manufacturers are making efforts to catch up.

Personally I think plurality is all good, and everybody enjoying the same thing on the same device at the same time is… terrifying. So the sooner competitors put their act together, the happier I’ll be.

But if you stay away from this s**t, I won’t blame you.

This article is about using NSLog with XCode unit testing; for a quick introduction to NSLog, follow the link.

Some programmers use traces to debug. Other programmers use breakpoints. Finally, some programmers use both.

So I wanted to trace some output while running (what formally looked like) a unit test, and I didn’t quite find my NSLog output in the console. Then I read this thread on cocoabuilder.com

Where are the traces gone?

OK, instead of [Run > Console], open [Build > Build Results]. Now, whether a build failed or succeeded, this window works like a tree and has lots of items marked green (success) or red (failed!). Pick any of these items, on the right hand side, there is an icon for ‘more details’  or ‘text output’.

Pressing this icon will display the actual console output, along with your NSLog output.

So if you have a test suite X, drill down to the ‘Run test suite X’ item and expand the text output; this will display information for the matching run, along with your NSLog output

This is a quick introduction to unit testing with XCode. This article does not provide a conceptual overview to unit testing.

As a first step. I did the following:

  1. Go to the project browser and select [ add > new file ]
  2. Select ‘objective c test case class’
  3. The file that opens immediately seems to contain a couple of tests. That, and a link to an overview document graciously provided by Apple.
  4. So I click, and read everything patiently (well, I’m planning to. I can display a lot of patience at times) (1).

One thing worth mentioning is that, up to stage 4 and notwithstanding footnote (1), this is a perfect introduction to unit testing, and a perfect approach to documentation. The IDE provides the way to get us started with what we want to do. The code hyperlinks the documentation.

Setting up a target for unit testing

Now to the point, what we want is write a test suite and, minimally (assuming we don’t have continuous integration, yet) wire it to the main project, so the test suite runs whenever we build.

  1. We need a target to run the test suite. Go to [ project > New Target > Unit Test Bundle ].
  2. Make a group to hold your test classes (Optional. We might as well dump everything, everywhere).
  3. At this point I deleted my first test class and re-created it. That’s because we need to add the test class to the test target (NOT to the main target, so uncheck that when going through the wizard) and the easy-clicky way is via the wizard, when we create a new test class.
  4. Switch the active target to Test (or whatever your test target is named)  and target the simulator (otherwise tests will skip).
  5. Press build.
  6. Press [Build]. If you haven’t modified the sample test class, this should run OK.
  7. Now modify the test class to fail a test, and press ‘Build’. This should then fail the build. If you check build errors and keep unfolding, you’ll eventually find a reference to your failed test, along with whatever you set the assert to output when the test fails.

OK, this didn’t work for me at first. In the sample test class, reassign USE_APPLICATION_UNIT_TEST to zero. USE_APPLICATION_UNIT_TEST doesn’t seem to be for unit tests; this is for tests that require your application (or some other GUI, not sure… ) to be running while you test.

NOTE: I have somehow gotten into the habit of stripping #import <Foundation/Foundation.h> off my .h files. Well. If you’re doing this, you’ll get errors when trying to compile your project classes to the test target. You need to add the project’s precompiled header (*.pch) to the build configuration for the test target (see below).

Running tests every time you build the main project

Now, this is trivial and elegant at once. To ensure we pass the tests before even thinking about running our app, all we need to do is drag the test target inside the main target.

Next time we build (targeting the simulator) test classes compile and run before actually running our app. If the tests fail, nothing runs until we fix the tests :)

Troubleshooting

There are three practical issues that tend to occur when trying to put legacy code under unit test with XCode. In whatever case this results in stupidly broken builds.

  1. Most of your existing source files are missing from the Test target.
    => expand the main target for your project; expand the test target; now select Compile Sources in your main target. select all files in the Compile Sources group (do it from the top right panel) and drag them into Compile Sources in the test target.
  2. Frameworks in use  are missing from the test target.
    => use the same approach as in (1). This time, duplicate content from Link Binary with Libraries.
  3. The precompiled header (.pch file) isn’t applied to the test target.
    1. Right click on the main target and choose ‘get info’.
    2. Select the build tab.
    3. Under Configuration: (top left) pick All Configurations
    4. Scroll down until you find the ‘Prefix header’ entry in the ‘GCC 2.2 – Language’ section. Copy the pch path/name and duplicate it to your Test target settings.

(1) At this stage, not everything being as perfect as it ought to be, I bothered popping a mail window and sending the link to myself. I wished I had an iPad icon on my desktop and could just drag the safari window to it – or the link. Yea. Kiss the future.

Today I watched Julie and Julia (or vice-versa) and I couldn’t help but get sympathetic to a feel-good movie about the ups, downs and hazards of a wacky personal project. That appropriately reminded me too, that I seemingly never set a hard deadline on my game project. As Brookes quoted:

Good cooking takes time. If you are made to wait, it is to serve you better, and to please you. [The Mythical Man Month p. 13 - originally: Menu of Restaurant Antoine, New Orleans.]

I won’t get into explaining how you cook-up a 12 hours pork stew, or why giving estimates for product delivery is pure technical arrogance facing money-wise operational goals. I’ve been dragging along (not always speed-jetting) carrying a mix of anxiety and anticipation, while clinging to ‘deliver often, deliver early’ as a mantra better than worth repeating every day.

‘Deliver often, deliver early’ could only mean either of two things in my case:

  • Make a small product ‘just for the sake of it’.
    I clearly missed several opportunities in this area; in part because I’d done two small prototypes (A flash-card thing for chinese and a nicely animated icon matching game) and couldn’t see how this could either make money or, more importantly, drive the development of something more ambitious); in part because instead of starting making/learning/porting a 3D engine (a concrete, pragmatic move towards making a game), I wrote an (optional) behavior scripting system that merely implied the many components needed in a finished product.
  • Define a ‘minimally marketable’ design for my product, and stick to it.
    On this side I’ve been more constant. While there’s a couple of non essential features that won’t make their way into the first release, I clearly anticipated early on what I needed to make my game usable, and keep it ‘minimally fun’.

Unsurprisingly, I didn’t start getting any good feedback from my casual play testers until I managed to tick all the boxes off ‘minimally playable and fun’. And now I do. I hear that my game is… …playable and fun.

OK, I lied. What it feels more like is, I’ve been working on this huge pile of cool stuff, until the day I patched it all together, only to realize it was neither playable, nor fun. I could have released a fun, playable game maybe 3 months ago. What’s true, however, is that that game wouldn’t have been as good as my prototype is now, because most of the cool stuff is making its way into the final product.

For the record, here’s a few things that aren’t needed to make a fun, playable 3D game, but still nice to have. In other words, the things that you might leave out if you need to release and make money ASAP:

  • Support for exporting animations (you could make a space shooter instead, or whatever…).
  • Procedural grass.
  • Lighting (ever played Katamari on your iTouch?)
  • Behavior scripting
  • Cool camera management
  • Modeling (or procedurally generating) natural landscapes

‘By the way, maybe you should check what seems like an interesting article temptatively rooting Agile into Brookes’ book.

One more thing. Coding is nothing like cooking. Cooking may take 6 hours. Cooking may take a day. But cooking’s just cooking. Coding up stuff takes ages.

Plus, cooking is a healthy activity where you get to stand, scurry and scour the local markets for fresh veg, meat and fish. My back is half-killing me.

…and we’re back!

Here’s two contradictory propositions about test first development (TFD):

  1. TFD helps you to design your software better.
  2. TFD should not change the way you design your software.

At the moment I’m still designing a library for intermediate level developers. Static members, for all the bad they are, often make my programming life simpler without jeopardizing the future of my code altogether, so I guess among intermediate developers some will feel my pain better than I do, and develop a negative understanding of the following, short sighted truths if I do not provide static methods as part of the kit:

  • Factory methods are a good alternative to constructors when constructors are not available (minor)
  • Where one, and one only, instance of a service is, for the foreseeable future, desirable, static methods avoid burdening oneself, or other developers, with the need to bounce a singleton around a software system (major).

As a quick reminder or introduction, here’s why TFD (among several other, theoretical and formal, protagonists) doesn’t like static members:

  1. A unit test is validating a class. This is done to ensure that the object will behave as expected, so that, if this object appears to misbehave in some way, you can rely on the unit test failing or passing to tell you either yes, the object is misbehaving, or no, the object is mis-informed – interacting with something else, and that thing must be broken.
  2. A static member is a member that you cannot, in many languages, replace by a stub. That means that you can’t isolate the behavior of A, using static member S, from the behavior of the system {A,S}.
  3. Since we can’t easily tell whether A or S or {A,S} is failing when A appears to fail, the unit test for A is imperfect. More importantly, {A,S} is harder to maintain.
  4. Ergo, static members are undesirable.

As an API designer, what should I do? Well maybe I’ll change my mind later, but for now, here is how I feel about it:

  1. If I were designing an API for experienced developers, I would most likely avoid statics. I couldn’t use them anyway because the use of static members would taint my API. Not all experienced developers have a deep grasp of why statics might be bad. This is not how humans learn. Most experienced developers feel that static members are bad. This is what developers learn.
  2. Since I am designing an API for intermediate developers, I may be ill inspired not to provide them with convenient static functions. In fact I should wonder whether my static functions are a poor substitute for globals.
  3. I need software written using my libraries to be unit-testable.
  4. Ergo, I shall have to write a stub version of my libraries – an empty shell containing all classes and function signatures in my libraries. This way developers can unit test software written using my library, and enjoy readily available stubs providing support for testing (e.g., logging API calls)

I find the ‘case of untestable static members’ delectable. I may be more against static members that many developers are, but today I’ve been the devil’s advocate, so I’m just about to turn my jacket but…

…not in this post.