Clean Code

I’ve been programming for along time now. My first program was probably back in 5th or 6th grade when I had to get checked off on basic computer skills in elementary school. I think they were pretty progressive for 1989. It would have been as BASIC program on an Apple II and gone something like this:

10 PRINT "Hello!"
20 GOTO 10

I got into this seriously in 8th grade programming games in BASIC on the TRS-80s in the typing lab. Then moved though various lanauges (QuickBasic, Pascal, C++, Lingo, Javascript, ActionScript 0, 1 and 2) before landing where I currently am: an ActionScript 3 developer working with the Flash Platform.

Throughout all of this, I really just concentrated on syntax of the language and getting stuff done. But two years ago, I started using design patterns and looking beyond the code into the technique 9or craft) of coding. And in the past few weeks, I’ve really started thinking seriously about how bad I code and how want to code. In my freshman year of college, my first English assignment was a required paper titled: “My Writing Sucks and And Why.” Now I’m doing this mentally.

I picked up a copy of the excellent Clean Code by Robert C. Martin and have just started to read it. A few weeks from now, I fully intent to be a better programmer and look back on the code that I’ll write today and think: “What the hell was I thinking?!”

Note, I’d consider ActionScript 0 to be what ever the hell we were writing for frame scripts in Flash 4. That was painful.

On using SWCs …

So I’m pretty late to this party. Up until now, I’ve been using 2 methods for sharing assets on my Flash projects:

    1. An assets proxy that a coworker of mine wrote.
    2. Nothing. Ok this doesn’t count.

The assets proxy loads a SWF file and view elements can pull assets from it like

assetsProxy["linkageID"];

Can it get easier? This does a great job of separating content from code in a reusable way and keeping the main app SWF small, however, you have to wait for the assets SWF to load. And write a lot of boilerplate code to set it up, start it loading and listening/responding to the loaded event.

So what’s another way? Enter the SWC. ActiveTuts has a great tutorial on how to create and use them.

My scenario: I have a collection of learning interactions that have a lot of little clips in the libraries. Many of these are the same across interactions and really should be shared in some way. A lot of them also have class files associated with them since they need a little more functionality than a basis extended Sprite.

These classes were mixed in with my project classes and this created a special case with using a SWC: You have to set it up so that the classes are imported from the SWC instead of the class file in the project folder. It took me a few hours to figure this out – classes specific to assets in your SWC file must not be in the class path of the project file.

So I created a separate directory for all classes needed for my assets SWC and it all started working. For now, I just dumped it all in the lib folder because I can’t think of a better place. The project classes are safely in the src folder, nice and separate.

With this SWC linked in FDT and the SWC added to the library path of the FLA this is a quick snip of my code:

package screen
{
	// this class is in the SWC, need to import
	import assets.view.WheelList.WheelListItemSprite;

	// stuff

	private function drawList():void
	{
		// stuff
		var item:WheelListItemSprite = new WheelListItemSprite();
		// stuff
	}
}

The library of my interaction FLA went from over 10 clips to none. And they're all separated and ready for reuse in other interactions.

Nori Bindable Model

Here’s the super simple bindable model class that I’ve created for Nori. I’ve never actually developed a project with Flex, but I really like the idea behind it’s data binding implementation. I tried to create something similar for Flash/AS3.

package com.nudoru.nori.model 
{
	import flash.utils.Dictionary;
	import org.osflash.signals.Signal;
	import com.nudoru.nori.model.bind.PropertyChangedVO;

	/**
	 * Adds data binding functionality to the abstract model
	 * Usage:
	 * 
	 * 	To set up a property to be bound:
	 * 		public function set bind_prop(value:String):void
	 * 		{
	 * 			bind_prop_field = value;
	 * 			dispatchPropertyChange("bind_prop", bind_prop_field [, old_value]);		// this is the important line
	 * 		}
	 * 	
	 * 	To bind the property:
	 * 		bindable_model.bindProperty("bind_prop", binding_listener_function);	
	 * 		bindable_model.bindtest = "hello!";
	 * 	
	 * 	The binding_listener_function may any function and as long as it takes the new property value as an argument
	 * 
	 * This class should be subclassed to create more enhanced functionality.
	 */
	public class BindableModel extends AbstractModel implements IBindableModel
	{	

		/**
		 * Signal for simple binding
		 */
		protected var _onPropertyChangeSignal	:Signal = new Signal(PropertyChangedVO);

		/**
		 * Map of the bindings
		 */
		protected var _bindingMap				:Dictionary = new Dictionary(true);

		public function get onPropertyChangeSignal():Signal
		{
			return _onPropertyChangeSignal;
		}

		/**
		 * Binds a function to a property name
		 * @param propName Name of the property
		 * @param setter Function to call when the property changes. Must take the property's value as a param
		 * @param overwrite Will remove existing setters and assign a new one
		 */
		public function bindProperty(propName:String, setter:Function, overwrite:Boolean = false):void
		{
			if(overwrite) unbind(propName);
			
			if(!isPropertyBound(propName))
			{
				_bindingMap[propName] = setter;
			}
			// if the signal doesn't have any listeners yet, set it up
			if(onPropertyChangeSignal.numListeners < 1)
			{
				onPropertyChangeSignal.add(handlePropertyChanged);
			}
		}

		/**
		 * Remove the bindings for a property
		 */
		public function unbind(propName:String):void
		{
			if(isPropertyBound(propName))
			{
				delete _bindingMap[propName];
			}
		}

		/**
		 * Determins if the property is bound to anything
		 */
		protected function isPropertyBound(propName:String):Boolean
		{
			return (_bindingMap[propName]) ? true : false;
		}

		/**
		 * Called from a setter to notify bindings of a change to the value
		 */
		protected function dispatchPropertyChange(name:String, value:*, oldvalue:*=undefined):void
		{
			if(isPropertyBound(name))
			{
				var vo:PropertyChangedVO = new PropertyChangedVO(name, value, oldvalue);
				onPropertyChangeSignal.dispatch(vo);	
			}
			
		}

		/**
		 * Listener for the onPropertyChangeSignal signal and notifys bound setter
		 */
		protected function handlePropertyChanged(changeObject:PropertyChangedVO):void
		{
			if(isPropertyBound(changeObject.name))
			{
				var func:Function = _bindingMap[changeObject.name]as Function;
				func.call(this, changeObject.value);
			}
		}

		/**
		 * Construtor
		 */
		public function BindableModel() 
		{
			super();
		}

	}
}

Nori Framework

Lately, I’ve been into learning new things – one of them has been to find out what IOC (Inversion of Control) and DI (Dependency Injection) is all about. As a working project for this, I’ve taken the Cairngorm based framework that I created at work and started to do a major rewrite around IOC. I’m basing most of it on Robotlegs.
Not much to say right now, but I’ll toss up information about it and informative links that I’ve found soon.

Social sim. engine, Part 3 – Progress!

Thanks to a wonderful confluence of events and great timing, I’m able to turn this in to a project for work – there are a handful of solutions in the queue that can use this starting next month – so I’m working full time on it over the month of Feburay.

After a few days, this is what I’ve got: click. It’s a pretty straight forward scenario, but it demonstrates all of the features that I’ve got working.

I’ve been able to keep up with my “play” metaphor and it’s working out great by providing many more opportunities for gaming rather than typical multiple choice branching.

One of the projects brought up a requirement that started a new idea – an inventory system. All I really need to do is allow the learner to reference a screen shot to get some data, but I think it can be taken farther. But more on that later.

Created a few learning interactions today

When I started Ramen, one of the goals was to allow the page templates/interactions to be used outside of the system – in a Lectora course for example. This has even become more important as my day job standardizes on Lectora as the shell for any tracked learning content. Over the past year, I’ve been able to write a whole lot of really easy to use APIs for creating learning interactions. Creating a new interaction takes just a few hours using the Ramen page template API and borrowing functionality from existing templates.

The biggest benefit of this is quick and easy reusability. Just change the XML file and it’s a new page. I don’t want to even think about how hard  some of these would be to pull of in Lectora. It gets really confusing when the action icons start to pile up.

I’m helping out on a project now that needs a few learning interactions developed – quickly. So I spent today working on these. Here they are in the Ramen player:

These aren’t the fanciest interactions ever created, but not bad for a few hours work.

Adding any old library object to a display list

Ok, so you know this used to be pretty straightforward in AS2:

var mc:MovieClip = attachMovie(linkageid, newname, depth);

By in AS3, all of you linked library objects are now classes, so you need to do this with the class name:

var mc:Thingy = new Thingy();

What if you want to attach any random movieclip at runtime but you don’t know what class it will be ahead of time. Maybe its driven by an external data source? You could have a nice if/else or switch block and call the class based on a variable, but that’s a pain in the ass.

So, here is a function that I came up with to make it easier:

function getArbitraryLibraryObject(n:String):Object {
var objC:Class = Class(this.loaderInfo.applicationDomain.getDefinition(n));
var obj:Object = Object(new objC());
return obj;
}
var mc:MovieClip  = getArbitraryLibraryObject(linkage) as MovieClip;

Let me know if there’s an easier way to go about it, but I haven’t run across one.

In my Ramen player, I’m using this to call sound effects and page to page transition effects.