Working with your Level-Up Cycle

The Level-Up Cycle in diagram form

A representation of how we acquire new skills

In Part 1 of this post I gave you a damn good excuse to play facebook games in order to get acquainted with your Level-Up Cycle – a process of acquiring new skills where we move from awareness of a possible new behaviour, through the intention to implement that behaviour, spend some time gathering feedback in conscious practice, initially disruptive before becoming integrated, and then – the magic moment – we Level-Up and what was once the idea of a possible new behaviour is a habitual unconscious practice.

Great games – Tony Hawk Skateboarding is my favourite example – allow us to progress from novice to expert without ever really feeling like we’re ‘being skooled’. What can we emulate about how a good game stimulates learning, that we can put into practice as programmers?

Creating the (small enough) Stimulus

There are obvious macro stimuli – books, blogs, screencasts, conferences, but in many cases these are almost equivalent to a whole game. How can we create the kind of micro-stimulus that game designers use to tease out new skills that prepare us for the end-of-level boss?

I think the ideal stimulus is something tiny (and not progress blocking or bug-related because that encourages those tiger-awareness chemicals) that we can feed into the Level-Up Cycle repeatedly until we get a serious boost in our performance, or we conclude that this is not a fruitful new approach.

My current micro-stimulus is this kind of code:

So – just banal conditionals guarding against simple corner cases such null. Sure, they work, and I’ve isolated those conditionals in helper functions, but I’ve gradually developed awareness that they can often be indicators that there’s a better way. And I’ve got an active intention to act on this situation – I don’t do it every time, but I try to make time to do it as part of regular refactoring.

So, I grabbed my first idea for a possible refactor – the NullObject pattern – and dived into some conscious practice – very much disruptive at this stage!

The implementation here is that the player has to choose a set of options. Some options either enable or disable another option – hence these enables and disables values can be another option, or they can be null. To avoid a Null Pointer Error, we don’t want to call the enable function on null.

So – that’s ok, we can just create a safe NullObject implementation of the IBudgetGameOption:

So I started to create my NullBudgetGameOption, but I quickly hit a problem…

What should get selectedSignal and get deselectedSignal return?

If they return null, they risk being the cause of a difficult to diagnose Null Pointer Error – when someone tries to add a handler to the Signal.

I hate those pesky Null Pointer Errors. If something is going to throw-up in my application, I want it to puke something nice and specific so that I can instantly diagnose the problem. So my first thought was to make these getters throw a NullObjectUseError that would make it straightforward to pick up.

I actually wrote all the code to implement this, but I could hear my complexity-dar pinging. It kept telling me that this broke the pattern. I’ve never come across this problem when using NullObjects before.

So I did the obvious thing – I asked the tweeks:

Twitter-geeks: When you use the NullObject pattern, do you throw Errors from invalid getters? eg For the Signals on this iFace. #flashdev
[@stray_and_ruby Jan 29 10:58am]

And because the twitter geeks are magic and generous, I got two near-instant replies:

@stray_and_ruby Isn’t point of Null Object Pattern to avoid throwing exceptions? Shld return implementation of interface that does nothing
[@DavidArno Jan 29 11:11am]
@stray_and_ruby isn’t the purpose of a NullObject to dodge errors and exceptions (like null reference)? Would be weird if it throws one imo
[@SlevinBE Jan 29 11:29am]

And of course they’re right. Totally right… so what does that mean? Does it mean that you can’t use a NullObject to stand in for an interface that has getters at all? Or only sometimes?

In the end it turns out that this is a classic case of interface overloading. I still feel that this is the weakest area of my programming – working out exactly what interfaces to build to, how to break them down, when to extend in the interface and when just to implement multiple interfaces.

The object returned by the enables and disables function only needs to be available to enable or disable. It doesn’t need to offer Signals for selection, or even the selected and deselected API.

So we can refactor enables and disables getters on the BudgetGameOptionVO to return a new simpler interface:

The original yukky conditionals can go, the IBudgetGameOption can extend this IDisableable interface, and the NullObject no longer has error issues:

I also learned a truth (I think):

If an interface represents an Object which might be replaceable with NullObject, it shouldn’t contain getters for complex classes unless they also deserve a NullObject implementation (which is unlikely).

Now I have a new intention to ask this ‘could you be null?’ question of my classes and interfaces, and use it to try to make better decisions about how to split and compose those interfaces. One day maybe I will have forgotten how I acquired this knowledge, and it will just be ‘obvious’ to me, but I think I need a lot more conscious practice before that happens.

Achievement unlocked: interfaces level 2

I feel like I’m on my way and I definitely just raised my game on my understanding of the benefits of the ‘need to know’ interface.

I haven’t totally Levelled-Up on eliminating naughty conditionals yet, but some of my practice at removing conditionals has started to become habit – for example, using the Mario Mushroom Operator ||= for lazy instantiation inside my classes. And I’m getting enough warm and fuzzy feedback that I’m motivated to keep experimenting.

It’s an open-ended game

You probably noticed that I’m returning Signal and not ISignal in my getters – this is not good, though at least it meant I didn’t disappear down the path of creating NullSignal to overcome it. The main reason for this is simply that the AS3 Signals interfaces have been in a state of flux over recent weeks and I’ve been caught out by the changes a couple of times, so using the concrete type has been more practical. Signals is still a 0.x release and the fact that the super-talented crew working on Signals have taken several shots to find the perfect interface configuration makes me feel a bit better about how tricky I find it.

Don’t forget to look backwards

Of course the really lovely thing about when we Level-Up is that often it happens without us noticing. By definition it’s a process of moving out of conscious behaviour, so it’s worth taking time every once in a while to see how far we’ve come. We can only do this by reflecting on where we’ve been – so I always take it as a good sign when the code I wrote months or years ago makes me cringe.

About the Author

I'm an actionscript programmer living and working in a tiny village in the Yorkshire Dales, UK. I used to be a TV reporter, but my inner (and often outer) geek won. I also write stuff. Most recently Head First 2D Geometry.

Visit Stray's Website

Share the post

Delicious It Digg this! Stumble this! Share on Reddit Share on Buzz Share on FriendFeed